I2C gives OSError: [Errno 110] ETIMEDOUT


I’m trying to connect the openMV to an Atmega 328 using I2C. Every time I try to send, I get an ETIMEDOUT error.

Does that mean that the openMV didn’t receive an ACK?

i2c = I2C(2) # The i2c bus must always be 2.
i2c.init(I2C.MASTER, baudrate=400000) # init as a master

    #slaves = i2c.scan()

Note: I’m using the following I2C logic Level Shifter https://www.electronicgeek.ca/products/iic-i2c-logic-level-converter-bi-directional-module-5v-to-3-3v-for-arduino
And, made sure that the proper SDA and SCL are connected

Yeah, that’s what it means. The Arduino can’t do I2C slave mode as far as I know. Please use the UART on the mega and on the OpenMV Cam to communicate. It’s way easier.


Thanks for your reply.

I have the Atmega328 programmed as a slave. I used an arduino as master to test it and it works. Additionally, I can’t use a UART because I have another device on the Atmega using it.

Lastly, I ran a test yesterday with openMV as master to a slave arduino and it was receiving the data byte. However, when I go directly to the Atmega, it’s giving me the timeout.


Have you heard of software serial on the Arduino? It’s let’s you make a low speed uart on the I/O pins that support interrupts. Pins 2 and 3. Using that library you can have another serial port.

I just took a look at it. It’s an interesting application and can definitely be useful. However, I’m not using an Arduino and would rather not create my own implementation of this on the Atmega328.

I’ll take a look bit more into to see if AVR has anything already to create a second UART.

But, what’s the issue with the I2C? I’ve been able to scan the device and discover its address. It doesn’t happen successfully all the time but a bit more work and debugging can probably produce a reliable communication.

Thank you,

Ah, the Arduino can be an I2C slave. I didn’t know this was possible: https://www.arduino.cc/en/Tutorial/MasterWriter - so, just make the OpenMV Cam act like the master Arduino in this example.

Yeah that’s what I’m trying. I’m writing to the register for the baudrate on the Atmega328 so that it matches with the openMV. I think that’s where my issue was.



I continued trying to get an I2C communication with the openMV but still have no luck.

This time, I tried to get the communication between the M7 and H7. Programmed a simple Slave that tries to receive 3 bytes on the H7 and a Master that scans and sends a byte on the M7. I also connected a pull-up resistor on the SCL and SDA lines.

Hi, which device is having the error? The H7 or the M7? Note that you have to generally catch exceptions when you can get timeouts and etc. The MicroPython HAL throws exceptions on any error.

Both devices are getting a timeout.

    except OSError as error:

I had the code above to identify what the error was and so that I know when the device gets the exception

Mmm, okay, I would just switch to the machine module. The machine module bitbangs I2C and has less weirdness.


How do you specify a Slave with the machine module? I only see an initialization and then the function calls to scan, write and read.


Um, the OpenMV Cam would be the master and the Arduino would be the slave. Please do not use the OpenMV Cam as a slave I2C device. I tried for hours to get this to work in the Pixy Emulation Example script and it’s just not really workable. Since the Arduino has slave I2C support it might be a better choice for that. The reason slave mode on the OpenMV Cam is bad is because the HAL library we use from MicroPython doesn’t allow for I2C to happen in the background while you’re doing image stuff. A processor can really only be an I2C slave if it’s processing data in an interrupt callback handler which the PYB library doesn’t have hooks for.

Oh okay…I was trying to get it communicating between two openMVs to test the I2C since it wasn’t working between openMV and Arduino nor between openMV and Atmega

Did you look at the STM HAL libraries in the CubeMX? I didn’t work much with it but maybe you can run the I2C in background.

It’s possible to run it in the background. If you modify our firmware and add an interrupt handler for just this it’s not that hard. The issue is that MicroPython uses the non-interrupt driven HAL driver. You can only get access to the interrupt driver one in C code.

Note that coding for our system in C is perfectly reasonable if you want to play around with an STM32. Our dev environment allows you to quickly flash the firmware rather easily.

Oh okay, I see what you mean.

Mhmm, I’ll keep it in mind. Maybe after my project is done, I’ll take some time to play around with the STM32