Dear gurus,
I have designed a DATA ACQUISITION SYSTEM AROUND UNO. I AM READING PROCESSING 5 SENSORS IN the main loop and Independently displaying the values on 7 segment display (max 7219 IC based) .
MY timer is displaying values continuously at a period of 1 seconds .
IT is obvious that my main loop is slower that the timer display rate. So I am using two variable for each sensor to store old and new value. And before displaying in timer ISR i am checking whether to display old value or new value for avoiding garbage value to be displayed. Still some times on full load i.e all sensors attached i get garbage value once a while on the display for any sensor.
I need to know how to sync the timer ISR based 7seg display with the sensor data in main loop.
timer ISR
display sensor output on 7seg max7219 IC based
main loop
processes and store sensor data . Internal 10 bit adc is used
Post your code.
Are you really using an interrupt to control output to your display?
interrupt is not excatly 1 second. as it 16mhz is not that accurate. 4 or 5 ticks less or more may be.
I just need a logic a little help.
//code is not exactly the same code.
void setup() {
int frequency = 1; // in hz
noInterrupts();// kill interrupts until everybody is set up
// Timer 1 b/c it's the only 16 bit timer
TCCR1A = B00000000;//Register A all 0's since we're not toggling any pins
// TCCR1B clock prescalers
// 0 0 1 clkI/O /1 (No prescaling)
// 0 1 0 clkI/O /8 (From prescaler)
// 0 1 1 clkI/O /64 (From prescaler)
// 1 0 0 clkI/O /256 (From prescaler)
// 1 0 1 clkI/O /1024 (From prescaler)
TCCR1B = B00001100;//bit 3 set for CTC mode, will call interrupt on counter match, bit 2 set to divide clock by 256, so 16MHz/256=62.5KHz
TIMSK1 = B00000010;//bit 1 set to call the interrupt on an OCR1A match
OCR1A = (unsigned long)((62500UL / frequency) - 1UL);//our clock runs at 62.5kHz, which is 1/62.5kHz = 16us
interrupts();//restart interrupts
Serial.begin(115200);
pinMode(13, OUTPUT);
}
volatile int seconds = 0; //make it volatile because it is used inside the interrupt
void loop()
{
if(channel_position>max_channel) //scanning and processing is done only on basis of chds feature
{
channel_position=0;
}
//Below switch scanns ,processes and displays channels as per nch setting //Curenntly four channel added// 27-12-2018//
switch(chanl[channel_position])
{
//changes done on 10-5-019 regarding channel 1 2 3 4 data availabilty ch4=0 etc
case 1://first channel
{
ch4=0; //this helps in avoiding display flicker. display only holding value
channel_scan_processor(chanl[channel_position]);
ch1=1;
break;
}
case 2://second channel
{
ch3=0;
channel_scan_processor(chanl[channel_position]);
ch2=1;
break;
}
case 3://third channel
{
ch2=0;
channel_scan_processor(chanl[channel_position]);
ch3=1;
break;
}
case 4://fourth channel
{
ch1=0;
channel_scan_processor(chanl[channel_position]);
ch4=1;
break;
}
/*ADD more cases for increasing channels*/
}
channel_position++;
}
}
ISR(TIMER1_COMPA_vect){ //Interrupt Service Routine, Timer/Counter1 Compare Match A
seconds++;
if(seconds >= 1) { //set to however many seconds you want
// This code is what happens
seconds = 0; // after 'x' seconds
digitalWrite(13, !digitalRead(13)); //
switch(chanl[timerchannel_scan])
{
case 0:
{
segdownwrite("noCh");
segupwrite2("-sel");
break;
}
//all channels only display the processed value effectively so if and else case used to display fresh value and previous value as well//
//10-1-19 edited p.r.b//
//ch1,ch2,ch3,ch4 are boolean variables to check whether the processing was done and the data that is to be displayed is latest and not corrupted//
case 1:
{
segdownwrite("Ch01"); //segaraweite not functioning properly for dcpt 0 27-2-2019
if(!ch1)segrawwrite(tempdisplayStr[1],(int)level2_eeprom_settings[1][6]);
else segrawwrite(displayStr[1],(int)level2_eeprom_settings[1][6]);
break;
}
case 2:
{
segdownwrite("Ch02");
// segrawwrite("-222.21",(int)level2_eeprom_settings[2][6]);
if(!ch2) segrawwrite(tempdisplayStr[2],(int)level2_eeprom_settings[2][6]);
else
segrawwrite(displayStr[2],(int)level2_eeprom_settings[2][6]);
break;
}
case 3:
{
segdownwrite("Ch03");
if(!ch3) segrawwrite(tempdisplayStr[3],(int)level2_eeprom_settings[3][6]);
else segrawwrite(displayStr[3],(int)level2_eeprom_settings[3][6]);
break;
}
case 4:
{
segdownwrite("Ch04");
if(!ch4) segrawwrite(tempdisplayStr[4],(int)level2_eeprom_settings[4][6]);
else segrawwrite(displayStr[4],(int)level2_eeprom_settings[4][6]);
break;
}
}
if(!level1_eeprom_settings[0] )
{
timerchannel_scan++;
}
}
}
If your sensors are too slow for a 1Hz refresh of the display, why force that rate with an interrupt?
I'd be more inclined to read one sensor per iteration of loop (which I think you are already doing) and update the display inline when the reading changes.
Also, interrupt routines are supposed to be as short and quick as possible. I've no idea how quick yours is, but short it isn't.