0

networking CircuitPython boards together (using i2c?)
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

networking CircuitPython boards together (using i2c?)

by kstillson on Wed Mar 31, 2021 11:25 pm

For a maker/art project, I need a bunch of microcontrollers, preferably CircuitPython-based, networked together (using a minimal number of wires) I've been using a chain of uart/serial connections: each node relaying commands down and responses back; effectively implementing my own app-layer mesh network, and it's a real pain.

What I would love is something like a bunch of QtPy style boards connected through their Stemma/QT ports, used for both power and data. I bought several QyPy SAMD21 boards, and quickly discovered that they are missing the I2CPERIPHERAL library. i.e., they can be I2c masters, but not clients. With some effort, I recompiled the U2F firmware image for the QtPy boards, adding CIRCUITPY_I2CPERIPHERAL=1 and removing CIRCUITPY_USB_HID=0 to make space. This does actually work- I can get I2C messages from one board to another in Python. But the SAMD21 boards just don't have enough RAM to run my real application.

I'm looking forward to the QtPy RP2040 boards, which will have plenty of RAM. In the meantime, I got a RP2040 Feather board. It is also missing the I2CPERIPHERAL library. I tried the same trick- but after hours fighting with the firmware build system, I just can't get it to work- there are literally hundreds of errors when I run the "make": conflicting types, missing includes, something about unsupported shift registers in Thumb mode.. I've no idea how to tackle these.

Surely I'm not the only one who needs a bunch of CircuitPython controllers to talk to each other.. I thought Stemma/QT and I2C seemed ideal for this, but now I'm not sure.

Any thoughts on either how to make I2C work between CircuitPython boards, or perhaps whether there's some completely different approach that's likely easier?
Thanks in advance!

- Ken

kstillson
 
Posts: 15
Joined: Tue Feb 04, 2014 1:48 am

Re: networking CircuitPython boards together (using i2c?)

by blnkjns on Thu Apr 01, 2021 10:32 am

Strange. Do you mind trying the arduino IDE? Setting up I2C devices there is really easy:
Code: Select all | TOGGLE FULL SIZE
void setup(){
  Wire.begin(0x1a);
  Wire.onRequest(doThis);
}

void doThis(){
  Wire.println("Hello, I'm module 0x1a");
}

This basically sets a board as client on address 0x1a (you can change this as you like), and ties function doThis to incomming requests!
You can even let the host board do all the talking in Python.

blnkjns
 
Posts: 304
Joined: Fri Oct 02, 2020 3:33 am

Re: networking CircuitPython boards together (using i2c?)

by tannewt on Thu Apr 01, 2021 5:50 pm

kstillson wrote:I'm looking forward to the QtPy RP2040 boards, which will have plenty of RAM. In the meantime, I got a RP2040 Feather board. It is also missing the I2CPERIPHERAL library. I tried the same trick- but after hours fighting with the firmware build system, I just can't get it to work- there are literally hundreds of errors when I run the "make": conflicting types, missing includes, something about unsupported shift registers in Thumb mode.. I've no idea how to tackle these.


I2CPeripheral is disabled on RP2040 because it hasn't been implemented yet. It's not a high priority for us but I added an issue to track it: https://github.com/adafruit/circuitpython/issues/4536

kstillson wrote:Surely I'm not the only one who needs a bunch of CircuitPython controllers to talk to each other.. I thought Stemma/QT and I2C seemed ideal for this, but now I'm not sure.

Any thoughts on either how to make I2C work between CircuitPython boards, or perhaps whether there's some completely different approach that's likely easier?
Thanks in advance!


You might want to look at CAN. The Feather CAN is in stock: https://www.adafruit.com/product/4759

CAN allows you to power each end separately and is designed to be noise resistant in an automotive environment. Each peer is on equal footing so it may be easier to manage than the uart ring.

tannewt
 
Posts: 2349
Joined: Thu Oct 06, 2016 8:48 pm

Re: networking CircuitPython boards together (using i2c?)

by kstillson on Thu Apr 01, 2021 8:46 pm

blnkjns wrote:Strange. Do you mind trying the arduino IDE? Setting up I2C devices there is really easy


Hi blnkjns- interesting idea. I really prefer Python, but I suppose I could go back to Arduino/C++, and perhaps it wouldn't be that bad if the master can stay in Python. I was able to get basic master and client sketches using Wire.h to compile, although I haven't yet been able to get it to work just yet. For some reason, my client never calls the callback (so the master's Wire.available() always returns false). Not sure what's wrong here, but I'll continue to play with it; probably something silly I'm doing wrong..

Anyway-- Thanks!! I'll dig in this direction until i2cperipheral gets implemented for the RP2040.

- Ken

kstillson
 
Posts: 15
Joined: Tue Feb 04, 2014 1:48 am

Re: networking CircuitPython boards together (using i2c?)

by kstillson on Thu Apr 01, 2021 8:58 pm

tannewt wrote:I2CPeripheral is disabled on RP2040 because it hasn't been implemented yet. It's not a high priority for us but I added an issue to track it: https://github.com/adafruit/circuitpython/issues/4536


ah- well, I guess that explains why I was having so much trouble getting it to compile! :-D

Thank you very much for opening the tracking item; I'll subscribe to that and eagerly await updates, although I take it holding my breath isn't recommended. ;-)

tannewt wrote:You might want to look at CAN. The Feather CAN is in stock: https://www.adafruit.com/product/4759 CAN allows you to power each end separately and is designed to be noise resistant in an automotive environment. Each peer is on equal footing so it may be easier to manage than the uart ring.


hmm.. Thanks for the idea, although I don't think it's ideal for my use-case. I'm likely to end up with a fair number of nodes on the network, and so I'd really like them to be as small and inexpensive as possible, and QtPy's are just ideal, especially if I can use those lovely Stemma/QT connectors. So I guess for now I'll try blnkjns's suggestion- revert from Python back to Arduino, and use the Wire.h library, at least on the clients. I suppose the plus side is that the SAMD21 boards might actually have enough RAM if I work hard on optimizing my client-side C++.

Thanks again for setting up the tracking issue, and for the quick and definitive reply.. It would really be wonderful to be able to do easy multi-node networking on the QtPy2040 boards once their available! I'm almost tempted to ask if I can help, but my C++ is sufficiently rusty that I suspect I'd need more help than I'd provide when trying to generate a library of sufficient quality for general-purpose use.

Best regards,

- Ken

kstillson
 
Posts: 15
Joined: Tue Feb 04, 2014 1:48 am

Re: networking CircuitPython boards together (using i2c?)

by tannewt on Fri Apr 02, 2021 12:02 pm

How far apart are the nodes? Aka, how much wire will be between them? You may have signal integrity issues with I2C if they are far apart.

tannewt
 
Posts: 2349
Joined: Thu Oct 06, 2016 8:48 pm

Re: networking CircuitPython boards together (using i2c?)

by kstillson on Fri Apr 02, 2021 4:53 pm

Thanks to both of ya.. I did eventually get things working with a CircuitPython based master and Arduino based client.

My initial problem was that when the QtPy boards are connected directly to each other through Stemma/QT, none of the boards have SDA/SCL pull-up resistors. Once I added those, it's just a bunch of fussing with string to bytearray conversions and how to get the response lengths interpreted correctly.

Thanks for reminding me about the concern wrt I2c bus length. My individual nodes are less than a meter apart, but the overall bus will be longer, and I take it that might cause problems. I did note that Sparkfun has a I2c range extender, although given its price, I'm not sure it's ideal for my node count.. Anyway, now I know to watch out for issues as the physical size of the network grows.

The main problem I have with my current serial solution is that passing signals node-to-node is really slow and unreliable. I know it's possible to have one transmitter and many receivers in uart, the problem is there's no easy way to get replies because if you connect multiple client reply TX pins together, they interfere with each other. I'm wondering if I can cheat by connecting a pin from all the clients together, all those pins set as gpio inputs by default, and when a particular client needs to send a message to the master, it quickly changes the pin to uart TX, sends it's message, then swaps the pin back to input mode. This client-response bus then gets connected to the master's RX pin. I can easily enough arrange it at the protocol level that no two clients will ever try to send a reply simultaneously. Anyway, I think I'll play around with this and see how it goes.

I've confirmed that alas the QtPy won't let me use the D4/D5 (i2c) pins for serial, so even if I can get my multi-sender uart system to work, I' won't be able to use the lovely Stemma/QT connectors.. oh well..

ok- I've got two avenues to play with now- proper i2c until I hit length constraints, and then perhaps my uart frankenstein.

Thanks again!

- Ken

kstillson
 
Posts: 15
Joined: Tue Feb 04, 2014 1:48 am

Please be positive and constructive with your questions and comments.