Trying PCA9685 Capes/Hats and BeagleY-AI?

Hey…

So, I am using this source code:

#!/usr/bin/python3

from time import sleep
import math
import smbus

# ============================================================================
# PCA9685 16-Channel PWM Servo Driver
# ============================================================================

class PCA9685:

  # Registers/etc.
  __SUBADR1            = 0x02
  __SUBADR2            = 0x03
  __SUBADR3            = 0x04
  __MODE1              = 0x00        # Line 500
  __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

  def __init__(self, address, debug=False):
    self.bus = smbus.SMBus(2)
    self.address = address
    self.debug = debug
    if (self.debug):
      print("Reseting PCA9685")
    self.write(self.__MODE1, 0x00)

  def write(self, reg, value):
    "Writes an 8-bit value to the specified register/address"
    self.bus.write_byte_data(self.address, reg, value)
    if (self.debug):
      print("I2C: Write 0x%02X to register 0x%02X" % (value, reg))

  def read(self, reg):
    "Read an unsigned byte from the I2C device"
    result = self.bus.read_byte_data(self.address, reg)
    if (self.debug):
      print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % (self.address, result & 0xFF, reg))
    return result

  def setPWMFreq(self, freq):
    "Sets the PWM frequency"
    prescaleval = 25000000.0    # 25MHz
    prescaleval = prescaleval / 4096.0       # 12-bit
    prescaleval = prescaleval / float(freq)
    prescaleval = prescaleval - 1.0
    if (self.debug):
      print("Setting PWM frequency to %d Hz" % freq)
      print("Estimated pre-scale: %d" % prescaleval)
    prescale = math.floor(prescaleval + 0.5)
    if (self.debug):
      print("Final pre-scale: %d" % prescale)

    oldmode = self.read(self.__MODE1);
    newmode = (oldmode & 0x7F) | 0x10        # sleep
    self.write(self.__MODE1, newmode)        # go to sleep
    self.write(self.__PRESCALE, int(math.floor(prescale)))
    self.write(self.__MODE1, oldmode)
    sleep(0.005)
    self.write(self.__MODE1, oldmode | 0x80)

  def setPWM(self, channel, on, off):
    "Sets a single PWM channel"
    self.write(self.__LED0_ON_L + 4*channel, on & 0xFF)
    self.write(self.__LED0_ON_H + 4*channel, 0xff & (on >> 8))
    self.write(self.__LED0_OFF_L + 4*channel, off & 0xFF)
    self.write(self.__LED0_OFF_H + 4*channel, 0xff & (off >> 8))
    if (self.debug):
      print("channel: %d  LED_ON: %d LED_OFF: %d" % (channel,on,off))

  def setDutycycle(self, channel, pulse):
    self.setPWM(channel, 0, int(pulse * int(4096 / 100)))

  def setLevel(self, channel, value):
    if (value == 1):
      self.setPWM(channel, 0, 4095)
    else:
      self.setPWM(channel, 0, 0)

When I use this line and report to my PCA9685 Cape (Servo Cape), it seems that 0x00 does not like to be called or used…

This line: __MODE1 = 0x00 # Line 500

I added the comment # Line 500 to be distinctive only.

So, the source code, not the called source code and not PCA9685.py by grippy98, I use on this endeavor was gathered by the docs.beagleboard.org pages online here as this and:

#!/usr/bin/python

from PCA9685 import PCA9685
import time

Dir = [
    'forward',
    'backward',
]
pwm = PCA9685(0x40, debug=False)
pwm.setPWMFreq(50)

class MotorDriver():
    def __init__(self):
        # Match these to your particular HAT!
        self.PWMA = 0
        self.AIN1 = 2
        self.AIN2 = 1
        self.PWMB = 5
        self.BIN1 = 3
        self.BIN2 = 4

    def MotorRun(self, motor, index, speed):
        if speed > 100:
            return
        if(motor == 0):
            pwm.setDutycycle(self.PWMA, speed)
            if(index == Dir[0]):
                print ("1")
                pwm.setLevel(self.AIN1, 0)
                pwm.setLevel(self.AIN2, 1)
            else:
                print ("2")
                pwm.setLevel(self.AIN1, 1)
                pwm.setLevel(self.AIN2, 0)
        else:
            pwm.setDutycycle(self.PWMB, speed)
            if(index == Dir[0]):
                print ("3")
                pwm.setLevel(self.BIN1, 0)
                pwm.setLevel(self.BIN2, 1)
            else:
                print ("4")
                pwm.setLevel(self.BIN1, 1)
                pwm.setLevel(self.BIN2, 0)

    def MotorStop(self, motor):
        if (motor == 0):
            pwm.setDutycycle(self.PWMA, 0)
        else:
            pwm.setDutycycle(self.PWMB, 0)

print("this is a motor driver test code")
Motor = MotorDriver()

print("forward 2 s")
Motor.MotorRun(0, 'forward', 100)
Motor.MotorRun(1, 'forward', 100)
time.sleep(2)

print("backward 2 s")
Motor.MotorRun(0, 'backward', 100)
Motor.MotorRun(1, 'backward', 100)
time.sleep(2)

print("stop")
Motor.MotorStop(0)
Motor.MotorStop(1)

and…the location in the docs is this item: Using PCA9685 Motor Drivers — BeagleBoard Documentation

The reason I bring it up…

  1. I made a funny bot.
  2. The funny bot was almost exclusively working for me but the trapeze act had it fall to doom.
  3. And fun is in order!

Now…I will try to explain this notion as well as possible:

  • class PCA9685 with __MODE1 = 0x00 makes the BeagleY-AI cancel itself.
  • The board ceases. It just dies and does not care to live.

The issue I have is that I would like to board to live past this circumstance of calling my source from the docs. from the PCA9685.py file without the board dying on me.

I can set __MODE1 to whatever and have the board understand not to die out. But, I think I need the /dev/i2c-2 for my i2c device to be recognized at 0x40. Am I wrong about that last sentence?

Seth

P.S. It is not complicated but I seem to miss key aspects to this build that are not allowing me to handle the complete and complex build.

Is the Servo Cape even supposed to work any longer? I will try some more configurations and then stall for a bit on this effort.

If anyone has any words of wisdom, shoot me a couple lines. Thank you.

The issue now, __MODE1 cannot be 0x00 and/or 0x01 but I think I can get away with 0x10. I will reread the datasheet and keep at it while people think about replying.

Seth

This has sort of been solved as the PCA9685 on the Servo Cape may need an up-to-date DTS set of files associated with what is available on the BeagleY-AI.

Slow to DTS is happening on my shift these days. So, I am calling this solved since the board dies when running source, the above mentioned source, and using any of the listed i2c devices on the BeagleY-AI for now.