Hello,
I am trying with an Arduino UNO to read data from the ADC at a specific frequency triggering the conversion with the Timer1 COMPB, and then at a slower rate to print a big message using Timer0 interrupts.
Putting pin toggle on each interrupt, I see that the biggest the message on timer0 interruption, the slower work the Timer1 interruption. (according to my oscilloscope)
But according to the datasheet the Timer1 interrupt should have a higher priority level than Timer0 Interruption.
There is a fault in the documentation?
Here my code:
#include <avr/sleep.h>
#define ALLMUX 0x0f
int ledbl = 13;
int ledbl2 = 12;
int ledbl3 = 11;
int ledbl4 = 10;
int c = 1;
int analogPin = 3;
int analogVal[4] = {0,0,0,0};
float voltageVal[4]={0,0,0,0};
float VrefInt = 1.1;
float analogStepInt = VrefInt / 1024;
boolean toogle0=0;
boolean toogle1=0;
boolean toogle2=0;
boolean toogle3=0;
int channelADC =0;
void setup() {
pinMode(ledbl, OUTPUT);
pinMode(ledbl2, OUTPUT);
pinMode(ledbl3, OUTPUT);
pinMode(ledbl4, OUTPUT);
digitalWrite(ledbl, LOW);
digitalWrite(ledbl2, LOW);
digitalWrite(ledbl3, LOW);
digitalWrite(ledbl4, LOW);
Serial.begin(9600);
Serial.print("\033[1;1H\033[JStarting measure with 1.1V on 4 channel\n\rA0 = that mean\n\rA1 = that mean\n\rA2 = that mean\n\rA3 = that mean\n\r");
//while(!(UCSR0A==UCSR0A&(1<<TXC0)));
//ADC init trigger mode on timer0, and end measure interrups
ADMUX=0; //reset to init
ADMUX|=((1<<REFS1)|(1<<REFS0)); //set measure reference to internal voltage 1.1V
ADMUX=ADMUX&~ALLMUX; //reset to init
ADMUX|=channelADC; //select ADC channel ADC0
ADCSRA=0; //reset to init
//ADC enable, autotrigger enable, ADC interrupt enable, ADC clk rescaler to /128 -> 16MHz/128= 125kHz
ADCSRA|=(1<<ADEN)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
//trigger mode 14 clk (13.5) for convertion (1/125kHz)*14=112us
ADCSRB=0; //reset to init
ADCSRB|=(1<<ADTS0)|(1<<ADTS2); //set timer1 compB as ADC trigger
DIDR0=0; //reset to init
DIDR0|=ALLMUX; //disable digital input on ADC0-4
set_sleep_mode( SLEEP_MODE_ADC );
sleep_enable();
cli();//disable interrupt
//set timer0 interrupt information print
TCCR0A=0; //reset to init
TCCR0B=0; //reset to init
TCNT0=0; //reset to init
OCR0A=156; // 15.625kHz/100Hz=156kHz => 15.625kHz/156=100.16025
TCCR0A|=(1 << WGM01); //set timer2 mode to CTC
TCCR0B|=(1 << CS02)|(1 << CS00); //set prescaler at /1024 so timer0clk at 15.625kHz
TIMSK0|=(1 << OCIE0A); //enable compA interrupts
//set timer1 interrupt 7.1kHz ADC trigger and control
TCCR1A=0; //reset to init
TCCR1B=0; //reset to init
TCNT1=0; //reset to init
OCR1A=2254; // 16MHz/7.1kHz ~= 2254 => 7.09849kHz = 140.8us
OCR1B=320; // (1/16MHz)*320=20us => 140.8us-20us=120.8us for the convertion
TCCR1B|=(1 << WGM12); //set timer1 mode to CTC
TCCR1B|=(1 << CS10); //set prescaler at /1 so timer1clk at 16MHz
TIMSK1|=(1 << OCIE1A)|(1 << OCIE1B); //enable compA and CompB interrupts
sei();//enable interrupt;
}
ISR(TIMER1_COMPA_vect){//timer1 compA interrupts
if(toogle2==0)digitalWrite(ledbl3, HIGH);
else digitalWrite(ledbl3, LOW);
toogle2^=0x01;
analogVal[channelADC]=ADCL|((ADCH&0x03)<<8); //read before low and then high or the value are not updated
channelADC++;
if(channelADC>=4)channelADC=0;
ADMUX=ADMUX&~ALLMUX;
ADMUX|=channelADC;
//space for digital filter
//
//
}
ISR(TIMER1_COMPB_vect){//timer1 compB interrupts
if(toogle3==0)digitalWrite(ledbl4, HIGH);
else digitalWrite(ledbl4, LOW);
toogle3^=0x01;
}
ISR(TIMER0_COMPA_vect){//timer1 interrupt
digitalWrite(ledbl2, HIGH);
for(int i=0;i<4;i++){
voltageVal[i] = analogVal[i] * analogStepInt;
}
String initCursor = "\033[2;6H \033[2;6H";
String fullMsg=initCursor +analogVal[0] + "\033[2;21H" + voltageVal[0] + "V\033[3;6H \033[3;6H"+analogVal[1] + "\033[3;21H" + voltageVal[1] + "V\033[4;6H \033[4;6H"+analogVal[2] + "\033[4;21H" + voltageVal[2] + "V\033[5;6H \033[5;6H"+analogVal[3] + "\033[5;21H" + voltageVal[3] + "V";
Serial.println(fullMsg);
digitalWrite(ledbl2, LOW);
}
ISR(ADC_vect)
{
if(toogle0==0)digitalWrite(ledbl, HIGH);
else digitalWrite(ledbl, LOW);
toogle0^=0x01;
}
void loop() {
//if nothing to transmit, then go sleep
if(UCSR0A==UCSR0A&(1<<TXC0))
sleep_cpu();
}
P.S. I know that sending a message in Timer0 interruption isn't a good idea, but even if I remove the message, the fact that the priority didn't match still a problem.
P.S.S The strange stuff I write are in ANSI escape code, I use it to move the cursor in the terminal