Article Directory
1. Jetson nano fan cooling
2020-5-10 0:23 Wind and rain knocked on the window lattice
. I started with a second-hand jetson nano on the *fish, and this story began.
- jetson nano 600RMB *fish
- Speed regulating fan 15RMB *bao
- Wireless network card 79RMB *bao
1. Manually set the fan speed terminal command
- full speed
sudo sh -c 'echo 255 > /sys/devices/pwm-fan/target_pwm'
- Stop (note that it is slowly reduced from the current speed to 0, the deceleration process is 1 minute)
sudo sh -c 'echo 20 > /sys/devices/pwm-fan/target_pwm'
2. Automatically adjust the fan speed according to the CPU temperature
Note: The conditions of the following procedures can be changed as needed.
# 源地址: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. Auto-start at boot
To set Jupyter to start automatically when booting, please refer to: Let Jupyter Lab start automatically on Jetson Nano.
Refer to ubuntu to implement python script running in the background + boot up automatically.
1. Create rc-local.service file
sudo gedit /etc/systemd/system/rc-local.service
2. Replace the rc-local.service file with the following
[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. Create the file rc.local
sudo gedit /etc/rc.local
4. Copy the following content into the rc.local file
#!/bin/sh -e
# rc.local
nohup sudo python ~/fan_control.py > /usr/local/out.log 2>&1 &
exit 0
5. Ubuntu system sudo command without password
sudo gedit /etc/sudoers
The %sudo ALL=(ALL:ALL) ALL
revised to%sudo ALL=(ALL) NOPASSWD:ALL
请仔细操作!
6. Add permissions to rc.local
sudo chmod +x /etc/rc.local
7. Enable the service
sudo systemctl enable rc-local
8. Start the service and check the status
sudo systemctl start rc-local.service
sudo systemctl status rc-local.service
9. Restart and check for success
reboot
If the fan turns automatically, it means success.
2. OLED screen display of I2C bus
1. Jetracer expansion board + battery package (255RMB)
I found a small car based on jetson nano on a treasure, there are two models: 1) jetbot; 2) jetracer. Jetbot uses differential drive steering, jetracer is a mini version of unmanned vehicle (geometric kinematics model is Ackerman wheel steering model). The latter is what I want. Jetracer is very good. The only shortcoming is that the motor does not have an encoder, which is missing in the subsequent functions (more accurate odometer information cannot be obtained). So: I only bought jetracer expansion board and lithium battery pack.
2. I2C bus
Jetson nano has 2 sets of I2C buses in total, namely (I2C BUS 1: 3, 5) (I2C BUS 2: 27, 28). The pins of the I2C bus are in J41, that is, the two rows of dense pin areas.
View devices on bus 1
sudo i2cdetect -y -r 1
Among them, 3c is the I2C device address of the OLED.
3. OLED display
Since the jetracer expansion board uses the 0.91inch OLED screen of SSD1306, you need to install Adafruit_SSD1306 first
sudo pip3 install Adafruit_SSD1306
Since the sample program displayed by OLED is on jetbot, install jetbot first.
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
If you need to uninstall jetbot, you can execute it in the root directory of jetbot:
sudo cat jetbot.uninstall.txt | sudo xargs rm -rf
Therefore, it is best to keep the jetbot.uninstall.txt
files.
Run the program:
cd jetbot/jetbot/apps/
sudo python3 stats.py
You will see that the OLED displays information such as Ethernet, wlan, memory and storage.
3. Car chassis and control
1. Ackerman steering car chassis (209RMB)
Due to poor scalability of jetracer and jetbot, (without mpu, without motor coding). Jetbot uses differential speed control, a simple TT motor without an encoder. Jetracer uses steering servos to control the direction, but the rear two motors do not have encoders. Therefore, the chassis of jetbot and jetracer are not considered.
I picked a mini car (motor with code, steering gear) without a controller in another store. In that store, there are also controllers (the kind that can be directly controlled by a gamepad). Because the car is already small, 211 x 191 x 65mm. If the system uses two computing boards, the car body must be bloated. I want to focus everything on jetson nano, just like jetracer.
Bottom layer and ROS serial communication protocol
Number of digits | Hexadecimal | ASCII code |
---|---|---|
1 | 0x7B | { |
2 | 0x2D or 0x2B | -Or+ |
3 | 0x30~0x39 | 0~9 |
4 | 0x30~0x39 | 0~9 |
5 | 0x30~0x39 | 0~9 |
6 | 0x30~0x39 | 0~9 |
7 | 0x2D or 0x2B | -Or+ |
8 | 0x30~0x39 | 0~9 |
9 | 0x30~0x39 | 0~9 |
10 | 0x30~0x39 | 0~9 |
11 | 0x30~0x39 | 0~9 |
12 | 0x7D | } |
For example, if I send {+3000-0100}, it means that the expected speed is 3000/100 and the expected angle is -100/100.
2. DC Motor+Stepper FeatherWing (45RMB)
The PCA9686 on the jetracer expansion board only leads to two channels, one of which is used to control the steering servo, and the two motors behind it share one channel. 在实际测试中,即使用同一个信号控制,两个电机的转速是不一样的,这次上电是左边的快些,下次上电可能就是右边的快些。
If the speeds of the left and right motors cannot be controlled to be consistent, then in actual operation, we cannot well control the car to drive on a predetermined trajectory. For more discussion, please refer to the two DC motors at different speeds. The car always goes in a straight line. How to solve it? .
The only solution is to control the left and right motors separately and use PID to adjust the speed to the same speed. However, but, but, however. . . The left and right motors on the jetracer expansion board share a control channel. Asked the customer service, unless the hardware circuit is changed. . .
So various search solutions, find DC Motor+Stepper FeatherWing shown in the figure below.
Pin description
Coincidentally, it is the motor control board used in the official version of jetbot (not the Micro Snow version) (it can also drive other types of motors). The diagram below is more straightforward.
Connection method:
MPU6050 jetson nano
VCC — 5v
GND — GND
SCL — 28
SDL — 27
(28, 27) means I2C bus0
The device address of MPU6050 is 0x68
code:
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)
If the speed of the two motors on the left and right are not the same, it means success.
Fourth, the sensor
1. MPU6050(3.28RMB)
I bought it from a certain treasure, this thing is so cheap. However, it was placed with DC Motor+Stepper FeatherWing. I don’t know what GY-521 stands for. Anyway, I know that jetson nano reads IMU data from this thing through I2C.
First, install py_imu_mpu6050
github address: https://github.com/romybompart/py_imu_mpu6050
sudo pip3 install py-imu-mpu6050
Connection method:
MPU6050 jetson nano
VCC — 5v
GND — GND
SCL — 28
SDL — 27
(28, 27) means I2C bus0
The device address of MPU6050 is 0x68
After connecting, execute the following command, the device address of mpu6050 will appear.
Jetson Nano I2C description and Python case: MPU6050