アプリとサービスのすすめ

アプリやIT系のサービスを中心に書いていきます。たまに副業やビジネス関係の情報なども気ままにつづります

Jetson nanoでPWM制御をするまでの手順【ハードウェア】

今回はJetson nanoでPWM(Pulse Width Modulation)制御をするまでの手順をまとめてく。

Jetson nanoでPWMのPinは「32, 33」の二つ
これを使ってサーボモータをマルチスレッドで二つ動かす。


目次
1. 配線図
2. Jetson nanoでGPIOのインストール
3. PWM設定-「Jetson-IO tool」の実行
4. PIN番号を合わせる
5. PWMでサーボモータを制御

1.配線図

Jetson nanoの40 PINs(サーボモータの配線は3つあってそれぞれ、PWMとGNDと電圧V。


Jetson nanoとサーボモータ(SG-5010)の配線図。



2 Jetson nanoでGPIOのインストール

PWM用のGPIOをインストール。

$ git clone https://github.com/NVIDIA/jetson-gpio.git
$ cd jetson-gpio
$ sudo python3 setup.py install

# グループ作成とユーザーの追加
$ sudo groupadd -f -r gpio
$ sudo usermod -a -G gpio <ユーザー名>

# udevルールの追加と反映
$ sudo cp lib/python/Jetson/GPIO/99-gpio.rules /etc/udev/rules.d/
$ sudo udevadm control --reload-rules && sudo udevadm trigger
# 再起動して使えるようにする
$ sudo reboot

3 PWM設定-「Jetson-IO tool」の実行

Jetson nanoにあるPINを外部ピンへ拡張する。

$ sudo /opt/nvidia/jetson-io/jetson-io.py

「Jetson Expansion Header Tools」でpwm0, pwm2を選択
「save and reboot to reconfigure pins」で再起動して反映。

|                Select desired functions (for pins):                |
 |                                                                    |
 |                 [ ] aud_mclk      (7)                              |
 |                 [ ] i2s4          (12,35,38,40)                    |
 |                 [*] pwm0          (32)                             |
 |                 [*] pwm2          (33)                             |
 |                 [ ] spi1          (19,21,23,24,26)                 |
 |                 [ ] spi2          (13,16,18,22,37)                 |
 |                 [ ] uartb-cts/rts (11,36)                          |


****jetson-io.py実行時に一瞬、画面に何かが表示されて直ぐに終了してしまう場合

DTB ファイルが /boot ディレクトリ配下に存在しているので、/boot/dtb ディレクトリを作成して、その中にコピー。

cd /boot
sudo mkdir dtb
sudo cp *.dtb* dtb/

再度
$ sudo /opt/nvidia/jetson-io/jetson-io.py

PWMが設定できてるなら下の様にpwm-0, pwm-2がnullになる

$ sudo cat /sys/kernel/debug/pwm
>>>>>>

platform/70110000.pwm, 1 PWM device
 pwm-0   (pwm-regulator       ): requested enabled period: 2500 ns duty: 0 ns polarity: normal

platform/7000a000.pwm, 4 PWM devices
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-1   (pwm-regulator       ): requested enabled period: 8000 ns duty: 1440 ns polarity: normal
 pwm-2   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-3   (pwm-fan             ): requested enabled period: 45334 ns duty: 0 ns polarity: normal

4. PIN番号を合わせる

Jetson Nanoでは普通に40PINを拡張しただけではサーボモータが動かない。

サーボモータが動くようにするにはさらに設定が必要で一番苦労したところ。

# assign Pin32 to PWM0
$ busybox devmem 0x700031fc 32 0x45
$ busybox devmem 0x6000d504 32 0x2
# assign Pin33 to PWM2
$ busybox devmem 0x70003248 32 0x46
$ busybox devmem 0x6000d100 32 0x00

$ cd /sys/devices/7000a000.pwm/pwm/pwmchip0
# Control Pin 32 of PWM0
echo 0 > export
echo 20000000 > pwm0/period
echo 2500000 > pwm0/duty_cycle
echo 1 > pwm0/enable

# Control Pin33 of PWM2
echo 2 > export
echo 20000000 > pwm2/period
echo 1500000 > pwm2/duty_cycle
echo 1 > pwm2/enable

設定したらサーボモータが動いた。



NVIDIAの元記事

参考記事


5 PWMでサーボモータを制御

1つのサーボモータを動かす

import RPi.GPIO as GPIO
import time

output_pins = {
    'JETSON_XAVIER': 18,
    'JETSON_NANO': 32,
    'JETSON_NX': 33,
    'CLARA_AGX_XAVIER': 18,
    'JETSON_TX2_NX': 32,
    'JETSON_ORIN': 18,
}
output_pin = output_pins.get(GPIO.model, None)
if output_pin is None:
    raise Exception('PWM not supported on this board')


def main():
    # Pin Setup:
    # Board pin-numbering scheme
    GPIO.setmode(GPIO.BOARD)
    # set pin as an output pin with optional initial state of HIGH
    GPIO.setup(output_pin, GPIO.OUT, initial=GPIO.HIGH)
    p = GPIO.PWM(output_pin, 50)
    val = 7.25
    incr = 0.25
    p.start(val)

    print("PWM running. Press CTRL+C to exit.")
    try:
        while True:
            time.sleep(1)
            if val >= 12:
                incr = -incr
            if val <= 2.5:
                incr = -incr
            val += incr
            p.ChangeDutyCycle(val)
    finally:
        p.stop()
        GPIO.cleanup()

if __name__ == '__main__':
    main()

マルチスレッドで2つのサーボモータを動かす

#!/usr/bin/env python

import Jetson.GPIO as GPIO
import time
import threading
import sys
from formura import Angle2Duty

OUTPUT_PIN1 = 32 
OUTPUT_PIN2 = 33
CYCLE = 50
t=2

def setup_device():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(OUTPUT_PIN1, GPIO.OUT, initial=GPIO.HIGH)
    pw = GPIO.PWM(OUTPUT_PIN1, CYCLE)

    GPIO.setup(OUTPUT_PIN2, GPIO.OUT, initial=GPIO.HIGH)
    ph = GPIO.PWM(OUTPUT_PIN2, CYCLE)
    return pw, ph

def pw_loop(pw):
    while flag:
        dc1 = Angle2Duty(450)
        pw.start(dc1)
        print("width dc {}".format(dc1))
        time.sleep(t)
        dc2 = Angle2Duty(500)
        pw.start(dc2)
        print("width dc {}".format(dc2))
        time.sleep(t)
        dc3 = Angle2Duty(410)
        pw.start(dc3)
        print("width dc {}".format(dc3))
        time.sleep(t)
        dc4 = Angle2Duty(300)
        pw.start(dc4)
        print("width dc {}".format(dc4))
        time.sleep(t)

def ph_loop(ph):
    while flag:
        dc1 = Angle2Duty(120)
        ph.start(dc1)
        print("ph height {}".format(dc1))
        time.sleep(t)
        dc2 = Angle2Duty(180)
        ph.start(dc2)
        print("ph height {}".format(dc2))
        time.sleep(t)
        dc3 = Angle2Duty(240)
        ph.start(dc3)
        print("ph height {}".format(dc3))
        time.sleep(t)
        dc4 = Angle2Duty(170)
        ph.start(dc4)
        print("ph height {}".format(dc4))
        time.sleep(t)
        

if __name__ == '__main__':
    flag = True
    c=0
    pw, ph = setup_device()
    th1 = threading.Thread(target=pw_loop, args=(pw,))
    th1.start()
    th2 = threading.Thread(target=ph_loop, args=(ph,))
    th2.start()
    while True:
        c +=1
        if c==3000:
            flag =False
            th1.join()
            th2.join()
            pw.stop()
            ph.stop()
            GPIO.cleanup()
            sys.exit(1)


参考記事

JetPack 4.3 (r32.3.1) で追加された Jetson-IO tool を使用して Pinmux テーブルを設定してみた。
Jetson Nano の 2 つのハードウェア PWM を使用してみた
Jetson Nano の GPIO にサーボモータをつないで制御してみる