Hello. I’m trying to connect a PCA9685 PWM expander module. I use a pca9685 library for the OpenMV servo shield, and a motorTB library to do pwm on the channels. After running the script, i get the following error:
Traceback (most recent call last):
File “”, line 57, in
File “”, line 22, in init
File “pca9685.py”, line 7, in init
File “pca9685.py”, line 13, in reset
File “pca9685.py”, line 9, in _write
OSError: [Errno 110] ETIMEDOUT
What am i doing wrong and is there a way to fix this issue?
motorTB library code:
class DCMotors:
def init(self, i2c, address=0x60, freq=1600):
self.pca = pca.PCA9685(i2c, address)
self.pca9685.freq(freq)
def _pin(self, pin, value=None):
if value is None:
return bool(self.pca9685.pwm(pin)[0])
if value:
self.pca9685.pwm(pin, 4096, 0)
else:
self.pca9685.pwm(pin, 0, 0)
def speed(self, index, value=None):
pwm, in2, in1 = _DC_MOTORS[index]
if value is None:
value = self.pca9685.duty(pwm)
if self._pin(in2) and not self._pin(in1):
value = -value
return value
if value > 0:
self._pin(in2, False)
self._pin(in1, True)
elif value < 0:
self._pin(in1, False)
self._pin(in2, True)
else:
self._pin(in1, False)
self._pin(in2, False)
self.pca9685.duty(pwm, abs(value))
def brake(self, index):
pwm, in2, in1 = _DC_MOTORS[index]
self._pin(in1, True)
self._pin(in2, True)
self.pca9685.duty(pwm, 0)
pca9685 library code:
import utime
import ustruct
class PCA9685:
def init(self, i2c, address=0x40):
self.i2c = i2c
self.address = address
self.reset()
def _write(self, address, value):
self.i2c.writeto_mem(self.address, address, bytearray([value]))
def _read(self, address):
return self.i2c.readfrom_mem(self.address, address, 1)[0]
def reset(self):
self._write(0x00, 0x00) # Mode1
def freq(self, freq=None):
if freq is None:
return int(25000000.0 / 4096 / (self._read(0xFE) - 0.5))
prescale = int(25000000.0 / 4096.0 / freq + 0.5)
old_mode = self._read(0x00) # Mode 1
self._write(0x00, (old_mode & 0x7F) | 0x10) # Mode 1, sleep
self._write(0xFE, prescale) # Prescale
self._write(0x00, old_mode) # Mode 1
utime.sleep_us(5)
self._write(0x00, old_mode | 0xA1) # Mode 1, autoincrement on
def pwm(self, index, on=None, off=None):
if on is None or off is None:
data = self.i2c.readfrom_mem(self.address, 0x06 + 4 * index, 4)
return ustruct.unpack("<HH", data)
data = ustruct.pack("<HH", on, off)
self.i2c.writeto_mem(self.address, 0x06 + 4 * index, data)
def duty(self, index, value=None, invert=False):
if value is None:
pwm = self.pwm(index)
if pwm == (0, 4096):
value = 0
elif pwm == (4096, 0):
value = 4095
value = pwm[1]
if invert:
value = 4095 - value
return value
if not 0 <= value <= 4095:
raise ValueError("Out of range")
if invert:
value = 4095 - value
if value == 0:
self.pwm(index, 0, 4096)
elif value == 4095:
self.pwm(index, 4096, 0)
else:
self.pwm(index, 0, value)
finally, my code:
import pca9685 as pca
#import motorTB as motors
#from motorTB import DCMotors
import sensor, image, time
from pyb import delay
import math
import machine
from machine import I2C, Pin
import servo
from servo import Servos
i2c = I2C(sda=Pin(‘P5’), scl=Pin(‘P4’))
delay(1000)
print(‘i2c intialized’)
driver = DCMotors(i2c, address = 0x40)
delay(50)
servo = Servos(i2c, address=0x40, freq=50, min_us=650, max_us=2800, degrees=180)
delay(50)
def motor(pin1, pin2, spd):
if spd < 0:
driver.pca9685.pwm(pin1, 0, round((-spd) * 40.95))
driver.pca9685.pwm(pin2, 0, 0)
elif spd == 0:
driver.pca9685.pwm(pin1, 0, 0)
driver.pca9685.pwm(pin2, 0, 0)
elif spd > 0:
driver.pca9685.pwm(pin1, 0, 0)
driver.pca9685.pwm(pin2, 0, round(spd * 40.95))
#print(round(spd*40.95))
while(True):
motor(4, 5, 67)
motor(6, 7, -20)
print(‘run’)
delay(1500)
motor(4, 5, 0)
motor(6, 7, 0)
print(‘stop’)
delay(1500)