Richard-Gemmell / teensy4_i2c

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

"Timed out waiting for transfer to finish." #16

Open zirafa opened 3 years ago

zirafa commented 3 years ago

Hello, thanks for writing this library. It definitely solved many of the blocking/speed issues I was encountering! However after swapping out the Wire.h library for Teensy4 I2C now I'm bumping up against an intermittent time out error: "Timed out waiting for transfer to finish."

I am running a Teensy 4.1 with audio shield, several MPR121 capacitive touch sensors, and an OLED. The error seems to happen while reading from the MPR121 sensors. If I increase the clock speed, the error happens less frequently. If I disable the MPR121 sensors entirely, the error disappears. My first thought was maybe there is a conflict between Teensy4 I2C and the Adafruit MPR121 library, but I'm not entirely sure. I suspect it might also be a conflict with the Audio library.

Any help is appreciated!

Richard-Gemmell commented 3 years ago

Hi zirafa, This message comes from the finish() method in the wire.h implementation. It means that an I2C transfer didn't complete before the timeout expired. The transfer can be either a read or write but it's probably an attempt to read the MPR121 in this case.

The timeout is set by the timeout_millis field in i2c_driver_wire.h. The default value is 200 milliseconds which is a very long time in I2C terms. I would expect a typical transfer to take less than 1 millisecond. I would normally say that changing the timeout won't help but you mention that the errors are less common at higher clock speeds. In that case it might be worth trying a few different values just to see if it makes the errors more or less common.

If you're going to do that, please make sure you get enough measurements to be sure that there's a real difference. It's very easy with intermittent faults to convince yourself that something makes a difference when it's just a quirk of random noise. I'd suggest a minimum of 20 data points for each condition.

I can think of 2 possible reasons for the problem. (There may well be more!)

  1. An interrupt service routine (ISR) is stalling the I2C transfer
  2. The transfer is being aborted because of an electrical problem

The ISR problem is easy to avoid. ISR's are callback functions that sit outside loop(). You don't call them directly. Instead, some library calls them when something happens. These functions need to be ultra fast. They should avoid calling Serial.print() or other IO. This sort of work should be done in loop() instead.

Electrical problems are always an issue with I2C because the protocol doesn't have any built in error correction or retry mechanism. When something goes wrong you either get an incorrect data value or the transaction fails. In the worst case scenario the I2C bus can lock up and every following transfer fails as well. It's difficult to eliminate electrical problems but you may be able to make them very rare. (I have a system which generates less than 1 error per million transfers.)

Does your system continue to work correctly after you've seen the error or do you have to reset it? i.e. is this issue just a nuisance or a major problem for you?

cheers, Richard

zirafa commented 3 years ago

Thank you for the detailed response! I will certainly investigate the wiring issues (quite messy) and ISR transfers. The weird thing is the problem does not occur when using the default Wire.h library. Maybe Teensy4_I2C is revealing some underlying instability in my setup that doesn't occur with Wire.h, but I'm not sure -- my expectation is that if a system is stable using Wire.h it would also be stable when using Teensy_I2C.

As for the severity of the problem, it is major. The system starts fine, but after receiving some input it becomes overloaded (basically all sensors suddenly turn on for a few milliseconds, causing a noise glitch) and then quickly settles down and continues to run (until it receives more input). If I keep pushing it with continuous input, sometimes the system will lockup and the Teensy will crash entirely, requiring a hard reset.

Richard-Gemmell commented 3 years ago

I agree that if the system is stable with the default Wire library then it should be stable with Teensy4_I2C as well.

This strongly suggests that there's a software bug somewhere rather than a hardware problem. You definitely shouldn't be able to crash the Teensy!

I've got a few questions.

Please can you send me the simplest possible example that illustrates the problem. I'll see if I can reproduce it.

Richard-Gemmell commented 3 years ago

Hi, I'm looking at another bug report at the moment as well. That issue has shown up a bug in the driver where the I2C master gets confused after receiving an error and never recovers.

It's quite possible that you're having the same problem. I've made some experimental improvements on the stuck_bus branch. Please give this a try and see if it improves the situation at all. I know it doesn't solve all the problems with the master but it may help.

There's a well known I2C issue called a "stuck bus" which can happen when a slave is waiting for the master to do something but the master has stopped listening. The Wire library I2C driver has a method called force_clock which can sometimes reset the slave automatically. My driver doesn't do that so this may be why the standard driver works and Teensy4_I2C doesn't. I'm planning to add that method (or something similar) in the next few weeks.

In the mean time, you might be able to reset the I2C slave devices with hardware. Some devices has a reset pin that you could connect to the Teensy and trigger if you think the bus is stuck.

You can tell if the I2C master failed by checking it's error code after a transfer. Use the underlying master device like this:

if (Master.has_error()) {
    I2CError error_code = Master.error();
    Serial.print("Transfer failed with error code ");
    Serial.println((int)error_code);
}

If you suddenly see every attempt to read a device trigger code 12 I2CError::bus_busy then you've probably got a stuck slave. Note that this can also be caused by having another I2C master on the same bus. I'm guessing that the Teensy is the only master device on your bus though.

Trigger the reset pin if you see error code 12 I2CError::bus_busy. You may need to call it for code 10 I2CError::data_nak as well.

zirafa commented 3 years ago

Thanks again for the pointers, I haven't had a chance to go through all the debug steps but I am using i2c pins 17/18 18/19 on the Teensy 4.1. My setup involves a mess of wires soldered to a protoboard, so it may take some time to isolate the problem in hardware and create example code for you to reproduce the problem.

Using your master branch I added your error checking code and got this error:

Timed out waiting for transfer to finish.
Transfer failed with error code 6

I switched to the stuck_bus branch and the Teensy locked up (and could not recover) with these error messages:

Pad control register: 0x1F860
Pad control register: 0x1F860
Pad control register: 0x1F860
Pad control register: 0x1F860
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 1. Error code: 0
Master: abort_transaction
MSR Flags: BBF MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=102 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=102 but MBF=1
[...repeats forever]

In one attempt I saw one of the i2c MPR121 devices blinking as if it was stuck.

After rebooting the Teensy, I got slightly different error messages (but it still locked up immediately and did not recover)

Pad control register: 0x1F860
Pad control register: 0x1F860
Pad control register: 0x1F860
Pad control register: 0x1F860
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=102 but MBF=1
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
Master: Cannot start. Bus already in use.
WARNING: Inconsistent state in finisMaster: Pin low timeout (PLTF)
Master: abort_transaction
MSR Flags: BBF MBF PLTF TDF 
  sending STOP
Master: Pin low timeout (PLTF)
Master: abort_transaction
MSR Flags: BBF MBF PLTF 
  sending STOP
Master: Pin low timeout (PLTF)
Master: abort_transaction
MSR Flags: BBF MBF 
  sending STOP
hed(). 'state'=102 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
ster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOPWARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNINMaster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
G: Inconsistent state in finished(). 'state'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished().Master: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
 'state'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: IncMaster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STonsistent state in finished(). 'state'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=1Master: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
00 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=1Master: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
00 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: InconsistenMaster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
t state in finished(). 'state'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=1Master: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
00 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: InconsiMaster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
stent state in finished(). 'state'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=1Master: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
00 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: InconsiMaster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
stent state in finished(). 'state'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'statMaster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
e'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error code: 0
Master: abort_transaction
MSR Flags: MBF 
  sending STOP
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
WARNING: InconMaster: abort_transaction
MSR Flags: BBF MBF TDF 
  sending STOP
sistent state in finished(). 'state'=1 but MBF=1
WARNING: Inconsistent state in finished(). 'state'=100 but MBF=1
Master: Cannot start. Transaction still in progress. State: 0. Error co

Unfortunately I don't see any reset pins on my i2c devices.

Richard-Gemmell commented 3 years ago

When you say that you're using pins 17/18 do you mean that you've got a single I2C bus connected to pins 17 and 18 or do you have 2 buses with one connected to pins 18 & 19 and one to 16 & 17?

Thanks for giving the stuck_bus branch a try. The output suggests that something is affecting the bus. The most likely explanation is that a slave is stuck and is holding SDA or SCL low. You can check this with a multimeter. Stop the master from and check SDA and SCL. They should be high. If one of them is permanently low then it's either a stuck slave or a short circuit.

If you've got an oscilloscope then you can use that to look for activity.

If you haven't got a stuck slave then maybe:-

zirafa commented 3 years ago

Oh my mistake -- I meant I have a single bus running on pins 18 & 19. I think you may be right that a slave is stuck, I'll take a closer look at that.

zirafa commented 3 years ago

Ok, so I removed all i2c devices except my i2c display and encountered this bug when simply replacing Wire with this library. Hopefully it is simple enough for you to reproduce.

  1. On a Teensy 4.1 connect a i2c display such as an SH1106 OLED to pins 18 + 19.
  2. Install the U8glib library.
  3. Using the default Wire.h library, run File > Example > U8g2 > u8x8> GraphicsTest. Select the correct constructor for your device, i.e. U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
  4. Compile and run code, observe that the graphics test displays correctly with no errors.
  5. Replace Wire.h with the Teensy4_i2c master branch. Update references to Wire.h in GraphicsTest.ino andU8g2/src/U8x8lib.cpp with
    // #include <Wire.h>
    #include <i2c_driver.h>
    #include <i2c_device.h>
    #include <i2c_driver_wire.h>
    #include <i2c_register_slave.h>
  6. Compile and run the updated GraphicsTest code. Observe that the display shows no output and the console shows the error: Timed out waiting for transfer to finish. which repeats indefinitely.
  7. Switch to Teensy4_i2c stuck_bus branch. Compile and run code.
  8. Again the display shows no output and console shows repeating error: "Master: Cannot start. Bus already in use."
Richard-Gemmell commented 3 years ago

Thanks for that. Do you have a link to the actual display you're using? I'm think of buying one so I can test it.

zirafa commented 3 years ago

Sure. This is the one I am using to test, though there appear to be lots of variations of this same display.

Richard-Gemmell commented 3 years ago

I bought a display and it's working Ok for me. It works the same with Wire.h and Teensy4_I2C.

I bought this display. The sheet which comes with it claims that it's an SSD1306. When I tried it with the SSD1306 driver it worked but had this problem. It works fine with the same SH1106 driver that you used.

It worked whether I powered it off the 3.3V or 5V pin on the Teensy.

Here's a picture of the wiring on my breadboard.

oled_display

It's possible that it works like this with short leads and no other connected devices but fails with a more complicated setup. What does your setup look like? Did you have any unused wires or any other devices connected to the bus?

Here's the complete code that I used.

#include <Arduino.h>
#include <U8x8lib.h>
//#include <Wire.h>
#include <i2c_driver.h>
#include <i2c_driver_wire.h>

U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

void setup(void)
{
  u8x8.begin();
}

void loop(void)
{
  u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
  u8x8.clear();
  u8x8.print("I2C Test Zirafa");

  delay(2000);
}
zirafa commented 3 years ago

Interesting. Did you encounter any issues running the u8x8 graphics test? I suspect the issue only comes up when the display is updating rapidly.

My setup is definitely more complicated, but I don't think I had anything extra connected. I'll give it another try and let you know.

Richard-Gemmell commented 3 years ago

The full example works OK too.

The only thing I can think of is that the driver works well until something corrupts an I2C message and then it fails to recover. I know this happens if you have a dodgy bus wire. I've started to create some tools to try to diagnose these issues and create an automated test suite for the driver. Unfortunately, This is going to take a lot of time.

I saw someone mention that powering an OLED from the Teensy's 3.3V line can introduce a lot of noise. Do you have yours connected to the 3.3 or 5V pin?

Richard-Gemmell commented 3 years ago

Are you powering your Teensy through the USB connector? If not, which pin are you using for power and what's the voltage?

zirafa commented 3 years ago

Hm, so for whatever reason, I can't reproduce the display bug now. The display seems to work fine in isolation or when other i2c devices are connected. That suggests bad wiring, though I'm not entirely convinced just yet.

It still seems odd that the error doesn't happen with the default Wire.h...but I could just be getting lucky with how Wire.h handles errors -- I suspect instead of timing out and crashing the entire bus just slows down.

I have my display connected to the 3.3v. I tried 5v and encountered the same issues.

Thanks for your help thus far. I think to get any further with this, I'm going to have to completely rewire everything and see if that fixes the problem.

aaronsherwood commented 1 year ago

Actually, nevermind! After toiling for hours I think I solved it. It was a hardware issue with the pull up resistors for the differential extender. Whew...