ものづくりのブログ

うちのネコを題材にしたものづくりができたらいいなと思っていろいろ奮闘してます。

【RaspberryPi】モータを沢山動かしてみたい

RaspberryPi で沢山モータを動かしてみたくてサンプルを作ってみました。
ここにメモを残します。

コード

import Adafruit_PCA9685
import json
import time

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

def set_servo_angle(channel, angle, pattern):

    pulse_min = 150  # 最小パルス幅(0度のとき)
    pulse_max = 650  # 最大パルス幅(180度のとき)
    pulse_width = pulse_min + (angle / 180.0) * (pulse_max - pulse_min)
    
    print(f"pattern: {pattern}, channel: {channel}, pulse_width: {pulse_width}")
    pwm.set_pwm(channel, 0, int(pulse_width))
    
    return

def move_servos(channels, start_angles, end_angles, speeds, pattern):

    max_steps = max(abs(end - start) for start, end in zip(start_angles, end_angles))
    steps = [abs(end - start) for start, end in zip(start_angles, end_angles)]
    directions = [1 if end > start else -1 for start, end in zip(start_angles, end_angles)]
    
    current_angles = start_angles[:] 

    for step in range(max_steps):
        for i, channel in enumerate(channels):
            print(f"range: {steps[i]} / {channel}")

            if step < steps[i]:
                current_angles[i] += directions[i]
                set_servo_angle(channel, current_angles[i], pattern)

        time.sleep(1 / min(speeds))

def motion(motion_file):
    json_load = json.load(open(f"{motion_file}.json", 'r'))

    for i in (json_load):
        move_servos(
            channels = json_load[i]['channels'],
            start_angles = json_load[i]['start_angles'],
            end_angles = json_load[i]['end_angles'],
            speeds = json_load[i]['speeds'],
            pattern = motion_file
        )

def main():
    while True:

        motion("pattern_01")

        motion("pattern_02")    

        motion("pattern_03") 

if __name__ == '__main__':
    main()

モーションファイル

pattern_01.json

{
  "a": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [90, 90,  90,  90,  90,  90,  90,  90,  90],
    "end_angles": [10, 45, 135, 150, 20, 30, 0, 0, 0],
    "speeds": [20, 50, 20, 30, 40, 90, 10, 10, 10]
  },
  "b": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [10, 45, 135, 150, 20, 30, 0, 0, 0],
    "end_angles": [160, 145, 35, 50, 120, 130, 20, 20, 20],
    "speeds": [20, 50, 20, 30, 40, 90, 100, 10, 10]
  },
  "c": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [160, 145, 35, 50, 120, 130, 20, 20, 20],
    "end_angles": [90, 90,  90,  90,  90,  90,  90,  90,  90],
    "speeds": [10, 50, 20, 30, 40, 50, 10, 10, 10]
  }
}

pattern_02.json

{
  "a": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [90, 90,  90,  90,  90,  90,  90,  90,  90],
    "end_angles": [0, 0, 0, 0, 0, 180, 180, 180, 180],
    "speeds": [150, 150, 150, 150, 150, 150, 150, 150, 150]
  },
  "b": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [0, 0, 0, 0, 0, 180, 180, 180, 180],
    "end_angles": [180, 180, 180, 180, 180, 0, 0, 0, 0],
    "speeds": [150, 150, 150, 150, 150, 150, 150, 150, 150]
  },
  "c": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [180, 180, 180, 180, 180, 0, 0, 0, 0],
    "end_angles": [90, 90,  90,  90,  90,  90,  90,  90,  90],
    "speeds": [150, 150, 150, 150, 150, 150, 150, 150, 150]
  }
}

pattern_03.json

{
  "a": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [90, 90,  90,  90,  90,  90,  90,  90,  90],
    "end_angles": [0, 0, 0, 0, 0, 180, 180, 180, 180],
    "speeds": [10, 10, 10, 10, 10, 10, 10, 10, 10]
  },
  "b": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [0, 0, 0, 0, 0, 180, 180, 180, 180],
    "end_angles": [180, 180, 180, 180, 180, 0, 0, 0, 0],
    "speeds": [10, 10, 10, 10, 10, 10, 10, 10, 10]
  },
  "c": {
    "channels": [0, 1, 2, 3, 4, 5, 6, 7, 8],
    "start_angles": [180, 180, 180, 180, 180, 0, 0, 0, 0],
    "end_angles": [90, 90,  90,  90,  90,  90,  90,  90,  90],
    "speeds": [10, 10, 10, 10, 10, 10, 10, 10, 10]
  }
}