Fast readings from ADS7828 without time gaps

Dear community,

my device have ADS7828 and 3.5" TFT display. ADS7828 communicate with I2C and TFT with SPI. I want to read ADS7828 fast, under 1ms to analyze input signal. I plan to redraw whole TFT for example every 250ms. Redrawing whole display area took some time. Not know exact value, but for example 100ms. And here is a problem - while drawing I can not read from ADS7828...

So, is it possible to reading from ADS7828 via interrupt every 1ms (or below 1ms) even while drawing? I never done this before and not know if this will work.

Does someone have an experience with ADS7828? I want to use all 8 channels as single-input. In datasheet is mentioned sample-and-hold feature. Does anyone know how this work?

Thanks!

You can set up a timer interrupt that triggers every 1 ms.

The problem is: you can NOT read this chip within the ISR as while you're in the ISR interrupts are disabled, so you can not communicate over I2C (even if that would be a good idea considering that an ISR is supposed to finish fast). All you can do in the ISR is set a flag asking your other processes to go ahead and read it.

What are you even trying to do, really? Reading an 8-channel 12-bit ADC produces at least 16 bytes of data, so you fill up your memory in a mere 128 reads (128 ms). That's without using memory for anything else - drawing a display will also require a significant amount of memory.

Thank you for your answer.
What do you mean use ISR interrupt for setting the flag for other process? Global variable? I am using MCUFRIEND_kbv.h where is command tft.fillScreen(BLACK); This command took lots of milliseconds to do because it will change color of all pixels of TFT. Is there a way how to do ADS7828 reads while Arduino processing this command?

I will not store all the datas. I only want to "catch" highest value of peaks which can last from 10 to 200 milliseconds.

Thank you.

unknow001:
Thank you for your answer.
What do you mean use ISR interrupt for setting the flag for other process? Global variable?

Indeed - and then the other process has to check for it and act on it.

The tft process is apparently blocking, and not giving back control to your sketch until it’s done. So that flag will be checked for only when it’s done - so that’s no use for you.

One solution would be to hack that library, and have it return control to you all the time.

Another solution would be for you to write the pixels one by one (as I understand that’s what that command does in one go), then check between every pixel write whether 1 ms has passed, if so, read that ADC.

Something like:

unsigned long lastMillis = millis();
for (byte x = 0; x < screenWidth; x++) {
  for (byte y = 0; y < screenHeight; y++) {
    if (millis() > lastMillis) {
      readADC();
      lastMillis++;
    }
    tft.setPixel(x, y, BLACK);
  }
}

Something like that: writing a single pixel will take less than 1 ms, hopefully far less, so every 1 ms you can go and read the ADC and do something useful with the data.

Do note that depending on the underlying library this may be terribly inefficient. You should also have a look at how it’s done within your tft library.

Another problem: how long does this ADC read take? I2C is pretty fast, but still it takes time. It may take nearly 1 ms for a single read to complete, in which case there’s basically no time left to write the pixels on your screen.

If that’s the case, probably the best solution is a second Arduino. One to do the ADC reading, a second to take care of the screen.

Thank you for explanation.
That ISR interrupt is Timer1? I read somewhere that Timer1 priority change can solve problem with blocking I2C. Than I should have Timer1 and I2C at the same time. But maybe I misunderstood it.

I know in general you can't do I2C communications in an ISR.

Just thinking: you're reading 16 bytes of data, plus I2C overhead this takes about 0.5 ms on a 400 kHz bus (default is 100 kHz - that would take about 2 ms per read). So you'd have to set your I2C clock to that speed to begin with. Then still you spend about half the time communicating on I2C, so your screen draws (if you even can do it pixel by pixel) are also taking double the time.

It seems that this is one of those rare situations that a second Arduino is in order. One exclusively for reading the ADC and finding peaks; the other to handle your screen and other tasks such as reading buttons or whatever you need it to do. Or a faster processor, one that can handle a 3.4 MHz I2C bus. A Teensy or so.

So ... 100kHz = 100Kbit/sec = 12.5kB/sec = 12.5B/ms ... yes, one reading from all 8 channels took max 2ms. I think it is good speed. I will redraw whole tft panel by pixels, draw text by chars etc. and between I will read from ADS7828.

Thank you.

unknow001:
So, is it possible to reading from ADS7828 via interrupt every 1ms (or below 1ms)

unknow001:
one reading from all 8 channels took max 2ms. I think it is good speed.

Mmm....
It always helps when you know your requirements clearly.

Increasing speed on I2C (to 400 kHz) and SPI (up to 8 MHz iirc is possible on an Arduino) will make all that communication go faster, make your program run faster, make you get more sampling, make you get a better peak detection.

Readings below 1ms is requirement. Real 2ms is acceptable solution. I not know if 400kHz will work. Need to test it.

Both the ADS7828 and the Arduino support that speed just fine.