I2C , Robit Elecfreaks

Questions and discussion about running MicroPython on a micro:bit board.
Target audience: MicroPython users with a micro:bit.
francois69
Posts: 9
Joined: Mon Sep 23, 2019 4:38 pm

I2C , Robit Elecfreaks

Post by francois69 » Mon Sep 23, 2019 5:10 pm

Hi,
I am a french teacher and i bought a Micro:bit and a board robit V2.0. It is a board for m-bot
https://www.elecfreaks.com/learn-en/mic ... .html#file

I had to program with Python.
I try to power the 2 motors, they are driving by a I2C.
I find informations on Github : https://github.com/Tinkertanker/pxt-robit . But it is not Python.
I think the adress'motors is 64
I not able to undertand how write inside the buffer and what is the number who can command the motors.
I try this program but the motor don't turn and if i read the adress it is a mystery.

from microbit import *
sleep(200)
print(i2c.scan())
buf = bytearray(2)
buf[0] = 0x00
buf[1] = 0x45
i2c.write(64, buf)
print(i2c.read(64, 8))

>>> [25, 30, 64, 112, 114]
b'\x05\x05\x05\x05\x05\x05\x05\x05'
MicroPython v1.9.2-34-gd64154c73 on 2017-09-01; micro:bit v1.0.1 with nRF51822
Type "help()" for more information.

Is somebody can help me ? Thank you :roll:
François

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: I2C , Robit Elecfreaks

Post by jimmo » Tue Sep 24, 2019 11:32 am

hi,

I had a quick skim through https://github.com/Tinkertanker/pxt-rob ... r/robit.ts

It looks like the way this works is that the micro:bit connects to a https://cdn-shop.adafruit.com/datasheets/PCA9685.pdf which can PWM 16 channels (it's designed to control the brightness of 16 LEDs). The motors appear to be connected between channels 0+1 (left) and 2+3 (right).

So to turn the left motor forward, you turn on channel 0, and turn off channel 1. Backwards would be turn off channel 0, and turn on channel 1.

To talk to this device, like many I2C devices, you write values into registers. So this code:

Code: Select all

buf = bytearray(2)
buf[0] = 0x00
buf[1] = 0x45
i2c.write(64, buf)
writes the value 0x45 into the register 0x00. (on the device at address 64). (Confusingly there are two layers of addresses here -- devices on the bus, and register addresses).

The initialisation sequence seems to be:
- set the MODE1 register (reg address 0x00) to 0x00.
- set the on/off time of each channel to 0. Each channel has four registers (control byte 0, 1, 2, 3). See the setPwm method. This relies on the fact that if you write a longer buffer, it sequentially writes to the following registers. So the first channel starts at register address 0x06, which it writes four bytes to (so the buffer five bytes in total).
- Then to set the frequency of the PWM controller it reads the old value from the MODE1 register (reg address 0x00), then writes the MODE1 and PRESCALE (0xFE) registers. See the setFreq method in that code for how this works.

Then to set a motor speed, it uses setPwm for the two channels connected to that motor. With a on and off time corresponding to the desired speed and direction.

Sorry if this all sounds really complicated... because it is. When I teach this stuff it's a whole day, and in-person, with diagrams and demos and stuff. Please let me know if you have more questions and I can explain it in more detail.

francois69
Posts: 9
Joined: Mon Sep 23, 2019 4:38 pm

Re: I2C , Robit Elecfreaks

Post by francois69 » Tue Sep 24, 2019 11:29 pm

Thanks for your answer. I try this code :

from microbit import *
sleep(200)
i2c.write(64, b'\0x00\0x00') # Mode1= 0x00
sleep(1)
i2c.write(64, b'\0x06\0x00') # Channel 0(motors) off LED0_ON_L=0
i2c.write(64, b'\0x07\0x00') # Channel 0(motors) off LED0_ON_H=0
i2c.write(64, b'\0x08\0x00') # Channel 0(motors) off LED0_OFF_L=0
i2c.write(64, b'\0x09\0x00') # Channel 0(motors) off LED0_OFF_H=0
sleep(1)
i2c.write(64, b'\0x00\0x10') # Mode1, bit 4(sleep) = 1 (to change Prescaller)
sleep(1)
i2c.write(64, b'\0xFE\0x1E') # Prescaller = 0x1E (hasard)
sleep(1)
i2c.write(64, b'\0x00\0x00') # Mode1= 0x00

i2c.write(64, b'\0x06\0xFE')#
i2c.write(64, b'\0x07\0x07')# LED0_ON_L + LED0_ON_H = 7FE (2046)
i2c.write(64, b'\0x08\0xFE')
i2c.write(64, b'\0x09\0x07')# LED0_OFF_L + LED0_OFF_H = 7FE (2046) duty cycle = 50%

But nothing append. I don't understand. Is there an other register for the direction ?
François

francois69
Posts: 9
Joined: Mon Sep 23, 2019 4:38 pm

Re: I2C , Robit Elecfreaks

Post by francois69 » Wed Sep 25, 2019 7:58 am

Hello,
I think i have an other problem :
if i write inside the register and after i read the same register i don't find what i have write :
I write in register 0x06 and i try to read the 16 registers since the beginning :

from microbit import *
sleep(200)
i2c.write(64, b'\0x06\0x01\02\03')
sleep(1)
print(i2c.read(64, 16))

I find :

>>> b'\x10\x00\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00'
MicroPython v1.9.2-34-gd64154c73 on 2017-09-01; micro:bit v1.0.1 with nRF51822
Type "help()" for more information.
Strange ?
Is there a problem with the I2C frequency bus ?

francois69
Posts: 9
Joined: Mon Sep 23, 2019 4:38 pm

Re: I2C , Robit Elecfreaks

Post by francois69 » Fri Sep 27, 2019 10:11 pm

Can you help me please ? :D

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: I2C , Robit Elecfreaks

Post by dhylands » Fri Sep 27, 2019 11:44 pm

Looking at the datasheet, bit 5 of MODE1 is the "auto-increment" bit.

Since you've set it to zero, this means that when you ask to read starting at offset 64 for 8 bytes it will return register 64 8 times.
In order to read consecutive addresses, you need to set bit 5 of MODE1 to 1 first. Similarly, when you write, if you send multiple bytes they won't go into successive registers unless the auto increment bit is set.

Also to send binary data, 010203 use b'\x01\x02\x03' and NOT b'\0x01\0x02\0x03' The first one has a length of 3. The second one has a length of 12. This is because b'\x0x11' is the same thing as b'\x00' + b'x' + b'1' + b'1'

Also, if you forget the x (which some of your examples seem to do) then the data is treated as octal rather than hexidecimal.

i.e. b'\07' is not the same thing as b'\x07'

francois69
Posts: 9
Joined: Mon Sep 23, 2019 4:38 pm

Re: I2C , Robit Elecfreaks

Post by francois69 » Sat Sep 28, 2019 10:37 pm

thank you Dhylands for your answer
i can finally write and read inside the register :
my program :

from microbit import *
print(i2c.scan())
sleep(20)
# Mode1 : bit5=1 (auto increment enable)
# LED0_ON_L + LED0_ON_H = 7FE (2046) LED0_OFF_L + LED0_OFF_H = 7FE (2046)
# duty cycle = 50%
i2c.write(64, b'\x00\x20\x00\x00\x00\x00\x00\xfe\x07\xfe\x07\xfe\x07\xfe\x07')
sleep(1)
i2c.write(64, b'\x00')
print(i2c.read(64, 16))

result from print :

>>> [25, 30, 64]
b' \x00\x00\x00\x00\x00\xfe\x07\xfe\x07\xfe\x07\xfe\x07\x00\x00'
MicroPython v1.9.2-34-gd64154c73 on 2017-09-01; micro:bit v1.0.1 with nRF51822

But the motors M1 or M2 don't turn. I read again the datasheet and i can't find why.
Have you one idea ?
Frabçois

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: I2C , Robit Elecfreaks

Post by dhylands » Sun Sep 29, 2019 12:52 am

Are you using motor drivers? The PCA9685 is only rated for 40mA per channel. Your motors probably need alot more current than that.

francois69
Posts: 9
Joined: Mon Sep 23, 2019 4:38 pm

Re: I2C , Robit Elecfreaks

Post by francois69 » Sun Sep 29, 2019 7:08 am

Hello,
i am using a board :
https://www.elecfreaks.com/learn-en/mic ... .html#file
inside there is drivers. I have tried to program with makecode

https://makecode.microbit.org/v0/77088- ... 9763-13941
and the wheels turn
With makecode the wheels can turn foward or reverse.
So each motors are powered by a bridge. If i write only in 4 registers
exemple :
(LED0_ON_L + LED0_ON_H = 7FE (2046) LED0_OFF_L + LED0_OFF_H = 7FE (2046), duty cycle = 50%)
it is not possible to change the sens of rotation ?

francois69
Posts: 9
Joined: Mon Sep 23, 2019 4:38 pm

Re: I2C , Robit Elecfreaks

Post by francois69 » Fri Oct 04, 2019 7:14 am

would anyone have an idea ? :roll:

Post Reply