Skip to content

Instantly share code, notes, and snippets.

@mahenzon
Last active January 26, 2024 14:35
Show Gist options
  • Save mahenzon/203e9d935b42db17c2f57ff69a23b4b0 to your computer and use it in GitHub Desktop.
Save mahenzon/203e9d935b42db17c2f57ff69a23b4b0 to your computer and use it in GitHub Desktop.
Repka-Pi 3 H5 LED and Servo example using PCA9685 board and Adafruit CircuitPython libs (RoboIntellect RM001 M02)

Установка зависимостей

Зависимости для взаимодействия с GPIO

sudo apt install -y libgpiod2 python3-libgpiod

Создание и активация виртуального окружения (в примере использован python3.9, установлен отдельно)

python3.9 -m venv venv
source venv/bin/activate
# установка библиотеки для работы с gpio (необходима)
pip install gpiod
# установка библиотек от Adafruit
pip install adafruit-circuitpython-servokit

Список зависимостей в табличном виде и в формате requirements.txt:

repka@Repka-Pi:~/projects/repka-pi-py-gpio$ source venv/bin/activate
(venv) repka@Repka-Pi:~/projects/repka-pi-py-gpio$ pip list
Package                          Version
-------------------------------- -------
Adafruit-Blinka                  8.31.0 
adafruit-circuitpython-busdevice 5.2.6  
adafruit-circuitpython-motor     3.4.13 
adafruit-circuitpython-pca9685   3.4.14 
adafruit-circuitpython-register  1.9.18 
adafruit-circuitpython-requests  2.0.4  
adafruit-circuitpython-servokit  1.3.17 
adafruit-circuitpython-typing    1.9.6  
Adafruit-PlatformDetect          3.59.0 
Adafruit-PureIO                  1.1.11 
gpiod                            2.1.3  
pip                              20.0.2 
pkg-resources                    0.0.0  
pyftdi                           0.55.0 
pyserial                         3.5    
pyusb                            1.2.1  
setuptools                       44.0.0 
typing-extensions                4.9.0  

(venv) repka@Repka-Pi:~/projects/repka-pi-py-gpio$ pip freeze
Adafruit-Blinka==8.31.0
adafruit-circuitpython-busdevice==5.2.6
adafruit-circuitpython-motor==3.4.13
adafruit-circuitpython-pca9685==3.4.14
adafruit-circuitpython-register==1.9.18
adafruit-circuitpython-requests==2.0.4
adafruit-circuitpython-servokit==1.3.17
adafruit-circuitpython-typing==1.9.6
Adafruit-PlatformDetect==3.59.0
Adafruit-PureIO==1.1.11
gpiod==2.1.3
pyftdi==0.55.0
pyserial==3.5
pyusb==1.2.1
typing-extensions==4.9.0

После этого можно запускать скрипт, но только от root пользователя, так как нужен доступ к GPIO.

Запуск без root доступа пока на этапе исследования. Предложения приветствуются.

"""
Repka-Pi 3 H5 LED and Servo example using PCA9685 board and Adafruit CircuitPython libs (RoboIntellect RM001 M02)
Adafruit libraries usage example
Hardware:
- Repka-Pi (any other i2c microcontroller is suitable: Raspberry, Orange, Banana, ODROID, ESP8266, etc.)
- PCA9685
- RGB LED
- Servos (in this example 4 servos are used on the RoboIntellect RM001 M02
Dependencies:
adafruit-circuitpython-servokit
Heavily depends on these changes:
- https://github.com/adafruit/Adafruit_Python_PlatformDetect/pull/336
- https://github.com/adafruit/Adafruit_Blinka/pull/772
"""
from time import sleep
import board
import busio
from adafruit_motor.servo import Servo
from Adafruit_PureIO import smbus
from adafruit_servokit import ServoKit
from adafruit_pca9685 import PCA9685
SDA = board.SDA
SCL = board.SCL
def set_angle_smooth(servo: Servo, angle: int, step: int = 1, wait: float = 0.003) -> None:
"""
Set angle step by step.
:param servo:
:param angle:
:param step:
:param wait:
:return:
"""
if servo.angle is None:
servo.angle = angle
return
current = int(servo.angle)
if current > angle:
step = -step
for i in range(current, angle, step):
servo.angle = i
sleep(wait)
def demo_write_raw_bytes(i2c_bus: busio.I2C) -> None:
"""
Sometimes you need to write raw bytes.
:param i2c_bus:
:return:
"""
bus: smbus.SMBus = i2c_bus._i2c._i2c_bus
addr = 64 # you have to know the address
buf = b"\x00" # you have to know bytes
bus.write_bytes(addr, buf)
def main():
# it's just a constant
max_duty_cycle = 0xffff
# Create the I2C bus interface.
# you can pass other pins if you need to.
i2c_bus = busio.I2C(SCL, SDA)
# if you want to control PCA9685 directly:
# Create a simple PCA9685 class instance.
pca = PCA9685(i2c_bus)
# Set the PWM frequency to 60hz. (or any other frequency_
pca.frequency = 60
# I have LED connected to the last three pins on the PCA9685 board
RED = pca.channels[len(pca.channels) - 1]
GREEN = pca.channels[len(pca.channels) - 2]
BLUE = pca.channels[len(pca.channels) - 3]
# reset
for idx in range(len(pca.channels)):
pca.channels[idx].duty_cycle = 0
print("Set some color")
# set some color (full red + half green)
RED.duty_cycle = max_duty_cycle # full
GREEN.duty_cycle = 0x7FFF # middle
BLUE.duty_cycle = 0 # off
# wait so human eye can see the change
sleep(1)
print("Set LED to 50%")
# Set the PWM duty cycle for channel zero to 50%. duty_cycle is 16 bits to match other PWM objects
# but the PCA9685 will only actually give 12 bits of resolution.
for idx in range(len(pca.channels) - 3, len(pca.channels)):
pca.channels[idx].duty_cycle = 0x7FFF
# wait so human eye can see the change
sleep(1)
print("Smooth on and off LED two times")
times = 2
max_brightness = max_duty_cycle
step = 100
for _ in range(times):
# Increase brightness:
for i in range(0, max_brightness - 1, step):
for idx in range(len(pca.channels) - 3, len(pca.channels)):
pca.channels[idx].duty_cycle = i
# Decrease brightness:
for i in range(max_brightness, 0, -step):
for idx in range(len(pca.channels) - 3, len(pca.channels)):
pca.channels[idx].duty_cycle = i
sleep(1)
print("Set LED to Blue")
RED.duty_cycle = 0
GREEN.duty_cycle = 0
BLUE.duty_cycle = max_duty_cycle
sleep(1)
print("Start moving servos. Make sure you have external power connected to the PCA9685 board")
# idk if you need to change the frequency
pca.frequency = 50
# i2c should be automatically detected!
kit = ServoKit(channels=16)
# if not, you can set the bus by yourself:
# kit = ServoKit(channels=16, i2c=i2c_bus)
# you can change servos rules (actuation_range, PWM range)
# servos = 4
# for idx in range(servos):
# servo = kit.servo[idx]
# set_angle_smooth()
# # servo.actuation_range = 180
# # servo.set_pulse_width_range(1000, 2000)
# Example for RoboIntellect RM001 M02 https://t.me/RepkaPitalk/24150
servo_base = kit.servo[0]
servo_claw = kit.servo[1]
servo_pull = kit.servo[2]
servo_raise = kit.servo[3]
# open claw
set_angle_smooth(servo_claw, 180, wait=0.05, step=1)
sleep(0.2)
# raise high
set_angle_smooth(servo_raise, 0, wait=0.05, step=1)
sleep(0.2)
# center
set_angle_smooth(servo_base, 60, wait=0.05, step=1)
sleep(0.2)
# pull to self
set_angle_smooth(servo_pull, 170, wait=0.01, step=2)
sleep(0.2)
# set LED to RED
RED.duty_cycle = max_duty_cycle
GREEN.duty_cycle = 0
BLUE.duty_cycle = 0
sleep(1)
# action!!
# pos
# set_angle_smooth(servo_raise, 5)
set_angle_smooth(servo_pull, 90)
set_angle_smooth(servo_base, 0)
# open claw
set_angle_smooth(servo_claw, 180)
# lower
set_angle_smooth(servo_raise, 50)
sleep(0.5)
# claw
set_angle_smooth(servo_claw, 100, wait=0.005, step=1)
sleep(0.5)
# raise high
set_angle_smooth(servo_raise, 0, wait=0.005, step=1)
sleep(0.2)
# rotate
set_angle_smooth(servo_base, 170)
sleep(0.2)
# lower
set_angle_smooth(servo_raise, 50, wait=0.01)
# open claw
set_angle_smooth(servo_claw, 180)
sleep(0.1)
# raise high
set_angle_smooth(servo_raise, 0)
sleep(0.2)
# center
set_angle_smooth(servo_base, 60, wait=0.001, step=1)
sleep(0.2)
# pull to self
set_angle_smooth(servo_pull, 170, wait=0.001, step=2)
sleep(0.2)
# Set LED to green
RED.duty_cycle = 0
GREEN.duty_cycle = max_duty_cycle
BLUE.duty_cycle = 0
print("done :)")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment