General Robotics

DFR0548 Driver Expansion Board for micro:bit

userHead Patrick.Gelinaud 2024-05-31 20:34:36 135 Views4 Replies

Hi,

 

I would like to use the driver FRR0548 on a micro with MicroPython. I have converted the JavaScript code to MicroPython, but it is not working. The driver works correctly under MakeCode. Can you help me? Here is the Python code:

 

import microbit
import time

PCA9685_ADDRESS = 0x40
MODE1 = 0x00
PRESCALE = 0xFE
LED0_ON_L = 0x06

# Énumération pour les moteurs CC
class Motors:
   M1 = 0x01
   M2 = 0x02
   M3 = 0x03
   M4 = 0x04

# Énumération pour la direction du moteur
class Dir:
   cw = 1
   ccw = -1

# Variable pour indiquer si le module PCA9685 a été initialisé
initialized = False

def init_pca9685():
   microbit.i2c.init()
   devices = microbit.i2c.scan()
   for addr in devices:
       print("Périphérique trouvé à l'adresse :", hex(addr))

   start = 0x07
   end = 0x70
   print("Scanning I2C bus...")
   for i in range(start, end + 1):
       try:
           microbit.i2c.read(i, 1)
       except OSError:
           pass
       else:
           print("Found:  [%s]" % hex(i))
   print("Scanning complete")
   set_freq(50)
   return True

def i2c_write(addr, reg : int, value):
   print(value)
   buf = bytearray(2)
   buf[0] = reg
   buf[1] = value
   print("microbit.i2c.write", PCA9685_ADDRESS, buf)
   microbit.i2c.write(PCA9685_ADDRESS, buf)

def i2c_read(addr: int, reg: int):
   val = bytes(1)
   print("i2c_read",bytes(val))
   val = microbit.i2c.read(addr, 1, repeat=False)
   print("i2c_read",bytes(val))
   return val

def set_freq(freq):
   print("set_freq")
   prescaleval = 25000000
   prescaleval /= 4096
   prescaleval /= freq
   prescaleval -= 1
   prescale = int(prescaleval)
   olmoode = bytes(1)
   oldmode= i2c_read(PCA9685_ADDRESS, MODE1)
   print("oldmode",oldmode)
   newmode = (int.from_bytes(oldmode, 'big') & 0x7F) | 0x10
   print("newmode",newmode)
   i2c_write(PCA9685_ADDRESS, MODE1, newmode)  # go to sleep
   print("prescale",prescale)
   i2c_write(PCA9685_ADDRESS, PRESCALE, prescale)  # set the prescaler
   print("oldmode", oldmode)
   time.sleep(5)
   i2c_write(PCA9685_ADDRESS, MODE1, int.from_bytes(oldmode, 'big') | 0xa1)

def set_pwm(channel, on, off):
   if channel < 0 or channel > 15:
       return

   buf = bytearray(5)
   buf[0] = LED0_ON_L + 4 * channel
   buf[1] = on & 0xff
   buf[2] = (on >> 8) & 0xff
   buf[3] = off & 0xff
   buf[4] = (off >> 8) & 0xff
   if buf:
       print("microbit.i2c.write(" + hex(PCA9685_ADDRESS) + ", " + "/".join(hex(v) for v in buf) + ")")
   microbit.i2c.write(PCA9685_ADDRESS, buf)

def MotorRun(index: int, direction: int, speed: int):
   speed = speed * 16 * direction;
   if (speed >= 4096):
       speed = 4095

   if (speed <= -4096):
       speed = -4095

   if (index > 4 or index <= 0):
       return

   pn = (4 - index) * 2
   pp = (4 - index) * 2 + 1
   print("speed", speed, pn, pp)
   if (speed >= 0):
       set_pwm(pp, 0, speed)
       set_pwm(pn, 0, 0)
   else:
       set_pwm(pp, 0, 0)
       set_pwm(pn, 0, -speed)

initialized = init_pca9685()
time.sleep(3)
MotorRun(Motors.M1, Dir.cw, 100)

 

2024-06-04 17:50:39

I am seeking your help with an issue I am facing in the development of a Python driver for the DFR0548 card. I have managed to write a first code in Python based on the existing JavaScript driver. However, I could not find any technical documentation detailing the frames to be sent in I2C, which makes the task more challenging.

My goal is to control the motors and servomotors using my Python driver. I have succeeded in making them work with makecode, but I can't get it to work in Python. I don't understand where the problem is coming from, and I would appreciate your informed opinion.

 

Moreover, I have been able to code the digital outputs and the analog  outputs without any difficulty. On the other hand, I am encountering difficulties with the peripherals on the I2C bus.

 

I am attaching my Python code along with the frames sent on the I2C bus to this message. If anyone has already encountered this type of problem or if you have any ideas to help me resolve this anomaly, I am open to any suggestions.

I would also be delighted if some of you could test my first code and share your feedback with me.

 

Thank you in advance for your valuable help.

 

python code :

 

import microbit
import time

PCA9685_ADDRESS = 0x40
MODE1 = 0x00
PRESCALE = 0xFE
LED0_ON_L = 0x06

# Enum for DC Motors
class Motors:
   M1 = 0x01
   M2 = 0x02
   M3 = 0x03
   M4 = 0x04

# Enum for Motor Direction
class Dir:
   cw = 1
   ccw = -1

class Servos:
   S1 = 0x08
   S2 = 0x07
   S3 = 0x06
   S4 = 0x05
   S5 = 0x04
   S6 = 0x03
   S7 = 0x02
   S8 = 0x01

isDebug = True
def DebugWrite(addr, buf):
   if isDebug :
       if buf:
           print("microbit.i2c.write(" + hex(addr) +
                 "," + "/".join(hex(v) for v in buf) + ")")

def DebugRead(addr, result):
   if isDebug :
       if result :
           print("microbit.i2c.read")
def DebugMess(mess):
   if isDebug :
       if mess :
           print(mess)

# Variable to indicate if the PCA9685 module has been initialized
initialized = False

def init_pca9685():
   microbit.i2c.init(freq=100000)
   devices = microbit.i2c.scan()
   for addr in devices:
       print("Device found at address:", hex(addr))
   if PCA9685_ADDRESS not in devices:
       print("PCA9685 not found.")
       return False

   print("PCA9685 found. Initializing...")
   set_freq(50)
   return True

def i2c_write(addr, reg, value):
   buf = bytearray(2)
   buf[0] = reg
   buf[1] = value
   DebugWrite(addr, buf)
   microbit.i2c.write(addr, buf)

def i2c_read(addr, reg):
   DebugWrite(addr, bytearray([reg]))
   microbit.i2c.write(addr, bytearray([reg]))
   val = microbit.i2c.read(addr, 1)
   DebugRead(addr, val)
   return val

def set_freq(freq):
   DebugMess("set_freq")
   prescaleval = 25000000
   prescaleval /= 4096
   prescaleval /= freq
   prescaleval -= 1
   prescale = int(prescaleval + 0.5)  # Rounding up

   oldmode = i2c_read(PCA9685_ADDRESS, MODE1)
   newmode = (oldmode[0] & 0x7F) | 0x10  # sleep
   i2c_write(PCA9685_ADDRESS, MODE1, newmode)  # go to sleep
   i2c_write(PCA9685_ADDRESS, PRESCALE, prescale)  # set the prescaler
   i2c_write(PCA9685_ADDRESS, MODE1, oldmode[0])
   time.sleep(0.005)
   i2c_write(PCA9685_ADDRESS, MODE1, oldmode[0] | 0x80)
   # i2c_write(PCA9685_ADDRESS, MODE1, oldmode[0] | 0xa1)

def set_pwm(channel, on, off):
   if channel < 0 or channel > 15:
       return

   buf = bytearray(5)
   buf[0] = LED0_ON_L + 4 * channel
   buf[1] = on & 0xff
   buf[2] = (on >> 8) & 0xff
   buf[3] = off & 0xff
   buf[4] = (off >> 8) & 0xff
   DebugWrite(PCA9685_ADDRESS, buf)
   microbit.i2c.write(PCA9685_ADDRESS, buf)

def motorRun(index, direction, speed):
   DebugMess("MotorRun")
   speed = speed * 16 * direction
   if speed >= 4096:
       speed = 4095
   elif speed <= -4096:
       speed = -4095

   if index > 4 or index <= 0:
       return

   pn = (4 - index) * 2
   pp = (4 - index) * 2 + 1
   if speed >= 0:
       set_pwm(pp, 0, speed)
       set_pwm(pn, 0, 0)
   else:
       set_pwm(pp, 0, 0)
       set_pwm(pn, 0, -speed)

def motorStop(index):
   DebugMess("MotorStop")
   set_pwm((4 - index) * 2, 0, 0)
   set_pwm((4 - index) * 2 + 1, 0, 0)

def motorStopAll():
   DebugMess("MotorStopAll")
   for idx in range(1, 5, 1):
       motorStop(idx)

def servo(index, degree):
   DebugMess("Servo")
   v_us = (degree * 1800 / 180 + 600)
   value = v_us * 4096 / 20000
   set_pwm(index + 7, 0, int(value))

initialized = init_pca9685()
time.sleep(1)
if initialized:
   motorRun(Motors.M1, Dir.cw, 255)
   time.sleep(5)
   motorStopAll()
   servo(Servos.S1, 20)
   time.sleep(1)
   servo(Servos.S1, 90)
   time.sleep(1)
   servo(Servos.S1, 160)
   time.sleep(1)

else:
   print("Initialization failed.")

 

Frames sent :
MicroPython v1.15-64-g1e2f0d280 on 2021-06-30; micro:bit v2.0.0 with nRF52833

Type "help()" for more information.

>>> Device found at address: 0x40

Device found at address: 0x70

PCA9685 found. Initializing...

set_freq

microbit.i2c.write(0x40,0x0)

microbit.i2c.read

microbit.i2c.write(0x40,0x0/0x31)

microbit.i2c.write(0x40,0xfe/0x79)

microbit.i2c.write(0x40,0x0/0x31)

microbit.i2c.write(0x40,0x0/0xb1)

MotorRun

microbit.i2c.write(0x40,0x22/0x0/0x0/0xf0/0xf)

microbit.i2c.write(0x40,0x1e/0x0/0x0/0x0/0x0)

MotorStopAll

MotorStop

microbit.i2c.write(0x40,0x1e/0x0/0x0/0x0/0x0)

microbit.i2c.write(0x40,0x22/0x0/0x0/0x0/0x0)

MotorStop

microbit.i2c.write(0x40,0x16/0x0/0x0/0x0/0x0)

microbit.i2c.write(0x40,0x1a/0x0/0x0/0x0/0x0)

MotorStop

microbit.i2c.write(0x40,0xe/0x0/0x0/0x0/0x0)

microbit.i2c.write(0x40,0x12/0x0/0x0/0x0/0x0)

MotorStop

microbit.i2c.write(0x40,0x6/0x0/0x0/0x0/0x0)

microbit.i2c.write(0x40,0xa/0x0/0x0/0x0/0x0)

Servo

microbit.i2c.write(0x40,0x42/0x0/0x0/0xa3/0x0)

Servo

microbit.i2c.write(0x40,0x42/0x0/0x0/0x33/0x1)

Servo

microbit.i2c.write(0x40,0x42/0x0/0x0/0xc2/0x1)

MicroPython v1.15-64-g1e2f0d280 on 2021-06-30; micro:bit v2.0.0 with nRF52833

Type "help()" for more information.

>>>

userHeadPic Patrick.Gelinaud
2024-06-02 22:28:35

Thanks for the python code suggestion which I tested immediately.

This new code doesn't work either. Here are the traces of the frames sent to DFR0548 Driver by the python code. Or I can find some documentation on what information to send to DFR0548 on the I2C bus. 

 

Thanking you in advance for your assistance

 

MicroPython v1.15-64-g1e2f0d280 on 2021-06-30; micro:bit v2.0.0 with nRF52833

Type "help()" for more information.

>>>

>>> Device found at address: 0x40

Device found at address: 0x70

PCA9685 found. Initializing...

set_freq

microbit.i2c.write(0x40,0x0)

microbit.i2c.read

microbit.i2c.write(0x40,0x0/0x11)

microbit.i2c.write(0x40,0xfe/0x79)

microbit.i2c.write(0x40,0x0/0x11)

microbit.i2c.write(0x40,0x0/0x91)

MotorRun

microbit.i2c.write(0x40,0x22/0x0/0x0/0x40/0x6)

microbit.i2c.write(0x40,0x1e/0x0/0x0/0x0/0x0)

userHeadPic Patrick.Gelinaud
2024-06-01 23:43:53

You can edit your code like this:

import microbit
import time

PCA9685_ADDRESS = 0x40
MODE1 = 0x00
PRESCALE = 0xFE
LED0_ON_L = 0x06

# Enum for DC Motors
class Motors:
  M1 = 0x01
  M2 = 0x02
  M3 = 0x03
  M4 = 0x04

# Enum for Motor Direction
class Dir:
  cw = 1
  ccw = -1

# Variable to indicate if the PCA9685 module has been initialized
initialized = False

def init_pca9685():
  microbit.i2c.init(freq=100000)
  devices = microbit.i2c.scan()
  for addr in devices:
      print("Device found at address:", hex(addr))
  if PCA9685_ADDRESS not in devices:
      print("PCA9685 not found.")
      return False

  print("PCA9685 found. Initializing...")
  set_freq(50)
  return True

def i2c_write(addr, reg, value):
  buf = bytearray(2)
  buf[0] = reg
  buf[1] = value
  microbit.i2c.write(addr, buf)

def i2c_read(addr, reg):
  microbit.i2c.write(addr, bytearray([reg]))
  val = microbit.i2c.read(addr, 1)
  return val

def set_freq(freq):
  prescaleval = 25000000
  prescaleval /= 4096
  prescaleval /= freq
  prescaleval -= 1
  prescale = int(prescaleval + 0.5)  # Rounding up

  oldmode = i2c_read(PCA9685_ADDRESS, MODE1)
  newmode = (oldmode[0] & 0x7F) | 0x10  # sleep
  i2c_write(PCA9685_ADDRESS, MODE1, newmode)  # go to sleep
  i2c_write(PCA9685_ADDRESS, PRESCALE, prescale)  # set the prescaler
  i2c_write(PCA9685_ADDRESS, MODE1, oldmode[0])
  time.sleep(0.005)
  i2c_write(PCA9685_ADDRESS, MODE1, oldmode[0] | 0x80)

def set_pwm(channel, on, off):
  if channel < 0 or channel > 15:
      return

  buf = bytearray(5)
  buf[0] = LED0_ON_L + 4 * channel
  buf[1] = on & 0xff
  buf[2] = (on >> 8) & 0xff
  buf[3] = off & 0xff
  buf[4] = (off >> 8) & 0xff
  microbit.i2c.write(PCA9685_ADDRESS, buf)

def MotorRun(index, direction, speed):
  speed = speed * 16 * direction
  if speed >= 4096:
      speed = 4095
  elif speed <= -4096:
      speed = -4095

  if index > 4 or index <= 0:
      return

  pn = (4 - index) * 2
  pp = (4 - index) * 2 + 1
  if speed >= 0:
      set_pwm(pp, 0, speed)
      set_pwm(pn, 0, 0)
  else:
      set_pwm(pp, 0, 0)
      set_pwm(pn, 0, -speed)

initialized = init_pca9685()
time.sleep(1)
if initialized:
  MotorRun(Motors.M1, Dir.cw, 100)
else:
  print("Initialization failed.")
 

userHeadPic lia.ifat
Patrick.Gelinaud wrote:

Thanks for the python code suggestion which I tested immediately.

This new code doesn't work either. Here are the traces of the frames sent to DFR0548 Driver by the python code. Or I can find some documentation on what information to send to DFR0548 on the I2C bus. 

 

Thanking you in advance for your assistance

 

MicroPython v1.15-64-g1e2f0d280 on 2021-06-30; micro:bit v2.0.0 with nRF52833

Type "help()" for more information.

>>>

>>> Device found at address: 0x40

Device found at address: 0x70

PCA9685 found. Initializing...

set_freq

microbit.i2c.write(0x40,0x0)

microbit.i2c.read

microbit.i2c.write(0x40,0x0/0x11)

microbit.i2c.write(0x40,0xfe/0x79)

microbit.i2c.write(0x40,0x0/0x11)

microbit.i2c.write(0x40,0x0/0x91)

MotorRun

microbit.i2c.write(0x40,0x22/0x0/0x0/0x40/0x6)

microbit.i2c.write(0x40,0x1e/0x0/0x0/0x0/0x0)

2024-06-02 22:29:42
1 Replies