I’m developing a protection relay to college but i can not use analogRead inside a timerInterrup. Microcontroller stops when I do it.
SerialUSB.print("Leitura ADC: \t");
SerialUSB.println(analogRead(PA1));
And there are good reasons you should not do this.
Rather, set a global flag and restore interrupts. In your loop() you can interrogate the flag, perform the analog read inline or in a function, then reset the flag for later use.
Ray
Afterthought…
I’ve include some code written for the Attiny85 …. look carefully at how f_wdt is declared and used; that is:
volatile boolean f_wdt = 1;
then in the interrupt routine proper, this is the only active code:
f_wdt=1; // set global flag
/*
* Watchdog Sleep Example
* Demonstrate the Watchdog and Sleep Functions
* LED on digital pin 0
*
* KHM 2008 / Lab3/ Martin Nawrath [email protected]
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne
*
* Modified on 5 Feb 2011 by InsideGadgets (www.insidegadgets.com)
* to suit the ATtiny85 and removed the cbi( MCUCR,SE ) section
* in setup() to match the Atmel datasheet recommendations
*/
#include <avr/sleep.h>
#include <avr/wdt.h>
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
int pinLed = 0;
volatile boolean f_wdt = 1;
void setup(){
pinMode(pinLed,OUTPUT);
setup_watchdog(8); // approximately 4 seconds sleep
}
void loop(){
if (f_wdt==1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
f_wdt=0; // reset flag
digitalWrite(pinLed,HIGH); // let led blink
delay(1000);
digitalWrite(pinLed,LOW);
pinMode(pinLed,INPUT); // set all used port to intput to save power
system_sleep();
pinMode(pinLed,OUTPUT); // set all ports into state before sleep
}
}
// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {
cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // System sleeps here
sleep_disable(); // System continues execution here when watchdog timed out
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii=9;
bb=ii & 7;
if (ii > 7) bb|= (1<<5);
bb|= (1<<WDCE);
ww=bb;
MCUSR &= ~(1<<WDRF);
// start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
f_wdt=1; // set global flag
}
a) Get in, get out really fast. ISRs live on borrowed time. Mind the mutual exclusion principles.
b) Don’t call outside the ISR without knowing the other code obeys (a).
c) Rarely let one ISR interrupt another.
d) Read (a)
Some things don’t work inside interrupts as they use interrupts in their operation.
I’d definitely not write anything out to Serial (or USB Serial) inside an ISR, and I suspect that reading the Analogue is likely to use an interrupt i.e to flag that the “conversion” is complete.
Note. I’m not sure why you are using the USBSerial class as if you are using the bootloader, “Serial” is USBSerial (Serial1 is hardware serial 1)
e.g. I have some code that runs on a 100Hz extrernal interrupt trigger (AC mains freq x 2), and I need to read data from SPI after I get an interrupt.
But I don’t read from SPI in the ISR, I set a global volatile flag and then handle the SPI read in the main loop next time it checks the flag variable
I dont need to use Serial class in timer interrupt, I used it to verify what value is returned by analogRead. I tried to collect data from analogRead each xxx microseconds.
amostrasSinal[indexAmosta] = analogRead(PA1);
indexAmosta++; // Incrementa ponteiro
if(indexAmosta >= SAMPLES){ // Se alcançar a quantidade de amostras configuradas, zerar
indexAmosta = 0;
}
If its not doing anything else, then just setting a flag in the ISR will get picked up really quickly in the main loop.
I recall someone else posted a question about something similar and @ddrown posted a reply showing how you need to defined the flag variable as volatile and how many instructions this takes to process a tight while loop
The STM32 running at 72Mhz is quite a fast processor, so setting a flag in the ISR and processing it in the main loop is unlikely to give a massive delay.
60Hz is approx 16.666mS
show user how & what exactly?
say 100 samples, so every 3.6 degrees is 0.166mS or 166uS / sample
at 20usec sampling, that’s ( 16.666*1000uS )/20uS = 8333 samples
adc conversion takes how long?
didn’t someone do something with adc & dma recently? pig-o-scope
arduino loop executes every 24uS, really?
anybody else also puzzled?
srp
60Hz is approx 16.666mS
show user how & what exactly?
Generally unwise.
In fact you may need to re-code in assembler if timing is that critical, as its the only way you are going to be able to get more precise timings
NB.
All Micro’s does is miltiply the number of millis by 1000, and work out how long there is between the call to micros and the next millis tick (systick which occurs after 72,000 clock cycles
So Micro’s its self has quite a lot of overhead.
Perhaps if you explained exactly what you were trying to achieve with all these complex timings, we may be able to advise if you are just looking at the whole problem in the wrong way.
So Micro’s its self has quite a lot of overhead.
But I doubt you would find the information you need in the wiki
You will need to refer to the programming manual for the STM32F103 called RM0008 , which I think you can download from here http://www.st.com/web/en/resource/techn … 171190.pdf

