I2C.SLAVE

I want to use OpenMV as a I2C slave .

How can I create a call back for when the master requests data from the OpenMV slave??

I notice in the official Micro-Python port they have a switch callback that triggers a interupts when the switch connected to a pin is pressed. I assume that I need something similar but a callback for the SCL falling then disable the interrupt till after callback function is finished so that not to get multi callbacks for ever SCL cycle.

Um, I have actually no idea how to do this right. See the picture emulation i2c example for the best I2C code I could come up with. The general problem is that the camera will be busy doing work when an I2C transaction happens which means that you would be there to service the I2C hardware which wants a byte to send.

I personally don’t think the MP HAL can actually do I2C slaving right. Same for SPI. Maybe things have gotten better though lately. Is there a SPI or I2C MicroPython slave example script anywhere?

Google info:

https://www.google.com/search?q=MicroPython+I2c+slave&oq=MicroPython+I2c+slave&aqs=chrome..69i57j0l2.6411j0j4&client=ms-android-verizon&sourceid=chrome-mobile&ie=UTF-8

Um, so, the slave hardware works if you setup to transfer a byte before the master needs it and then sit there waiting for the master to take the data. Otherwise, the master gets NACKs from you.

So, a way to design the protocol would be to have the master be okay getting NACKs and then when you have data you form an I2C packet to send and then give that to the I2C send() method as a slave device with a timeout.

That said… You’re kinda self timed by the Arduino or whatever is connected to you and you can’t process the next frame until serviced.

Alternatively, you could also just make the protocol two way. The master gives you a command. You do stuff then while the master polls for a response.

I am playing with trying to make the OpenMV as a slave I2C with the Lego brick as a master so I can’t change any of the protocol at the master end.

So basically I would set up a 8 byte buffer with (x,y,w,h) as unsigned short int and every loop of the image processing I would update this 8 byte buffer so there would always be the data ready for the I2C send. I just need to make an interrupt to to service the master I2C request for data. I think the best way to implement this is to get an interrupt to the SCL line, something like this 5. Switches, callbacks and interrupts — MicroPython 1.19.1 documentation

I will also ask on the official Micro-python forum as well.

Other ports of Micropython does have working functionality of this see ESP32 i2c · loboris/MicroPython_ESP32_psRAM_LoBo Wiki · GitHub

Look at the external int class under pyb. This let’s you make rising or falling edge interrupts.

That said, while the camera is fast enough to setup access for the I2C I’m not sure hw will handle not seeing the I2C start condition.

Note, the HW functionality must be wrapped in exception handlers. I2C and SPI throw exceptions all the time.

I recommend heavily to ready what the underlying C code is doing for making an I2C slave and looking at the M7 HAL I2C code. It will help determine what’s wrong.

(Obviously you shouldn’t need to do this but… This is where we are).

That said, while the camera is fast enough to setup access for the I2C I’m not sure hw will handle not seeing the I2C start condition.

Yes I think that in the end it may require writing a software I2C slave that is triggered by a interrupt on the SCL pin.

I have spent the day trying to hack the Lego UART grey blob, as far as I know no one has cracked it yet. Everyone has been using I2C to create after market sensors for Lego as the I2C grey blob has been cracked

Code entry points:

https://github.com/openmv/openmv/blob/master/src/sthal/f7/src/stm32f7xx_hal_i2c.c#L1016
https://github.com/openmv/openmv/blob/master/src/sthal/f7/src/stm32f7xx_hal_i2c.c#L1597

Not sure if you want to disable interrupts or not while things are happening.

Thanks for the links I will have a look over the code. :slight_smile: