I2C / Wire problem with nano 33 IoT

I’m having trouble communicating with a nano 33 IoT (SAMD), via I2C / Wire, to a VL6180X.

Done all I can to minimize electrical noise, and correct I2C pull ups. But it only runs for ms to seconds, before it hungs up.

It seems I’m not the only one having trouble with the Wire library and its hung ups.

So I went on to switch from Wire library, to the instead recommended SBWire library.

But now my code compile with the following error;

“SBWire-master\src\utility\twi.c:27:10: fatal error: avr/io.h: No such file or directory”

The SBWire library has found its place here “C:\Users\xxx\Documents\Arduino\libraries\SBWire-master” after adding it as a .zip. Even though it isn’t listet in library manager?

So does this mean that the SBWire only is intended to work with avr processors and not the SAMD?

It seems my only way to get around the hung ups is the SBWire, since the original arduino Wire still haven’t fixed the hung up problem, at least not for the SAMD. Any other suggestions?

Yes.

On the SAMD platform?

Fix your hardware!

Really? You have pull-ups to 2.8V? Post a complete wiring diagram/schematics of your setup!

Hi

Regarding the hung ups, it seems to be a general problem not special related to SAMD. But related to the wire library.
I think I have done what is possible to fix the HW, like others with the same problem, and I do get fewer hung ups, but if only one hung up per 5 minutes gets the arduino to lock then that not good.
I have the taken off the pull ups from the VL6180 pololu bob, that should leave me with the correct 4K7 from the nano 33 IoT, running 3V3.
I really would like a failsafe sketch, meaning even with best HW, if an error occurs the SW can handle it, like it is meantioned in forums speaking of the SBWire.

What if a bit flips in a register inside the ATSAMD processor, how are you going to fix that ? You can't, you assume that it works.
That is how you should look at the I2C bus.

The more convinced you are that your hardware is okay, the more we are convinced that it is not :wink: Please show that diagram/schematics and a photo of the wiring and a link to your module.

There are a few vague things that should be fixed:

  • A timeout was added to the AVR Wire library and it is even documented in the reference or not documented, depending on the search engine.
  • There is a halting-bug in the ATSAMD Wire library that might have been fixed or not. It is a real issue, and I don't now the actual status.

If you mention a SBWire library, please give a link to it. If you mention speaking of SBWire in forums, please give a link to it.

Hi

OK, I think I understand your point about the bit flip, and must admit Im not experienced to know how the SBWire library have fixed this, but in the readme it says " twi_stop() is called followed by twi_init()" on timeout.
GitHub - freespace/SBWire: Modified Arduino Wire library which implements basic timeout.
https://github.com/freespace/SBWire

To my understanding, looking/"searhing around", the fixing of the halting bug in the SAMD wire library has not been implemented. But there have been "thoughts" on it.
https://www.arduino.cc/reference/en/language/functions/communication/wire/setwiretimeout/

Regarding the HW (sorry for missing photo) but it is as simple as SCL-SCL SDA-SDA, also tried to noise protect two lines with grounded aluminum foil, short wires around 75 mm, not twisted, only "trouble" being a small DC motor near by - with 3 X 0,1 uF for noise. And and as mentioned actually works, but sometimes may be after minutes one error occurs and sketch stops.

(Hope my english is understandable, and links now OK) : )

Now I have tried to make my own modification to the pololu VL6180X library, controlling the use of the Wire functions. Putting in a timeout functionality and using wire.available. Unfortunately that didn’t bring any luck.
https://github.com/pololu/vl6180x-arduino/blob/master/VL6180X.cpp

Meaning that instead of using pololus ToF1.readReg(0x04F) I now use my own I2Cread(0x04F).

When the sketch hang up its happening at Wire.endTransmission or Wire.requestFrom, so my timeout doesn’t even come into any use. (last print being "I 3" or "I 4")

uint8_t I2Cread(uint16_t reg) {

  uint8_t value;
  unsigned long timeOut;

  Serial.println("I 1");
  Wire.beginTransmission(0x56);
  Serial.println("I 2");
  Wire.write((uint8_t)(reg >> 8)); // reg high byte
  Wire.write((uint8_t)(reg >> 0)); // reg low byte
  Serial.println("I 3");
  Wire.endTransmission();

  Serial.println("I 4");
  Wire.requestFrom(0x56, (uint8_t)1);

  Serial.println("I 5");
  timeOut= millis()+5;
  value= 0;
  do {
    if (Wire.available()== 1) {
      value = Wire.read();
    }
  } while((value== 0) && (timeOut> millis()));

  return value;
  
}

Adding a timeout after a Wire.requestFrom() is useless. The Wire.requestFrom() function only returns when the whole I2C sessions has finished.

A photo would really help, to see how the motor and I2C bus are connected.
Did you know that the GND is the most important wire of the I2C bus ?
Grounding and GND currents are a craftsmanship on its own.

About those vague things that I mention, there might be a problem in the library. There are lately a number of questions on this forum with a ATSAMD21 and ATSAMD51 that halt with I2C trouble. That can't be a coincidence.
Do you at least use the latest official Arduino libraries ?
Some companies copy the Arduino libraries for their own board and then forget to keep up with the bug fixes of the Arduino libraries.

Thanks for answers Koepel

OK I understand regarding timeout, and requestFrom(), but I wanted to try at least something, and thats were my knowledge ends.

The motor and I2C are separate, meaning GND from nano 33 goes to motor driver, and another GND goes to VL6180X, but problem does also occur even with motor not running but very seldom, but again that one time it happens, the sketch must not stop. Cant put in a photo, my 10 years old "smartphone" camera doesnt work anymore - yes I know..

Im convinced I have the latest Wire library (arduino original, cheked github dates), but as you mention I have also found question on this forum and other places, I think there simply is a problem with the ATSAMD wire library implementation - which has been solved for at least avr processor with SBWire library.

But anyhow this leaves me with a nano 33 IoT not working properly in respect of I2C. Now Im even considering something like a SPI I2C bridge / interface. (breakout board)

https://www.nxp.com/products/peripherals-and-logic/signal-chain/bridges/spi-to-ic-bus-bridge:SC18IS604

Hi Koepel

Looking and searching for a solution, and not keen to use that HW bridge, I fell across a library

https://github.com/Testato/SoftwareWire

It seems you have been involved in that? If everything else false, could you tell me if this would work with SAMD, and beeing resistent to errors also?

Now I also discovered this https://github.com/SMFSW/WireWrapper which says

Arduino Wrapper for Wire library (for SAM, ESP8266...), I will have a look at that also. Annoying thing about all solutions, is that other included libraries in my skect using wire (VL6180 library) has to be copyit and rewritten with new solution.

Thanks

Don't expect it to work better than the hardware solution. A software emulation almost never does a better job in terms of stability and robustness.

For situation where you must handle freezes the hardware designers introduced the watchdog which resets your controller if the code doesn't reset the watchdog for a certain time. If you designed your hardware buggy (which often means outside the specs) the watchdog is probably the better solution than a software emulation of a hardware functionality.

The SoftwareWire is at the moment only for the AVR family. There are other software I2C libraries which use only pinMode / digitalRead / digitalWrite but I don't know which one have timeouts. The "big list" does not tell if they are failsafe: https://github.com/Testato/SoftwareWire/wiki/Arduino-I2C-libraries

We still don't have enough information about your project and wiring.
This is your module: https://www.pololu.com/product/2489
It has I2C level shifters for the 2.8V sensor. But a I2C level shifter makes the I2C bus weaker.
If you remove the pullups from that module, then the I2C level shifter does no longer work.
You don't have a I2C bus between the level shifter and the sensor at the moment.
Unless you kept those 10k on the module, but we don't know.

3.3V / 4k7 + 3.3V / 10k + 2.8V / 10k = 1.3mA
You can go up to 3 mA. Adding more pullup to the I2C bus lowers its impedance.

You don't have to look for other libraries for the ATSAMD21G. The Arduino Wire library should not halt the sketch. If it does, then you need a whole different platform.

Let's get serious: An embedded system should never stop by a something from the outside. Every software engineer for embedded systems knows that. Arduino is for learning and fast prototyping, and was started at a university. They didn't care about this. For me, this bug is utterly stupid.

Assuming it is a bug, I still don't know what to think of it. I don't have a ATSAMD21G in a active project.

You could move over to a common other processor.
The ESP32 uses a bottom layer made by the manufacturer with the Arduino layer on top of that. If you don't put it in I2C Slave mode, then it is very good. The Raspberry Pi Pico has Mbed with Arduino on top of that, but it might not yet be fully bug-free.
The ESP32 and Mbed have multitasking. You could keep a watchdog alive from a software task.

The first reply was by pylon, asking for more information. In reply #4, I wrote once more about your hardware. We do that for a reason. It starts by making the I2C bus as good as possible, and then solve other (software) problems.

Thank for answers,

The HW looks like in the picture. Not pictured is a DC motor driver and motor from pololu.

I have taken off the two 10K pull-ups on the 3,3 V side of the I2C bus (yellow circle, maybe hard to see in forum picture, but they are attached to Vin ). Because the nano 33 IOT already has 4K7 on its I2C bus pins. NOT on 2,8 V side.

The SCL and SCA runs for about 75 mm, in parallel, in small wires, I wrapped them in aluminium foil, and connected aluminium foil to nano 33 IOT GND. The Vcc and GND for VL6180 board are just "hanging free", so are a wire from GPIO 0 to nano 33 IOT pin D15.

The DC motor driver Pololu - DRV8835 Dual Motor Driver Carrier is connected to D5, D6 nano 33 IOT pins.

And yes, all nano 33 IOT, VL6180X, and motor driver share the same Vcc and GND. When connected to USB, the nano 33 IOT deliveres power.

After reading this Pololu - 9. Dealing with Motor Noise

I have put on these 3 0,1 uF on the motor directly.

Its seems a couple of others have come across the arduino wire problem hanging up for example

How to replace the default Wire library with non-hangup version? - Using Arduino / Networking, Protocols, and Devices - Arduino Forum

Known defect in Arduino I2C code causes hangup problems | Paynter's Palace (fpaynter.com)

Arduino I²C Freezes After Startup (adoclib.com)

And as Koepel mentiones here

Introducing AccelStepperI2C library - Development / Libraries - Arduino Forum

The I2C bus is weak, it often fails when motors are involved. In the above and in my project motors are involved.

Im sure its possible to make the HW (regarding noise) better, as mentioned.

Still the HW and sketch is working for some time. But it’s a problem that one time it hang ups, even if its minutes apart. The sketch must be fail safe, and not stop. I still think there is a problem with the ATSAMD wire library implementation - which has been solved for at least avr processor with SBWire library. Looking further at solutions, SAMD datasheet, etc. I must admit I don’t have the knowledge for making a new Wire library, as you mention arduino is mostly for learning, not for experts.

Again as I understand the fixing of the halting bug in the SAMD wire library has not been implemented. But there have been "thoughts" on it. See Notes and Warning, Portability:

You must not pull the I2C signals to VIN. It might be VIN of your module but you didn't draw where that connects to. Also we cannot see where the motor (drivers) are connected to and how the whole thing is powered. If you power the motor by the same 5V you use for the Arduino you probably have found the cause of your problems.

2 Likes

In addition to what pylon wrote: I don't know if you are willing to lower the impedance of the I2C bus. The SDA should not be parallel with SCL. It is unclear if you bundled SDA with SCL and then wrapped them in foil (that would be bad).

I2C is now only pulled to 3V3 internally by nano 33 IOT. (as recommended 10 K in circle of the VL6180 board taken off, and leaving internally the 4K7 on nano).

As you can see all, the motor, motordriver, and VL6180 is powered by same 3V3 coming from nano 33 IOT power (nano makes this 3V3 from USB and should easily be able to deliver the current needed). If this is bad how can I separate that?

I do think I did the bad thing ; ) SCL SDA are bundle together. Should only the SCL, or SCA, be in foil or both in separate foil?

Another question, should this question/topic be moved to nano 33 IOT, your opinion?

PS the VDD seen on VL6180 board is 2V8 made on same board internally.

Hi @NoX20

Have you checked that your N-channel MOSFET level-shifters' maximum gate source threshold voltage "V(GS) th max" is less than 2.8V?

@NoX20 The information you give is so little and even that information is vague and I see possible problems everywhere.

You have to tell what you have, you have to be accurate and specific.
A circuit without the GND connected will not work of course, that is what you show in the diagram.

Did you give a link to those motors ? The Nano 33 IoT has 600mA for user application. That means your motors should have a maximum stall current of 300mA.

Who told you to remove those 10k resistors ?
I want you to add more pullup resistors.

The buck converter of the Nano 33 IoT provides up to 1A of current at 3.3V. That must be sufficient for all components on-board and for all you connected. I have huge doubts that this is enough to drive a motor.

Provide the power for the motors by a separate power supply.

How long are those wires? Remember, a complete I2C bus (all wires and traces shouldn't exceed 50cm.

May I ask why? Although I don't think the 10k pull-ups pose a problem it's not clever to have multiple pull-ups on one bus. Do you think the edges aren't steep enough?

The I2C bus is not a typical twisted-pair transmission line. I see no problem in pullup resistors here and there.
A problem with the edges can be solved with a lower clock speed.

It is the impedance of the SDA and SCL signals.
Suppose there is only 10k pullup and a drop from 3.3V down to 1.0V is seen as a low. Then there is only 0.23 mA to overcome by external noise.

Please go easy on me :innocent: I'm just talking about short wires and ignoring the whole bunch of capacitive and inductive dynamic behavior.

I have had some experience working with I2C (wire.h) on arduino Nano
I built a garden mower using a nodemcu and 3 nanos communicating with I2C. The NodeMCU master uses I2C to control each Nano which has a dedicated function(motors, sensors, perimeter detection)

I have a level shifter 3v to 5v, 2.2K pullups on the 5v side.

I was seeing nano lock ups for no reason. For a small time it would work Ok. However after diagnosis I found that digital noise from wiring on the arduino digital pins interferes with the 5v rail of the nano. This causes the I2C to fail (actually crashes the nano).

Originally, I tried all sorts of power supply options, smoothing, I2C pullups, etc but nothing would eliminate it.

To overcome this I used a module of 7 x 0.1uF capacitors connected to a common single ground.
Each capacitor I connected a digital pin, that had wiring on it, of the problem nano.

This stops transient noise from the digital interface(s) getting on to the 5v rail of the nano.
So far I have had no further issues.