From 4d92bf17cfc620a492801fa41bb712addcc599d2 Mon Sep 17 00:00:00 2001 From: Sebastian Ludwig Date: Thu, 19 Jun 2014 23:23:13 +0200 Subject: [PATCH 1/4] Fixed: PWM servo driver did not reset properly during initialization. --- Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py index 76ab5137..686059fd 100644 --- a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py +++ b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py @@ -32,7 +32,7 @@ def __init__(self, address=0x40, debug=False): self.debug = debug if (self.debug): print "Reseting PCA9685" - self.i2c.write8(self.__MODE1, 0x00) + self.i2c.bus.write_byte(0x00, 0x06) def setPWMFreq(self, freq): "Sets the PWM frequency" From 47a75a2fa69301a269beb80fc5a563b1a2db9876 Mon Sep 17 00:00:00 2001 From: Sebastian Ludwig Date: Thu, 19 Jun 2014 23:27:39 +0200 Subject: [PATCH 2/4] Passing debug flag from PWM to Adafruit_I2C. --- Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py index 686059fd..bfe9b64a 100644 --- a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py +++ b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py @@ -28,6 +28,7 @@ class PWM : def __init__(self, address=0x40, debug=False): self.i2c = Adafruit_I2C(address) + self.i2c.debug = debug self.address = address self.debug = debug if (self.debug): From 0780adbd87a165905572630b0730f357dec15bee Mon Sep 17 00:00:00 2001 From: Sebastian Ludwig Date: Fri, 20 Jun 2014 00:34:08 +0200 Subject: [PATCH 3/4] Addition to fix in 4d92bf1: ending sleep of PCA9685 in PWM servo driver initialization. --- Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py index bfe9b64a..73427baa 100644 --- a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py +++ b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py @@ -25,6 +25,7 @@ class PWM : __ALLLED_ON_H = 0xFB __ALLLED_OFF_L = 0xFC __ALLLED_OFF_H = 0xFD + __SLEEP = 0x10 def __init__(self, address=0x40, debug=False): self.i2c = Adafruit_I2C(address) @@ -34,6 +35,10 @@ def __init__(self, address=0x40, debug=False): if (self.debug): print "Reseting PCA9685" self.i2c.bus.write_byte(0x00, 0x06) + mode1 = self.i2c.readU8(self.__MODE1) + mode1 = mode1 & ~self.__SLEEP # wake up (reset sleep) + self.i2c.write8(self.__MODE1, mode1) + time.sleep(0.005) # wait for oscillator def setPWMFreq(self, freq): "Sets the PWM frequency" From e7ce458ad930dad07e69336210b5188c8b0c7cd4 Mon Sep 17 00:00:00 2001 From: Sebastian Ludwig Date: Sat, 21 Jun 2014 11:20:59 +0200 Subject: [PATCH 4/4] Extended fix in 4d92bf1 to work if more than one PCA9685 is connected. In the old version any subsequent board initialization reset all previously initialized boards. --- Adafruit_I2C/Adafruit_I2C.py | 14 ++++-- .../Adafruit_PWM_Servo_Driver.py | 43 +++++++++++++------ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/Adafruit_I2C/Adafruit_I2C.py b/Adafruit_I2C/Adafruit_I2C.py index 0c4a7d98..6c826166 100755 --- a/Adafruit_I2C/Adafruit_I2C.py +++ b/Adafruit_I2C/Adafruit_I2C.py @@ -25,15 +25,14 @@ def getPiRevision(): def getPiI2CBusNumber(): # Gets the I2C bus number /dev/i2c# return 1 if Adafruit_I2C.getPiRevision() > 1 else 0 - + def __init__(self, address, busnum=-1, debug=False): self.address = address # By default, the correct I2C bus is auto-detected using /proc/cpuinfo # Alternatively, you can hard-code the bus version below: # self.bus = smbus.SMBus(0); # Force I2C0 (early 256MB Pi's) # self.bus = smbus.SMBus(1); # Force I2C1 (512MB Pi's) - self.bus = smbus.SMBus( - busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber()) + self.bus = smbus.SMBus(busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber()) self.debug = debug def reverseByteOrder(self, data): @@ -69,6 +68,15 @@ def write16(self, reg, value): except IOError, err: return self.errMsg() + def writeRaw8(self, value): + "Writes an 8-bit value on the bus" + try: + self.bus.write_byte(self.address, value) + if self.debug: + print "I2C: Wrote 0x%02X" % value + except IOError, err: + return self.errMsg() + def writeList(self, reg, list): "Writes an array of bytes using I2C format" try: diff --git a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py index 73427baa..35c993ca 100644 --- a/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py +++ b/Adafruit_PWM_Servo_Driver/Adafruit_PWM_Servo_Driver.py @@ -9,23 +9,35 @@ # ============================================================================ class PWM : - i2c = None - # Registers/etc. + __MODE1 = 0x00 + __MODE2 = 0x01 __SUBADR1 = 0x02 __SUBADR2 = 0x03 __SUBADR3 = 0x04 - __MODE1 = 0x00 __PRESCALE = 0xFE __LED0_ON_L = 0x06 __LED0_ON_H = 0x07 __LED0_OFF_L = 0x08 __LED0_OFF_H = 0x09 - __ALLLED_ON_L = 0xFA - __ALLLED_ON_H = 0xFB - __ALLLED_OFF_L = 0xFC - __ALLLED_OFF_H = 0xFD + __ALL_LED_ON_L = 0xFA + __ALL_LED_ON_H = 0xFB + __ALL_LED_OFF_L = 0xFC + __ALL_LED_OFF_H = 0xFD + + # Bits + __RESTART = 0x80 __SLEEP = 0x10 + __ALLCALL = 0x01 + __INVRT = 0x10 + __OUTDRV = 0x04 + + general_call_i2c = Adafruit_I2C(0x00) + + @classmethod + def softwareReset(cls): + "Sends a software reset (SWRST) command to all the servo drivers on the bus" + cls.general_call_i2c.writeRaw8(0x06) # SWRST def __init__(self, address=0x40, debug=False): self.i2c = Adafruit_I2C(address) @@ -33,8 +45,12 @@ def __init__(self, address=0x40, debug=False): self.address = address self.debug = debug if (self.debug): - print "Reseting PCA9685" - self.i2c.bus.write_byte(0x00, 0x06) + print "Reseting PCA9685 MODE1 (without SLEEP) and MODE2" + self.setAllPWM(0, 0) + self.i2c.write8(self.__MODE2, self.__OUTDRV) + self.i2c.write8(self.__MODE1, self.__ALLCALL) + time.sleep(0.005) # wait for oscillator + mode1 = self.i2c.readU8(self.__MODE1) mode1 = mode1 & ~self.__SLEEP # wake up (reset sleep) self.i2c.write8(self.__MODE1, mode1) @@ -68,6 +84,9 @@ def setPWM(self, channel, on, off): self.i2c.write8(self.__LED0_OFF_L+4*channel, off & 0xFF) self.i2c.write8(self.__LED0_OFF_H+4*channel, off >> 8) - - - + def setAllPWM(self, on, off): + "Sets a all PWM channels" + self.i2c.write8(self.__ALL_LED_ON_L, on & 0xFF) + self.i2c.write8(self.__ALL_LED_ON_H, on >> 8) + self.i2c.write8(self.__ALL_LED_OFF_L, off & 0xFF) + self.i2c.write8(self.__ALL_LED_OFF_H, off >> 8)