ESP32 read i2c or i3c in IRQ macro

Post here to discuss any new features, components, chips, etc, that you would like to see in Flowcode.
stefan.erni
Valued Contributor
Posts: 1002
http://meble-kuchenne.info.pl
Joined: Wed Dec 02, 2020 10:53 am
Has thanked: 191 times
Been thanked: 217 times

ESP32 read i2c or i3c in IRQ macro

Post by stefan.erni »

Hi Ben

Sampling data is simple: create an IRQ with the correct timer setup. Read data in the IRQ-macro and collect it in a large buffer.
When the buffer is full, save to disk or send with USB/Bluetooth in one block to the App-Developer.
And even a little better if there are two large buffers then you can write in one and save the other.

There is still a small problem with the ESP32 to do this:

In the macro of the IRQ, the I2C does not work, the program hangs immediately.
Also many other commands cause a crash, but not all commands.

Would it be possible to improve this, so the I2C does not crash?
And maybe have a look at I3C as well for the ESP32 :)

mnfisher
Valued Contributor
Posts: 1462
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 136 times
Been thanked: 713 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by mnfisher »

Hi Stefan,

I don't think it's possible - the hardware i2c uses interrupts and will probably lock up if the processor is already handling one..

As a thought on the double buffered approach - can you have two tasks that read the sensor - filling a buffer with a maximum number of samples before the wdt kicks in (for sake of argument, say 10000) Then it pauses, transferring 'read duty' to the other task which reads to the second buffer. Meanwhile a task running on the other core writes the data to UART or SD?
It would need semaphore or two of some type - so the data writer outputs the correct buffer. Also I think it might be possible to read faster than it is possible to output the data.

One task would probably suffice - will need a delay when swapping from buffer 1 to buffer 2..

There also have to be some pauses for RTOS to keep it's cool - so there might be a small gap between samples read by task 1 and task 2.

Martin

stefan.erni
Valued Contributor
Posts: 1002
Joined: Wed Dec 02, 2020 10:53 am
Has thanked: 191 times
Been thanked: 217 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by stefan.erni »

Hi Martin

With your help from last time it works to sample at 480Hz and write to disk in a separate task in the second core. Perfect!
But there are a few errors in the data. I will call these needles. I have sampled the LSM6 in IRQ with the STM32 and there the values are perfect (but I can't save to the Sd-card) One idea is to read the LSM6 more regularly like the STM32.
Now I set a variable in the IRQ to read data. But depending on the position in the main(rec macro) it goes faster or slower until the macro is called, irregular reading is maybe not so good.

Accelero data x,y,z with a movement:
2025-04-16_11-21-15.PNG
2025-04-16_11-21-15.PNG (81.01 KiB) Viewed 2808 times
read Button and if irq from USB or BT:
2025-04-16_11-36-42.PNG
2025-04-16_11-36-42.PNG (98.3 KiB) Viewed 2808 times

mnfisher
Valued Contributor
Posts: 1462
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 136 times
Been thanked: 713 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by mnfisher »

The spikes are odd... Do they give incorrect data - or are they so short as to be ignored?

Looking at the datasheet - the device has an 8k FIFO buffer (At least - I looked at LSM6DS3)
Would it be possible to utilise this to increase the data rate - each read has 'overhead' - so taking a single sensor reading involves - send i2c_address_write, register address, i2c_address_read - read data (8 bytes)....
Using the buffer this is 'reduced' to i2c_address_write, register_address, i2c_address_read read data (8k)
Also - how often does the data 'need' to be updated? The sensor seems to be able to generate an interrupt on position change - would it be possible to read data on this interrupt - depending on application - the device may be in constant motion?

Martin

stefan.erni
Valued Contributor
Posts: 1002
Joined: Wed Dec 02, 2020 10:53 am
Has thanked: 191 times
Been thanked: 217 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by stefan.erni »

Hi Martin

I use the lsm6dsv16bx.
at the moment i am using this on an extrem small board with I2C on a QWII connector.
Unfortunately I cannot work with an IRQ from the LSM.
I can read the FIFO but I can't read it fast enough via the i2c bus and ESP32.
I have also checked the pullup from STM32 and ESP32 board, all are 2k2.
with the STM32 I can read out at 7680Hz without errors
with the ESP32 I can only read out at 240Hz without needles
If I use 480Hz an higher with the ESP32 I get these needles.

mnfisher
Valued Contributor
Posts: 1462
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 136 times
Been thanked: 713 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by mnfisher »

Hi Stefan,

I got a LSM6DS3 sensor - and managed to get 'block' read from the fifo working... I think - there are a couple of caveats - I dump the data (it would need to alternate buffers in the read) - and the writing 'out' of the data needs to be able to keep up with the reads. Also - I don't check that the data looks 'reasonable' - so it might just be 0s or other guff..

I display the WhoAmI byte for 5s (I had wdt issues until I increased the stack size)

In this sample - I have set the sensor to 1..04kHz (just the accelerometer - so 6 bytes per sample) (Maybe - see below)

The main loop reads the number of samples from 0x3E/0x3f every 10ms- and outputs this to UART - and at 1.04kHz this gives about the right value (~70 samples (420 bytes) - the loop will take longer than 10ms!)

I use a block read - with i2c running at 1MHz - note that I had to increase the stack size (idf.py menuconfig) (and I used 32768)

Also note - I have the version of cal_string that gives a pointer sign error, and I added target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-pointer-sign) to CMakeLists.txt to ignore this...

Here I demonstrate reading 8k of data every 1s - I'm not sure I have set up the sensor correctly (3a, 3b always gives a buffer size of 0 :-( )

I'm using a logic analyser rather than a scope - would be interesting if you still get the 'needles' in the trace?

Martin

mnfisher
Valued Contributor
Posts: 1462
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 136 times
Been thanked: 713 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by mnfisher »

It took a lot of fiddling to get it to write to the FIFO...

I just used accelerometer - so 6 bytes per sample With a104Hz update speed - reading every 500ms - gives about 52 samples (so ~300 bytes) and reading these takes about 4.1ms. Of course there is also the overhead of reading the status registers - and here outputting the FIFO level to UART.... (included)

This with 1MHz i2c - will try a faster ODR. Here at 416Hz - with a 50ms delay. I've found that the FIFO buffer gets 'blocked' and power cycling the esp32 (just the sensor doesn't) fixes it. There is surely a better solution. It 'seems' like the sensor overflows the FIFO (0x3b return 0x60) - but I haven't found a software 'fix' for this.

Also - I have no idea if the values read 'make sense' or are garbage. I'm assuming you don't need to act on them in real time (saving to SD) - the values seem to change even if the sensor is not moving (although on my desk - so there might be some motion?)

I have assumed that 3a /3b return the number of samples - so attempt to read 6 x samples bytes. This might be incorrect (originally I did samples/6 - and the number of samples was consistent)

Martin
Attachments
lsdm3.fcfx
(24.66 KiB) Downloaded 15 times

mnfisher
Valued Contributor
Posts: 1462
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 136 times
Been thanked: 713 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by mnfisher »

A shot showing a multiple read - as can be seen there is a 'gap' between writing the address to read - first is a read of the status registers (2 bytes) then send of address 0x3e - then multiple read. The multiple read seems to be consistent speed - As can be seen - the read gets 'blocks' of data with small delays at intervals (7uS - but I didn't measure how much data)

The 'read' would be best pulled to a separate task - and ideally use an interrupt when the FIFO buffer has reached a certain level. However, the delay / ODR can be adjusted to allow a maximal read size too...
Attachments
LabNation_Screenshot11.png
LabNation_Screenshot11.png (201.75 KiB) Viewed 2365 times

stefan.erni
Valued Contributor
Posts: 1002
Joined: Wed Dec 02, 2020 10:53 am
Has thanked: 191 times
Been thanked: 217 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by stefan.erni »

Hi Martin

Fifo with the LSM6dsv16bx and LSM6DS3 are different.
I had to read out the FIFO for a project and it worked. But a lot of effort. I can also post this once, it's about the quaternions.
Now I have to read two LSM6dsv16 Accelero and Gyro data. That actually already works. But there are these needles with the ESP32 that do not exist with the STM32. With the STM32 I get a regular scan on the oscilloscope I mean a constant ODR.

Can we solve the IRQ problem of the ESP32 and I2C somehow?
For the ESP32 users this would be useful and prevent many errors and trouble

mnfisher
Valued Contributor
Posts: 1462
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 136 times
Been thanked: 713 times

Re: ESP32 read i2c or i3c in IRQ macro

Post by mnfisher »

Hi Stefan,

The approach would be to use the interrupt to signal a task - that waits on a 'semaphore' or 'signal' (we've done this before :-) ). The issue of multiple reads is that there is the 'long' (for a MCU) delay (80uS if memory serves) in the read after sending the register address. This surely limits the speed.
Reading multiple samples overcomes this - is there a way to read more than one sample at a time with the sensor you have? - it certainly made a dramatic difference in the demo above - although setting up the FIFO was tricky (and I'm not entirely sure I have it right - some samples may by spurious - if the sensor and FIFO ODR rates differ..)

Martin

Post Reply