PyB-to-PyB using I2C?

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Gordon_Hardman
Posts: 68
Joined: Sat May 03, 2014 11:31 pm

Re: PyB-to-PyB using I2C?

Post by Gordon_Hardman » Mon Mar 16, 2015 7:55 pm

At some point all of these leave the strictly lower level and need to address what the user is trying to do, and the consequences of, say, a corrupt block/packet of data. In previous projects, the data was real-time and was sent at a rate of 100 hz. It was important to reliably detect that a packet was bad, but then the consumer had to live with that until a new set of data showed up in msec. A little bit like a Kalman filter, in a way. If the data is terribly important, and an acknowledge/request for repeat is needed, that is different. On my project I used a combination of a Fletcher checksum and a so-called horizontal parity check. This was because it was computationally simple! I never saw it allow a bad block of data through. However, this chip has a hardware CRC genereator, which should be even better, if it could be used to protect a block or packet. But you are right, it needs a way to signal how long a block of data is going to be- or have begin and end flags of some kind... It should be malleable so that it can implemented in different ways for diffreent uses, I guess.

-Gordon

Gordon_Hardman
Posts: 68
Joined: Sat May 03, 2014 11:31 pm

Re: PyB-to-PyB using I2C?

Post by Gordon_Hardman » Mon Mar 16, 2015 9:31 pm

At some point all of these leave the strictly lower level and need to address what the user is trying to do, and the consequences of, say, a corrupt block/packet of data. In a previous project, the data was real-time and was sent at a rate of 100 hz. It was important to reliably detect that a packet was bad, but then the consumer had to live with that until a new set of data showed up in 10 msec. A little bit like a Kalman filter, in a way. If the data is terribly important, and an acknowledge/request for repeat is needed, that is different. On my project I used a combination of a Fletcher checksum and a so-called horizontal parity check. This was because it was computationally simple! I never saw it allow a bad block of data through. However, this chip has a hardware CRC genereator, which should be even better, if it could be used to protect a block or packet. But you are right, it needs a way to signal how long a block of data is going to be- or have begin and end flags of some kind... It should be malleable so that it can implemented in different ways for different uses, I guess.

-Gordon

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

Re: PyB-to-PyB using I2C?

Post by dhylands » Mon Mar 16, 2015 9:49 pm

My experience with i2c slaves is using the smbus protocol with a slave running on an ATMega128.

smbus limits the packet size to 255 bytes.

The smbus protocol has something called Block Read and Write which allow variable sized packets, but the packet size is part of the message.

For non-smbus transfer, my understanding is that the NAK at the end terminates the packet.

So I would expect the slave to do a recv for whatever its max is, and it may get less data.

I don't know exactly what the HAL supports.

Gordon_Hardman
Posts: 68
Joined: Sat May 03, 2014 11:31 pm

Re: PyB-to-PyB using I2C?

Post by Gordon_Hardman » Mon Mar 16, 2015 11:10 pm

I tested the following slave code, and it works as expected:

Code: Select all

i2cS = I2C(2, I2C.SLAVE)             # create and init as a slave
i2cS.init(I2C.SLAVE, addr = 0x55)     # init as a slave
print("Slave")

while True:
    data = []
    try:
        data = i2cS.recv(3, timeout=100) # 100 msec
    except:
        pass
    if data != []:
        print(data)
    else:
        print('.')

Gives the following on the VCP, when you send '123' on the master:
.
.
b'123'
.
.
.
.

The try/except is necessary because the timeout function actually throws an "OSerror: 116".
I will have to extend this in some fashion, I am still thinking it through. Maybe if I want to send 16 bytes, it is done in two stages- first send '0x10' and then send the actual block of data.

cloudformdesign
Posts: 35
Joined: Wed Mar 11, 2015 7:48 pm

Re: PyB-to-PyB using I2C?

Post by cloudformdesign » Sat May 02, 2015 4:07 pm

I'd like to do some testing with this and the asyncio library to see if we can get an asynchronous I2c socket. Has anybody tried this?

mosi
Posts: 24
Joined: Tue Oct 07, 2014 12:07 am

Re: PyB-to-PyB using I2C?

Post by mosi » Sat May 02, 2015 6:51 pm

Reporting similar issues.
I can not get the I2C SLAVE talking back to I2C MASTER.
However, both devices do work with a designated I2C slave digital potentiometer flawlessly.

Code: Select all

############## SLAVE device ###########
import pyb
from pyb import I2C
from pyb import Pin
pyb.freq(168000000)
i2c = pyb.I2C(2, I2C.SLAVE, addr=0x42)

while True:
  data = []
  try:
    data = i2c.recv(3, timeout=200) # 100 msec
  except:
    pass
  if data != []:
    print(data)
  else:
    pass

and master:

Code: Select all

import pyb
from pyb import I2C
pyb.freq(168000000)
#i2c = I2C(2, I2C.MASTER, baudrate=400000)
i2c = I2C(2, I2C.MASTER)
i2c.scan()
i2c.send('abc',addr=0x42,timeout=100000)
#i2c.send('abc',addr=0x42)
after hard reset:
1) run slave code
2) run master code

the following happens:
>>> i2c.scan()
[66]
>>> i2c.send('abc',addr=0x42,timeout=100000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: 116
>>> i2c.send('abc',addr=0x42,timeout=100000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: 16
>>> i2c.scan()
[]
MASTER can not see the SLAVE 0x42 on I2C.

Can anybody explain or replicate?

mosi
Posts: 24
Joined: Tue Oct 07, 2014 12:07 am

Re: PyB-to-PyB using I2C?

Post by mosi » Sat May 02, 2015 7:18 pm

Found the only solution that works, but the code is definitely buggy.
Follow the previous post for code setup
### MASTER:
>>> i2c.scan()
[]
### SLAVE:
>>> i2c
I2C(2, I2C.SLAVE, addr=0x42)
>>> i2c.recv(3, addr=0x00, timeout=122000)
###MASTER:
>>> i2c.send('abc',addr=0x42,timeout=100000)
###SLAVE:
b'def'

If you change slave to receive less than 3 chars,
IOSError: 16 and the I2C interface is fried until hard reset.
The reset must be then performed also on MASTER.

Why is i2c.scan() on MASTER empty, even when SLAVE is ready?

User avatar
pythoncoder
Posts: 3495
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: PyB-to-PyB using I2C?

Post by pythoncoder » Sun May 03, 2015 7:56 am

I2C master mode has had a lot of testing on the Pyboard with different devices and data lengths. My guess is that slave mode has been less used and the bug probably lies there.
Peter Hinch

User avatar
vdb_peter
Posts: 6
Joined: Mon Feb 11, 2019 12:51 am
Location: Melbourne

Re: PyB-to-PyB using I2C?

Post by vdb_peter » Sun Apr 07, 2019 5:25 am

Hi guys
Just wondering whether there's been any further development of the board to board I2C?

Personally, I'm using ESP8266.

My goal is to use 2 devices to monitor each other to improve up time.

Thanks

User avatar
devnull
Posts: 344
Joined: Sat Jan 07, 2017 1:52 am
Location: Singapore / Cornwall
Contact:

Re: PyB-to-PyB using I2C?

Post by devnull » Sun Apr 07, 2019 7:02 am

As far as I am aware, the 8266 does not support I2C client mode.

Post Reply