Skip to content

Add support for reading single continous from ISR - #26

Open
drLaba wants to merge 1 commit into
CuriousScientist0:mainfrom
drLaba:ISR
Open

Add support for reading single continous from ISR#26
drLaba wants to merge 1 commit into
CuriousScientist0:mainfrom
drLaba:ISR

Conversation

@drLaba

@drLaba drLaba commented Dec 23, 2025

Copy link
Copy Markdown

Hi! First, thank you very much for the library. And for the documentation provided!

I used the library in a project with data read from several sensors, including one ADS1256. The sensors took some time to read, and thus with high sampling rates, ADS1256 didn't get the chance (time) to read its value before it was overwritten (by the next high-frequency ADS1256 measurement).

In general — reading values from ADS1256 in an interrupt, and buffering them (storing temporarily), allows to use the library alongside other, slower to execute, code.
The approach was succinctly explained by dr Bonet over on Arduino Stack Exchange.

This pull request uses interrupts differently than the way they have been used previously in the library (54c63e5).
It does not impact the existing read___() and cycle___() methods*.
Here, data from ADS1256 is read in the interrupt.

To achieve it, I've added:

  • "Stripped down" version of readSingleContinuous()readSingleContinuousImmediately().
    This method does not wait for the desired state (LOW/HIGH) of DRDY signal.
    I've considered also readSingleContinuousFromISR() to align with ESP32's FreeRTOS naming convention, but decided it may imply too much.
  • Helper method for attaching the interrupt setInterruptFunction().
    I've decided to include it in the library, because the PIN number of DRDY and signal indicating ready data (FALLING) are both known to the library, and constant.
  • *I've extracted the acquisition initializing code to a separate startSingleContinousConversion() method, to be used: manually when using this new interrupt-based approach, and called from within readSingleContinuous() instead of the code being inline. readSingleContinuous() stays backwards compatible.

I tried to keep the library's coding style and conventions.

I believe the implementation is specific to each project, so I didn't add an example code use case.

  • One option (most probably the preferred one) is to use a ring buffer as explained by dr Bonet.
     void ARDUINO_ISR_ATTR ADS1256DataReadyCallback()
     {
     	ads1256_ring_buffer.push(ads1256->readSingleContinuousImmediately());
     }
    
     // Inside the main loop:
     while (!ads1256_ring_buffer.empty()) {
     	process_ads1256_data(ads1256_ring_buffer.pop());
     }
  • Since my project is based on FreeRTOS, I've used a FreeRTOS queue with good performance (30 kHz ADS1256 alongside 800 Hz built-in ADS, 800 Hz first BMI160, and 200 Hz second BMI160). I don't have experience with ring buffers, so although my simple implementation worked, I was afraid of the possible pitfalls, and went with predesigned queue as a safer choice. The flow could be as follows:
     void ARDUINO_ISR_ATTR ADS1256DataReadyCallback()
     {
     	readout = ads1256->readSingleContinuousImmediately();
    
     	xQueueSendFromISR(readoutsQueue, &readout, NULL);
     }
    
     void setup() {
     	ads1256 = new ADS1256(<<settings>>);
    
     	ads1256->InitializeADC();
    
     	ads1256->setMUX(<<value>>);
     	ads1256->setPGA(<<value>>);
     	ads1256->setDRATE(<<value>>);
    
     	ads1256->startSingleContinousConversion();
    
     	ads1256->setInterruptFunction(ADS1256DataReadyCallback);
     }
    
     void loop() {
     	// read other sensors
    
     	while (xQueueReceive(readoutsQueue, &readoutTemp, 0) == pdPASS)
     	{
     		processADS1256Data(readoutTemp);
     	}
     }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant