I2C , Robit Elecfreaks
-
- Posts: 9
- Joined: Mon Sep 23, 2019 4:38 pm
I2C , Robit Elecfreaks
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
François
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
François
Re: I2C , Robit Elecfreaks
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:
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.
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)
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.
-
- Posts: 9
- Joined: Mon Sep 23, 2019 4:38 pm
Re: I2C , Robit Elecfreaks
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
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
-
- Posts: 9
- Joined: Mon Sep 23, 2019 4:38 pm
Re: I2C , Robit Elecfreaks
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 ?
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 ?
-
- Posts: 9
- Joined: Mon Sep 23, 2019 4:38 pm
Re: I2C , Robit Elecfreaks
Can you help me please ?
Re: I2C , Robit Elecfreaks
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'
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'
-
- Posts: 9
- Joined: Mon Sep 23, 2019 4:38 pm
Re: I2C , Robit Elecfreaks
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
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
Re: I2C , Robit Elecfreaks
Are you using motor drivers? The PCA9685 is only rated for 40mA per channel. Your motors probably need alot more current than that.
-
- Posts: 9
- Joined: Mon Sep 23, 2019 4:38 pm
Re: I2C , Robit Elecfreaks
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 ?
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 ?
-
- Posts: 9
- Joined: Mon Sep 23, 2019 4:38 pm
Re: I2C , Robit Elecfreaks
would anyone have an idea ?