Fast answer on LCD-I2C?

The issue is the stated requirement of:

to have time to check some GPIO input every few micro seconds.

How long is "a few micro seconds" ?
If it is in the ball park of under 10, (which is what I think of when the word "few" is used), THAT is going to be very difficult if not impossible to always meet.

Polling is not the answer as there is no way to always meet that type of timing requirement even on a very fast processor as eventually something that takes longer will likely need to be done.
Depending on the processor even something as simple as a single digitalRead() can take longer than a few microseconds.

I think at this point to provide any sort of guidance, a better understanding of the actual project needs to be disclosed.

--- bill

thank you for your thought, I appreciate.
As explained (but I realize that the title of the thread was not exact), my intent was to find a solution to print data on LCD without disturbing the collect of data (from Hall sensors and encoders) ,their computation and the release of results.
I was expecting to find an "on the shelf" solution, and I finally found one solution by proceeding stuff in parallel. See my sketch above.
This may not be the best solution, and it is for sure not the most sexy sketch, but at least that works :slight_smile: .
However, if some other solutions can be considered "at low cost" (time for me), then I am ready to investigate.
thank you

Just FYI, if you are still looking for a fast driver for LCD on I2C, I just published one which is lots faster than those others out there. You can check it out at GitHub - KStandiford/Fast-LCD-I2C: A fast driver for LCD displays on the I2C bus for Pi Pico and Arduino. The readme has timing.

The I2C bus is too slow to meet your requirements. At 100000 speed it takes 90 usec to send a byte and 4-5 bytes per character on the screen. Speeding up to 400000 BPS helps but not nearly enough. After that, most Liquidcrystal versions for I2C still throw away half the bandwidth. And BTW, I know for a fact that I2C on the pico does NOT use interrupts.

PCF8574 used in most backpacks has a maximum SCL frequency of 100kHz. i.e. the standard I2C bus speed.

Yes, you might find that the PCF8574 "works" at 400kHz.
But this is 400% overclocking.

You still have the same number of I2C interrupts which take the same number of CPU cycles to service.
i.e. the LCD library might block the foreground code but your other interrupt services will continue as normal.

I have never met a human that can read LCD text at I2C speed.
Graphic animations are limited. The display is smeary if you write too fast.

David.

I don't follow!

What part of the I²C code uses interrupts? If it is by nature blocking code, then it has no reason whatsoever to use interrupts! :thinking: The foreground code should be able to use them freely for encoders and such.

Wire.h library uses interrupts.

Yes, it blocks the foreground code until the whole I2C sequence has completed. i.e. a bit pointless.

Hey-ho. I did not write it.

That sounds completely stupid! :astonished: Why on earth would it do that?

Because in an ideal world you would let the hardware get on with the job.
Meanwhile you can get on with other things.

However the average user is quite happy to wait. Or even notice.
And it avoids a lot of grief in Forums.

David.

But I still fail to see what an interrupt has to do with the process of communicating by I²C?

Let alone spending time inside an interrupt. :astonished:

An "interrupt on completion" is what would actually enable other processes to co-exist/ co-operate.

I share your frustration! Time for someone to write a better library. (NO!)

Go on. If you want to use Wire.h non-blocking you can extend the class with a "done" flag.
Use a "startTransaction()" and startRequest() that check the "done" flag e.g. with an "isDone()" member.

In practice it seldom matters.
Let's face it. No one complains about analogRead() blocking. Very few people bother to "start" a conversion, get on with life, come back when the conversion has completed. i.e. use the hardware as Nature intended.

Yes, I find it irritating that Wire fills a small buffer before it does anything. Then it waits for the whole buffer to drain. But it all "works ok" for moderate amounts of I2C traffic.

David.

1 Like

Go spend some time looking at the Wire library code.

In the AVR, most of the i2c state protocol is handle in s/w.
i.e. the h/w really doesn't do that much to off load the data transfer primarily only handles some of the very low level h/w signalling like for arbitration.
Interrupts are used to trigger the s/w to track and move through the various states and load up the registers for the transfers.

Combine that with, IMO, whoever originally did the Arduino Wire library (which sits on top of some low level C code) , didn't appear to understand how the low level C code and h/w worked before they came up with their intended design.
IMO, it looks like they had assumed it worked or could work like the Serial port and that they could use ISRs to run in the back ground to push out the bytes.
Just look at the goofy uneeded double buffering that does on between the Wire.cpp code and the utility/twi.c code.
IMO, it was fairly braindead from the beginning as it wastes quite a bit of statically allocated memory given the way it works, particularly on the transmit side given the multiple output buffers.

The reason the Wire library can hang is because the low level s/w state machine is/was incomplete so there are a few cases where a foreground loop is waiting for an ISR to set to a flag that will never happen under certain situations.
Some of those are when there are multiple masters, a misbehaving slave, or noise on the bus signals.

--- bill

Well, for the present I will pass on that :grin:, but I am pleased that you confirm what I believe should be self-evident that there was never any reason for it to use interrupts and the fact that it does simply indicates gross incompetence, and particularly insofar as it may or does block other use of interrupts.

Why would it block other interrupts?

Like Bill, I guess that they intended to make I2C traffic seamless. i.e. like Serial quietly drains a small buffer as reasonably fast as you fill it.
So you seldom have to wait for space in the buffer.

Either they concluded that users would cause grief or they simply never implemented the plan.

David.

That isn't what I said or meant to say.
The low level twi code is interrupt driven and it has to be since it has to transition between various i2c bus states and there timing requirements that could not be met any other way.
In terms of blocking interrupts, the use of interrupts by the low level twi code doesn't block other interrupts.

What I was trying to say, is that the Arduino Wire library on the AVR started with some C code that implemented I2C and then added a C++ wrapper around that code. (Wire.cpp and Wire.h)
The low level C code supports some amount of deferred / background writes, it is the Wire library wrapper that does not support this.
The Wire library wrapper also added another layer of buffering for both directions, that was not needed as the twi code already support buffering on output prior to starting the actual transmission and had its own rx buffer.
So IMO, it is the Wire library Wire.cpp code wrapper that could and should have been done differently/better.

--- bill

1 Like

I find that a trifle suspicious. Oh well! :roll_eyes:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.