jetson nano|折腾日志

一、jetson nano 风扇降温

2020-5-10 0:23 风雨敲窗棂
在*鱼上入手了一个二手jetson nano,这篇的故事就开始了。

  • jetson nano 600RMB *鱼
  • 调速风扇 15RMB *宝
  • 无线网卡 79RMB *宝

1. 手动设定风扇转速终端命令

  • 全速
sudo sh -c 'echo 255 > /sys/devices/pwm-fan/target_pwm'
  • 停止(注意,是从当前速度缓慢降到0,减速过程为1分钟)
sudo sh -c 'echo 20 > /sys/devices/pwm-fan/target_pwm'

2. 根据CPU温度自动调节风扇转速

注意:以下程序的条件可根据需要自行更改。

# 源地址:https://blog.csdn.net/bornfree5511/article/details/103076414
#!/usr/bin/python
#~/fan_control.py
import time
 
while True:
    fo = open("/sys/class/thermal/thermal_zone0/temp","r")
#thermal_zone1是cpu的温度,thermal_zone2是gpu的温度,thermal_zone0的温度一直是最高的,可能
#是封装的温度,可用jtop查看具体的信息
    thermal = int(fo.read(10))
    fo.close()
 
    thermal = thermal / 1000
    
    if thermal < 30: 
        thermal = 0
    elif thermal >= 30 and thermal < 70:
        thermal = thermal - 30
    else:
        thermal = thermal
 
 
    thermal = str(thermal)
    print thermal
 
    fw=open("/sys/devices/pwm-fan/target_pwm","w")
    fw.write(thermal)
    fw.close()
 
    time.sleep(60)

3. 开机自启动

设置jupyter开机自启动请参照:让Jupyter Lab在Jetson Nano上自动启动
参照ubuntu实现python脚本后台运行+开机自启

1.建立rc-local.service文件

sudo gedit /etc/systemd/system/rc-local.service

2.将下列内容替换rc-local.service文件

[Unit]
Description=/etc/rc.local Compatibility
ConditionPathExists=/etc/rc.local
 
[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99
 
[Install]
WantedBy=multi-user.target

3.创建文件rc.local

sudo gedit /etc/rc.local

4.将下列内容复制进rc.local文件

#!/bin/sh -e
# rc.local
nohup sudo python ~/fan_control.py > /usr/local/out.log 2>&1 &
exit 0

5.Ubuntu系统 sudo指令免密码

sudo gedit /etc/sudoers

%sudo ALL=(ALL:ALL) ALL 修改为%sudo ALL=(ALL) NOPASSWD:ALL

请仔细操作!
6.给rc.local加上权限

sudo chmod +x /etc/rc.local

7.启用服务

sudo systemctl enable rc-local

8.启动服务并检查状态

sudo systemctl start rc-local.service
sudo systemctl status rc-local.service

9.重启并检查是否成功

reboot

如果风扇自动转了起来,说明成功。

二、I2C总线之OLED屏显示

1. jetracer扩展板+电池套餐(255RMB)

在某宝上找到基于jetson nano的小车,有两款:1)jetbot;2)jetracer。jetbot利用差速驱动转向,jetracer则是迷你版的无人车(几何运动学模型为阿克曼轮转向模型)。后者是我想要的。jetracer很好,唯一不足的是,电机不带编码器,在之后的功能上有所缺失(无法得到较准确的里程计信息)。于是:我只购买了jetracer扩展板、锂电池组。

在这里插入图片描述

2. I2C总线

jetson nano总共有2组I2C总线,分别为(I2C BUS 1: 3,5)(I2C BUS 2: 27,28)。I2C总线的引脚在J41,也即那两排密集的引脚区。
在这里插入图片描述
查看总线1的设备

sudo i2cdetect -y -r 1

在这里插入图片描述
其中,3c就是OLED的I2C设备地址。

3. OLED显示

由于jetracer扩展板上使用的是SSD1306的0.91inch OLED屏幕,所以需要先安装Adafruit_SSD1306

sudo pip3 install Adafruit_SSD1306

由于OLED显示的示例程序在jetbot上,所以先安装jetbot.

git clone https://github.com/NVIDIA-AI-IOT/jetbot.git
cd jetbot
python3 setup.py build
sudo python3 setup.py install --record jetbot.uninstall.txt

如果需要卸载jetbot,可以在jetbot根目录下执行:

sudo cat jetbot.uninstall.txt | sudo xargs rm -rf

所以,最好保留jetbot.uninstall.txt文件。

运行程序:

cd jetbot/jetbot/apps/
sudo python3 stats.py

会看到OLED显示了以太网,wlan,内存与存储等信息。
在这里插入图片描述

三、小车底盘与控制

1. 阿克曼转向小车底盘(209RMB)

由于jetracer与jetbot可扩展性很差,(不带mpu,不带电机编码)。jetbot是用差速控制,是用简单的TT马达,不带编码器。jetracer是用转向舵机控制方向,但是后面两个电机也不带编码器。因此,不考虑jetbot与jetracer的底盘。

在另一家店里挑了一款不带控制器的迷你小车(带编码的电机,舵机)。那家店里,也有带控制器的(买来直接能用游戏手柄控制运动的那种)。由于,车本来就很小,211 x 191 x 65mm。如果系统用两个计算板子,车体肯定很臃肿。我想把所有的全集中在jetson nano上,就像jetracer一样。在这里插入图片描述

底层与ROS串口通讯协议

位数 十六进制 ASCII码
1 0x7B {
2 0x2D或0x2B -或+
3 0x30~0x39 0~9
4 0x30~0x39 0~9
5 0x30~0x39 0~9
6 0x30~0x39 0~9
7 0x2D或0x2B -或+
8 0x30~0x39 0~9
9 0x30~0x39 0~9
10 0x30~0x39 0~9
11 0x30~0x39 0~9
12 0x7D }

例如,我发送{+3000-0100},表示速度期望值为3000/100,角度期望值为-100/100。

2. DC Motor+Stepper FeatherWing (45RMB)

jetracer扩展板上的PCA9686只引出两个通道,其中一个通道用于控制转向舵机,而后面两个电机则共用一个通道。在实际测试中,即使用同一个信号控制,两个电机的转速是不一样的,这次上电是左边的快些,下次上电可能就是右边的快些。如果左右两个电机速度无法可控的保持一致,那么实际运行中,我们无法很好的控制小车按预定的轨迹行驶。更多讨论请参看2个直流电机速度不一样,小车走直线总是偏,怎么解决?

唯一的解决方法就是:左右电机单独控制,利用PID调速到相同转速。然而,但是,但是,然而。。。jetracer扩展板上的左右电机共用一个控制通道。问了客服,除非更改硬件电路。。。

于是各种查找方案,找到下图所示的DC Motor+Stepper FeatherWing。
在这里插入图片描述
管脚说明

在这里插入图片描述
凑巧的是,它就是jetbot官方版本(非微雪版)采用的马达控制板(也可以驱动其他型号的电机)。下面的图更直接明了。
在这里插入图片描述

连线方式:
MPU6050 jetson nano
VCC — 5v
GND — GND
SCL — 28
SDL — 27
(28, 27)表示I2C bus0

MPU6050的设备地址为0x68

程序代码:

import atexit
from Adafruit_MotorHAT import Adafruit_MotorHAT
import traitlets
from traitlets.config.configurable import Configurable


class Motor(Configurable):

    value = traitlets.Float()
    
    # config
    alpha = traitlets.Float(default_value=1.0).tag(config=True)
    beta = traitlets.Float(default_value=0.0).tag(config=True)

    def __init__(self, driver, channel, *args, **kwargs):
        super(Motor, self).__init__(*args, **kwargs)  # initializes traitlets

        self._driver = driver
        self._motor = self._driver.getMotor(channel)
        if(channel == 1):
            self._ina = 1
            self._inb = 0
        else:
            self._ina = 2
            self._inb = 3
        atexit.register(self._release)
        
    @traitlets.observe('value')
    def _observe_value(self, change):
        self._write_value(change['new'])

    def _write_value(self, value):
        """Sets motor value between [-1, 1]"""
        mapped_value = int(255.0 * (self.alpha * value + self.beta))
        speed = min(max(abs(mapped_value), 0), 255)
        self._motor.setSpeed(speed)
        if mapped_value < 0:
            self._motor.run(Adafruit_MotorHAT.FORWARD)
            self._driver._pwm.setPWM(self._ina,0,0)
            self._driver._pwm.setPWM(self._inb,0,speed*16)
        else:
            self._motor.run(Adafruit_MotorHAT.BACKWARD)
            self._driver._pwm.setPWM(self._ina,0,speed*16)
            self._driver._pwm.setPWM(self._inb,0,0)

    def _release(self):
        """Stops motor by releasing control"""
        self._motor.run(Adafruit_MotorHAT.RELEASE)
        self._driver._pwm.setPWM(self._ina,0,0)
        self._driver._pwm.setPWM(self._inb,0,0)
import time
import traitlets
from traitlets.config.configurable import SingletonConfigurable
from Adafruit_MotorHAT import Adafruit_MotorHAT



class Robot(SingletonConfigurable):
    
    left_motor = traitlets.Instance(Motor)
    right_motor = traitlets.Instance(Motor)

    # config
    i2c_bus = traitlets.Integer(default_value=0).tag(config=True)
    left_motor_channel = traitlets.Integer(default_value=1).tag(config=True)
    left_motor_alpha = traitlets.Float(default_value=1.0).tag(config=True)
    right_motor_channel = traitlets.Integer(default_value=2).tag(config=True)
    right_motor_alpha = traitlets.Float(default_value=1.0).tag(config=True)
    
    def __init__(self, *args, **kwargs):
        super(Robot, self).__init__(*args, **kwargs)
        self.motor_driver = Adafruit_MotorHAT(i2c_bus=self.i2c_bus, addr=0x68)
        self.left_motor = Motor(self.motor_driver, channel=self.left_motor_channel, alpha=self.left_motor_alpha)
        self.right_motor = Motor(self.motor_driver, channel=self.right_motor_channel, alpha=self.right_motor_alpha)
        
    def set_motors(self, left_speed, right_speed):
        self.left_motor.value = left_speed
        self.right_motor.value = right_speed
        
    def forward(self, speed=1.0, duration=None):
        self.left_motor.value = speed
        self.right_motor.value = speed

    def backward(self, speed=1.0):
        self.left_motor.value = -speed
        self.right_motor.value = -speed

    def left(self, speed=1.0):
        self.left_motor.value = -speed
        self.right_motor.value = speed

    def right(self, speed=1.0):
        self.left_motor.value = speed
        self.right_motor.value = -speed

    def stop(self):
        self.left_motor.value = 0
        self.right_motor.value = 0
robot = Robot()
robot.set_motors(2.0, 1.0)

如果左右两个电机转速不一样,说明成功。

四、传感器

1. MPU6050(3.28RMB)

某宝上买的,这玩意这么便宜。不过当时是和DC Motor+Stepper FeatherWing一起下的单。具体也不懂GY-521是代表啥,反正知道jetson nano通过I2C从这玩意中读取IMU数据。
在这里插入图片描述
首先,安装py_imu_mpu6050
github地址:https://github.com/romybompart/py_imu_mpu6050

sudo pip3 install py-imu-mpu6050

连线方式:
MPU6050 jetson nano
VCC — 5v
GND — GND
SCL — 28
SDL — 27
(28, 27)表示I2C bus0

MPU6050的设备地址为0x68

连接后,执行以下命令,会出现mpu6050的设备地址。
在这里插入图片描述
Jetson Nano I2C说明及Python案例:MPU6050

猜你喜欢

转载自blog.csdn.net/u013468614/article/details/106030044