Richard-Gemmell / teensy4_i2c

An I2C library for the Teensy 4. Provides slave and master mode.
MIT License
92 stars 20 forks source link

I2C higher speed modes #14

Closed sacreyoubeurt closed 3 years ago

sacreyoubeurt commented 3 years ago

Hi Richard, first I wanted to thank you for your great teensy4 I2C library.

I and 2 other guys are working on a project of MIDI modular controller. A master unit communicates thru Teensy usbMIDI with audio software on a computer. Slave units handles the actual controlling parts (knobs, encoders etc.) and communicate with master using I2C.

MIDI send and MIDI feedback are working quite okay. But we are facing issues when computer sends a lot of MIDI feedback to master unit (like more than 10 control change values continuously changing) and it tries to send it back to slaves. Feedback data to slave looks ok but data from slave to master becomes inaccurate (example 1 control change value continuously changing). Given that usbMIDI is most faster (I read 12Mbits minimum) than I2C, we feel like I2C is certainly saturated in this operation.

So we thought :

We read you thought about implementing higher speed modes like 3.4 Mbps and 5 Mbps. Do you think you could do this in a near future ? We would be most grateful if you do.

Thank you in advance for your reply. Best regards,

sacreyoubeurt commented 3 years ago

To complete my previous post, we use :

Best regards,

Richard-Gemmell commented 3 years ago

Hi, I glad to hear that the library is useful for you. Thanks for mentioning it.

I wasn't planning to support speeds higher than 1 Mbps. This is partly because I'm not sure that it would make a significant difference. nox771 made some interesting graphs of I2C data transfer rates. (Scroll down a bit to see the graphs.) If his data applies to the Teensy 4 then increasing the I2C clock speed from 1 MHz to 5 MHz would only increase the transfer rate by about 50%. (From 70 kB/s to 100 kB/s)

I'll consider supporting faster modes if this increase in transfer rates would make a significant difference to your project. If you need significantly higher transfer rates than this then you might need to use a different protocol.

It's possible that you can resolve your issue by rationing use of the I2C bus. Perhaps you can sample slider positions at a lower frequency or ignore repeated MIDI messages. If you haven't done so already, you could estimate how much data you need to send from the slave Teensy to the master and vice versa. I2C is half-duplex so you need to split the bandwidth between send and receive. If the numbers look less than the expected throughput then you might have some other problem.

I2C isn't very reliable so you might be getting corrupted messages. I get about 1 error in every 1,000,000 messages on my project but I've seen error rates as bad as 1 error for every 3 messages. Consider running a reliability test to find the error rate for your setup. (I just ping a message backwards and forwards and check it after transfer.) You might need to design your project to cope with corrupted messages.

You might also be having problems with concurrency. I2C messages are received asynchronously. If you're not careful, you can end up reading your message buffer while it's receiving another message. You end up getting half of one message and half of the next.

I hope this helps a little. Please let me know how much data you need to transfer between your Teensies.

cheers, Richard

Richard-Gemmell commented 3 years ago

I apologise in advance if you've already checked those things. R

sacreyoubeurt commented 3 years ago

Hi Richard, Thank you for your replies and sorry for the delay. We moved on other points of the project and don't work full time on it.

Regarding the information you gave about transfer rates, increasing the i2C clock doesn't look like the best way to reach our goal.

As you do, we thought about filtering MIDI entering data but MIDI feedback is sometimes a single message, i.e. a single CC value, along a tempest of other CC values, but this first one is still essential. So some sort of "polling" usbMIDI every 1 ms would take the risk to miss it. So we thought we could filter each one of the CC values, i.e Ch1 CC0, Ch1 CC1 etc. depending of how much values of each one is coming but that looks terribly laborious.

Because of these two points, we are currently thinking about using Teensy 4.x USB hosts to communicate one to each other instead of I2C. In fact, USB is much more faster than I2C and is natively hot swappable. But all remains to do. You can follow this thread if you're interested : [https://forum.pjrc.com/threads/66362-Using-usbMIDI-with-I2C-without-saturating-I2C-bus].

In any case, designing the use of I2C as you advise (rationing, handle errors and corrupted messages) definitely looks like the way to follow when significant transfer rate is needed.

Best regards,