TIMER1_COMPA is configured as a 0.5s timer (aprox)
ADC_VECT is just here because I used ADCL and ADCH inside TIMER1.
INT0_vect it is a triggering and it fires at 1s
The program works fine with TIMER1 and ADC_VECT.....but it works continuosly and I want that INT0_VECT (a photosensor) would make the trigger to adquire the data.
When In insert INT0_VECT, it has an chaotic behaviour
Is it possible or the ATMega just can't handle the three interrupts working at the same time?
Before I conected the photosensor to the int0 pin I have tested with a little program that with or without light I have a 0 or 1 logic. I calculate a tension division for that purpose. During 30 minutes with a flashing light at 2 lighting per second no error ocurred.
And allanhurst yes, probably I'm doing it wrong but I don't get the point. I think the problem it is not in the interrupts, it is in loop.
I need to disable interrupts when I have to send a burst of data throw serial and it seems when I reactivate them sometimes never reactivate so the program doesn't work.
So I guess it is my sw problem and not a problem of the interrupts.
But. Is there any possibility I crush the arduino? Because it freezes after some seconds and I only ocuppied 55% of the mem....
I am not sure what are you trying to achieve but:
cli(); disables all interrupts
sei(); enables all unmasked interrupts
When entering interrupt routine interrupts are disabled (as if you called cli(); as the first command)
When leaving ISR unmasked interrupts are enabled (as if you called sei(); as last command)
Calling sei(); inside ISR is unwise unless you know what you re doing - the interrupt can trigger again and again and you may run out of RAM (entering ISR including pushing some registers to the Stack possibly corrupting data if RAM is low). I suspect it may be your problem.
If you don't call sei(); inside the ISR you cannot enter ANY ISR until you finish the current ISR being executed - so you cannot get result from ADC ISR inside TIMER ISR - do you know it?
There is no multilevel priority in the 328 processor. Once an interrupt is being serviced, no other interrupts can interrupt it. Although I guess one can work around it if needed (never worked with interrupts on a 328). Only if two or more interrupt flags are set at the moment that the processor checks, the priority will determine which one will be serviced first.
With the timings that you mention (0.5 seconds and 1 second), do you really need interrupts? Can't you handle this in the loop(), possibly by using millis() for the timing?
Here you have part of the code. The rest is just configuration of timer and adc, but that works fine, I tested in other program without problem.
......
EICRA |= (1 << ISC00); // set INT0 to trigger on ANY logic change
EIMSK |= (1 << INT0); // Turns on INT0
sei();
}
void loop() {
if (i==500 ){ //if the array is filled, then send it
cli(); //stop interrupts to send via serial
for (i=0; i<500; i++){
Serial.println(data[i]);
}
}
sei(); //activate interrupts
}
ISR(TIMER1_COMPA_vect){//controls when I take the sample.
aval = ADCL;
aval += ADCH<<8 ;
data[i]=aval;
i++;
}
ISR(ADC_vect) {
}
ISR (INT0_vect) { //when I receive a change in the state (light to dark or dark to light) activate
i=0; //ok, you can start to fill the array.
}
I believe Serial.println depends on interrupts. When you disable them via cli() you run into troubles. The Serial buffer will overflow and you will get strange results.
I need to disable interrupts when I have to send a burst of data throw serial
Serial.print() requires interrupts to function, and this is code disabling and reenabling interrupts is not right.
void loop() {
if (i==500 ){ //if the array is filled, then send it
cli(); //stop interrupts to send via serial
for (i=0; i<500; i++){
Serial.println(data[i]);
}
}
sei(); //activate interrupts
}
Do you have i and data[] declared as volatile?
When i = 500 you need to make a protected copy of the data by disabling interrupts, transferring the data into another working array, and re- enabling interrupts to restart the data collection of another 500 values. Print or analyse the data in the working array while data is collected by interrupts in the background.
Also do you have variables used in ISRs declared as volatile?
I think the real problem is here:
The Compare Match interrupt will increment i over 500 and data will get out of the declared array and corrupt your data unless reset foom external interrupt come soon enough.
auch! that hurts, I supposed that serial.println didnt use interrupts.
THe thing is that I need to collect a window of 500ms and send it throw serial to matlab before another window start. I have like 600ms to send all that data so during that time I dont need any new sample.
So the flow chart is
Trigger
adquire data
send data
wait until trigger
But if I didn't stop interrupts during the "send data" new data would come.
ANd if I put flags inside the interrupts, I didn't keep them short xD.....
The program works fine with TIMER1 and ADC_VECT.....but it works continuosly and I want that INT0_VECT (a photosensor) would make the trigger to adquire the data.
When In insert INT0_VECT, it has an chaotic behaviour
If you're using photosensor with LM393 comparator, there's likely no feedback (hysteresis) in the design, so the digital signal is quite noisy and would create many, many false interrupts on each edge of the pulse. This could explain the chaotic behavior. The solution here was to add a capactior from D0 to GND on the sensor module.
You can leave all the interrupts alone, and stop Timer1 by writing the prescaler to 000 after you collect the 500 samples. Then the trigger can reset TCNT1 = 0 and start the timer running by writing the desired prescaler.
I believe Serial.println depends on interrupts. When you disable them via cli() you run into troubles. The Serial buffer will overflow and you will get strange results.