This is the very first time i'm programming on arduino. Basically my project is about reading temperature of avr cpu with adc and then blink some leds. For instance if temp is let's say 35, i'll have 35 on my monitor, and a red led blink 3 times and a blue led who will blink 5 times; and if temp gets over 80 a yellow led will start blinking.
All this runs with timer1 with 1024 prescaler, and im using registers to setup and blink leds.
My problem is that the temp i get on monitor is not updated together with the temp that the leds blink. For example, temp is 27,on monitor i get 27, led blink 27 then after 4 seconds when timer1 ends temp is 28, led blink 28 but i get no 28 on screen. And this happens for some of the starting temperatures, after 4 or 5 temperatures they will finally be updated together. And im wondering why is this happening and i thought it could be because im using delay() so i wanted to see if anything changed by using millis() instead.
i know i should do something like this
void setup()
{
Serial.begin(115200); //start Serial in case we need to print debugging info
pinMode(ledPin, OUTPUT);
startMillis = millis(); //initial start time
}
void loop()
{
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //test whether the period has elapsed
{
digitalWrite(ledPin, !digitalRead(ledPin)); //if so, change the state of the LED. Uses a neat trick to change the state
startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
}
but i cant make it work with registers instead of digitalWrite/digitalRead
this is the code where i need to use millis() instead of delay
if anyone can give me some example code that would work in a for cycle using registers i would be very grateful
float offset=293.51;
float gain= 0.99;
void setup() {
TCCR1A = 0;
TCCR1B = 0;
TCCR1B=B00000101;
TIMSK1=B00000001; // attivo timer overflow interrupt
Serial.begin(9600); //stampo a monitor
DDRB=B11010000; // pin 12 in output
DDRD=B11110000; // pin 7 e 6 in output
ADMUX = 0b11001000; //metto a 1 REFS1,REFS0 e MUX3 per avere il confronto interno con 1.1V
ADCSRA= 0b10000111; // metto a 1 ADPS0, ADPS1, ADPS2 e ADEN per far partire la conversione
}
ISR(TIMER1_OVF_vect) {
ADCSRA |= 0b1000000; // metto a 1 ADSC per far partire l'ADC
while(ADCSRA & 0b1000000); // coverto...
int aRead= ADCL;
aRead |= (ADCH << 8);
float t= (((aRead)-offset)/gain); // converto e calibro la temperatura in gradi celsius
Serial.println(t);
checkTemp(t);
}
void loop(){
}
//////////////////////////////////
void ledBlink(int t){
int tempDecine=t/10;
for(int i=0;i<tempDecine;i++){
PORTD=B10000000;
delay(350);
PORTD=B00000000;
delay(350);
}
delay(350);
int tempUnita=t;
while (tempUnita>10){
tempUnita= tempUnita-10;
if (tempUnita==10){
tempUnita=0;
}}
for (int i=0;i<tempUnita;i++){
PORTB=B11010000;
delay(350);
PORTB=B11000000;
delay(350);
}
delay(3000);
}
void checkTemp(int t){
if(t>=80){
PORTD=B01000000;
delay(350);
PORTD=B00000000;
delay(350);
}else{
ledBlink(t);
}
}
Unless you're fiddling around with the timer that runs micros/millis, there should be no reason port register manipulation doesn't work just as well as using digitalRead/Write
Please remember to use code tags when posting code
I think your guess is wrong. It's tempting to fish for a way out of a problem, but this is really a far fetched attempt at a solution. It's far more likely that your code has some built in problem. What did you see that made you think it was a timing problem? It could be because of delay() but it could equally likely be caused by billions of possible other things.
Thanks for your answer, I am also new to this forum so I apologize for not using the right format for the code.
I have to use port registers because my professor wants it that way.
I find really hard to translate the function digitalRead to something with port registers. How can i return an output pin status (high or low) using registers?
ISR(TIMER1_OVF_vect) {
ADCSRA |= 0b1000000; // metto a 1 ADSC per far partire l'ADC
while (ADCSRA & 0b1000000); // coverto...
int aRead = ADCL;
aRead |= (ADCH << 8);
float t = (((aRead) - offset) / gain); // converto e calibro la temperatura in gradi celsius
Serial.println(t);
checkTemp(t);
}
This TIMER1_OVF_vect ISR is wrong for several reasons as pointed out by @ sterretje in post #4.
You would do better to only set a flag =true in the ISR and then respond to that flag in loop().