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

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

PCA9685とjetson nanoで複数のサーボモータを動かす

Jetson nano でPWMコントローラーのPCA9685を使ってサーボモータを複数動かすまでの備忘録。

PWMコントローラーを使えば、モータを16個同時に操作できるし、スクリプト側でマルチthreadingを使わなくて済むとかいいことばかりなので使ってみた。

あとPWMコントローラーは普通にサーボモータを使うより角度や、デューティ比を正確に設定できるので必須アイテム。

目次
1. Adafruit-PCA9685のインストール
2. PCA9685とjetson nanoの配線
3. 複数のサーボモータを実際に動かす



1. Adafruit-PCA9685のインストール

pip3 install Adafruit_PCA9685

このままだとエラーが出るのでI2C.pyを書き換え。

vi ~/.local/lib/python3.6/site-packages/Adafruit_GPIO/I2C.py


I2C.pyの以下を修正
・2行をコメントアウト
return Device(address, "1", i2c_interface, **kwargs)にする

def get_i2c_device(address, busnum=None, i2c_interface=None, **kwargs):
    """Return an I2C device for the specified address and on the specified bus.
    If busnum isn't specified, the default I2C bus for the platform will attempt
    to be detected.
    """
#    if busnum is None:
 #       busnum = get_default_bus()
    return Device(address, "1", i2c_interface, **kwargs)

下のように信号が表示されればOK。

$ sudo i2cdetect -y -r 1
>>>>

#     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
#00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
#10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
#70: 70 -- -- -- -- -- -- --                         


2. PCA9685とjetson nanoの配線

PCA9685.                    Jetson Nano
------------------------------------
GND                  ->        GND
SCL                   ->        I2C(5 番)
SDA                   ->        I2C(3番)
VCC                   ->        3.3V
V+                      ->        5V




3. 複数のサーボモータを実際に動かす

simpletest.py

from __future__ import division
import time
import Adafruit_PCA9685

pwm = Adafruit_PCA9685.PCA9685()

# Configure min and max servo pulse lengths
servo_min = 102  # Min pulse length out of 4096
servo_max = 492  # Max pulse length out of 4096

# Helper function to make setting a servo pulse width simpler.
def set_servo_pulse(channel, pulse):
    pulse_length = 1000000    # 1,000,000 us per second
    pulse_length //= 60       # 60 Hz
    print('{0}us per period'.format(pulse_length))
    pulse_length //= 4096     # 12 bits of resolution
    print('{0}us per bit'.format(pulse_length))
    pulse *= 1000
    pulse //= pulse_length
    pwm.set_pwm(channel, 0, pulse)

# Set frequency to 60hz, good for servos.
pwm.set_pwm_freq(50)

print('Moving servo on channel 0, press Ctrl-C to quit...')
while True:
    # Move servo on channel O between extremes.
    pwm.set_pwm(15, 0, servo_min)
    time.sleep(1)
    pwm.set_pwm(14, 0, servo_max)
    time.sleep(1)
    pwm.set_pwm(15, 0, servo_max)
    time.sleep(1)
    pwm.set_pwm(14, 0, servo_min)
    time.sleep(1)


Tkinerを使ったversion

from __future__ import division
import time
import Adafruit_PCA9685

from tkinter import *

pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(50)

class App:

    def __init__(self, master):
        frame = Frame(master)
        frame.pack()
        scale_pan = Scale(frame, label="pan", from_=0, to=180, tickinterval=90, orient=HORIZONTAL, command=self.update_pan)
        scale_pan.set(90)
        scale_pan.grid(row=0, column=0)
        scale_tilt = Scale(frame, label="tilt", from_=0, to=180, tickinterval=90, orient=VERTICAL, command=self.update_tilt)
        scale_tilt.set(90)
        scale_tilt.grid(row=0, column=1)

    def update_pan(self, angle):
        duty = int( float(angle) * 2.17 + 102 )
        pwm.set_pwm(14, 0, duty)
        time.sleep(0.1)

    def update_tilt(self, angle):
        duty = int( float(angle) * 2.17 + 102 )
        pwm.set_pwm(15, 0, duty)
        time.sleep(0.1)

root = Tk()
root.wm_title('Servo Control')
app = App(root)
root.geometry("220x120+0+0")
root.mainloop()

うまくいった。


参考サイト

Jetson nanoとPCA9685でサーボを動かそうとするときのI2Cエラー対処法!
jetson_nano_grove