periodic readout of 4 channel ADC

I use a LTC2488ADC and read periodically channel 0 through 3 and show the values on LCD 4x16

first test used a 200 ms delay before set channel and readout channel and it works fine but it eats away 400 ms CPU time I need for other jobs

then I replaced delay(200) with a time laps procedure millis() etc.

But here I never get to channel 3 as it is mysteriously reset to 0 before reading channel 3.

oddly enough a debug command Serial.println(ADC_run); solved this problem but without my understanding. I tried delay() with different timings but it did not resolve it.

Where did I go wrong? I work on this problem since 3 days to no avail

source code attached

ADC_LTC2488-3.ino (7.76 KB)

Attach,code in line in code tags - can't read from mobile tablet

by the way: the used board is a MEGA

// set up the speed, data order and data mode
SPISettings settingsA(2000000, MSBFIRST, SPI_MODE0);

// … wait for ADC ready variables …
unsigned long start_time, used_time, delta_t, ADCdelay;
unsigned long s_time, e_time, laps;

boolean readADC , setADC, ADCready, set_read;

uint8_t stat, val1, val2, val3, result; // uint8_t = unsigned int 8 bit = byte;
unsigned long temp0; // 24 bit ADC value

unsigned int Temperatur[3]; // Hex Temperatur value of each channel
unsigned int CelsiusT;
float Celsius[3]; // scaled or mapped Celsius Degree
int ADC_run; // circle through ADC 0 - 3

// +++++++++++++++++ Set up +++++++++++++
void setup() {

Serial.begin(9600); // for debugging and communication

SPI.begin();
// read three bytes from device A
SPI.beginTransaction(settingsA);

// BEGIN( col,row) for LCD
lcd.begin(16, 4);
lcd.clear();
lcd.setCursor(0, 0); // colum 0 , row 0 = 1st and line
Serial.println();
Serial.print(" MOSI:");
Serial.print(PIN_SPI_MOSI); // to verify the correct pin selction for the selected hardware
Serial.print(" SCK:");
Serial.print(PIN_SPI_SCK);
Serial.print(" MISO:");
Serial.print(PIN_SPI_MISO);
Serial.print(" SS:");
Serial.println(PIN_SPI_SS);

lcd.write(" Magnet Heating “);
lcd.setCursor(0,1); // begin 2nd line
lcd.write(” Unit “);
lcd.setCursor(0,3); // begin of line 4
lcd.write(” Version 1.0 ");
delay(1000); // enable the user to see header and version

setADC=false; // enter channel select routine
readADC=false; //read selected channel
set_read=false; // toggle function ; if false set ADC true & readADC false
ADCdelay = 160; // equals to 160 ms waiting time for ADC conversion

ADC_run=0; // select channel 0 - 3
start_time=millis(); // set time to actual now
}
// +++++++++++ end setup +++++++++++++++++

void loop() {

used_time=millis(); // get actual time counter
if (used_time < start_time) start_time= millis(); // reset time after timer overrun
delta_t = used_time - start_time; // calculate actual time passed

if (delta_t > ADCdelay) // ADC ready for readout or channel select
{

Serial.println(ADC_run); // if this line is removed channel 3 can not be selected!!!

if (!set_read)
{
setADC=true; // enable channel select
readADC=false; // disable reading ADC
set_read=true; // toggle function select
}
else
{
setADC=false; // disable channel select
readADC=true; // enable reading ADC
set_read=false; // toggle function select
}

// } // end if

// ************ read ADC ***********

if (readADC) // if enabled start reading ADC
{

digitalWrite (PIN_SPI_SS, LOW); // chip select for ADC

// reading only, so data sent does not matter
val1 = SPI.transfer(0);
val2 = SPI.transfer(0);
val3 = SPI.transfer(0);

digitalWrite (PIN_SPI_SS, HIGH); // chip deselect

// create a 20 bit word out of 3 bytes ADC readings
temp0=0;
temp0= (temp0 | val1) << 8; // transfere a byte and shift left
temp0= (temp0 | val2) << 8; // tranfere 2nd byte and shift left
temp0 = (temp0 | val3) >> 4; // transfere 3rd byte and shift 4 unused bits right
// as the last 4 bits are not used in this version

Temperatur[ADC_run] = temp0 & 0xFFFF; // convert to integer and cut off status bits

CelsiusT = map(Temperatur[ADC_run],0x83,0xFFFF,0,50000); // 4 - 20mA scaling 0ºC - 50ºC

Celsius[ADC_run] = CelsiusT/1000.0; // the use of decimal point makse constand a float

// ======== display channel no, nominal value and actual value on 4x16 LCD
if (ADC_run == 0) {

lcd.setCursor(0,ADC_run); // set cursor in line 0 … 3
lcd.print(txt1);
lcd.print(ADC_run);
lcd.print(set0);
lcd.print(Celsius[ADC_run],3);
}

if (ADC_run == 1) {
lcd.setCursor(0,ADC_run); // set cursor in line 0 … 3
lcd.print(txt1);
lcd.print(ADC_run);
lcd.print(set1);
lcd.print(Celsius[ADC_run],3);
}

if (ADC_run == 2) {
lcd.setCursor(0,ADC_run); // set cursor in line 0 … 3
lcd.print(txt1);
lcd.print(ADC_run);
lcd.print(set2);
lcd.print(Celsius[ADC_run],3);

}

if (ADC_run == 3) {
lcd.setCursor(0,ADC_run); // set cursor in line 0 … 3
lcd.print(txt1);
lcd.print(ADC_run);
lcd.print(set3);
lcd.print(Celsius[ADC_run],3);
}

++ADC_run;
if (ADC_run >=4) ADC_run=0;

start_time = millis(); // restart ADC waiting time

} // end if {readADC}

if (setADC)
{

//send channel select to device
digitalWrite(PIN_SPI_SS, LOW); // not set by SPI lib ! chip select

SPI.transfer(SelChannel[ADC_run]);

digitalWrite (PIN_SPI_SS, HIGH); // chip deselct

start_time = millis(); // restart ADC waiting time
} // end if setADC

} // end if delta_t>

//} // end loop

}

Thanks but please edit the code above

Press ctrl-T or cmd-T in the IDE to indent properly, remove unnecessary empty lines etc this is just unreadable
Copy and paste within code tags (see how to use the forum for that)

Needs to look like this

// your code here

What’s this ?

  used_time=millis(); // get actual time counter
  if (used_time < start_time) start_time= millis(); // reset time after timer overrun

doing ??

What’s you deal with playing around with if (!set_read) ??

the millis() will overrun and reset to 0 after about 70 days. When this happens the resulting Delta time will become a minus value. This will avoid such a situation.

if (!set_read) --> first conversion cycle ist used to select the next channel, second cycle to read out selected channel. This routine toggles those 2 functions.

here the reformatted code.

the millis() will overrun and reset to 0 after about 70 days. When this happens the resulting Delta time will become a minus value. This will avoid such a situation.

if (!set_read) → first conversion cycle ist used to select the next channel, second cycle to read out selected channel. This routine toggles those 2 functions.

ADC_LTC2488-3.ino (7.79 KB)