Pages: [1]   Go Down
Author Topic: Arduino Uno get's stuck when doing analogRead  (Read 486 times)
0 Members and 1 Guest are viewing this topic.
Berlin
Offline Offline
Newbie
*
Karma: 0
Posts: 4
physicist, nerd, music-lover
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Dear all,

I'm writing a program that uses the Arduino as an A/D-Datagrabber, we try to measure some voltages of capacitors and that measurement should happen right after a falling pin-voltage. For this i wrote a function with a for-loop that writes the AnalodRead-values of the Pins A0-A3 into an array and then gives out the values of this array via Serial. If i put this code into the void loop(), it works, but then the Ardunio is not doing the measurement i want when the interrupt is triggerd. If i put the same code into a function and try to call it via Interrupt, the Uno-board get's stuck and does nothing anymore until i reset it.

This is the code:
(sorry that some is still german, i'm too lazy to translate all the variables  smiley-confuse)

Code:

double Vcc;                     //Value of reference voltage
unsigned long Anfang;      //Timeflag for time measurement
double Werte[] = {0,0,0,0}; //Array for measurement values
int Pins[] = {A0,A1,A2,A3}; //Array that gives the pins that are to measure


/* Code for generating the reference voltage

Code von http://code.google.com/p/tinkerit/wiki/SecretVoltmeter */

long readVcc() {
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1125300L / result; // Back-calculate AVcc in mV
  return result;
}

void setup() {
  Serial.begin(9600);   
  attachInterrupt(0,measure,FALLING); //Interrupt 0 (=Pin 2) calls measure() if Voltage is dropping
}



void loop() {
  //empty, all functions are implemented in measure()
}



void measure()

 //Get start-timestamp
  Anfang = micros();

 //measure reference voltage
  Vcc = readVcc()/1000.0;

  //A/D-Grabbing
 
  for (int i=0;i<4;i++) {
    Werte[i]=analogRead(Pins[i]);
  }
  Serial.print("\tDauer der Messschleife: ");
  Serial.print(micros()-Anfang);   
  Serial.println("mikrosek");
 
 //Get start-timestamp
  Anfang = micros();
 
  //Print out measured values
  for (int i=0;i<4;i++) {
    Serial.print("Analog-Eingang = " );                       
    Serial.print(Pins[i]);       
    Serial.print(" Wert = " );                       
    Serial.print(Werte[i]);     
    Serial.print("\tEntspricht der Spannung = ");     
    Serial.println(Werte[i] / 1023 * Vcc);
  }
  //Print out time needed for process
  Serial.print("\tDauer der Ausgabeschleife: ");
  Serial.print(micros()-Anfang);
  Serial.println("mikrosek");
}

Again: If i use this code as it is, the Arduino stops working as soon as the Interrupt is called. I checked this by putting a small "serial.print "watining" - delay 1sec" into the main loop. The Arduino freezes as soon as the trigger comes.

If i put the exactly same code into the main loop, it works and reads the for pins, gives their values and the time needed for the measurement. But i need to have this done with the interrupt. I also tried to block another Interrupt call by putting (no)Interrupts() into measurement(), but this wont help.

Is there something in the measurement-function that is not working with interrupt-calls or do i miss something else?

Any suggestion is welcome.

Thanks,
Sascha
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26287
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial output and delays in an interrupt?
Well, that certainly ticks the boxes for a freeze.

A single analogRead takes around 100us.
Even that is far too long to be doing in an interrupt.
« Last Edit: February 12, 2013, 08:25:59 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 114
Posts: 4257
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Serial.print in an interrupt routine.  Naughty !
Multiple Serial.prints in an interrupt routine.  A capital offence !!
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Berlin
Offline Offline
Newbie
*
Karma: 0
Posts: 4
physicist, nerd, music-lover
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, then. Looks like a no-brainer for experienced guys ;-)

As i said, it's not helpful if the programm spams the measured values in a loop, but maybe i can swap the serial-printout part out of the measure() function into another one that is NOT called by an interrupt. It's not mandatory that the printout comes right after the measurement.


Thanks so far!
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26287
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It may be that you don't need an interrupt at all, just a fast polling loop.
If you do find that an interrupt is necessary, because the trigger signal is short and could be missed by a polling loop, then have the service routine simply set a flag that is then examined (and eventually reset) by the main loop.
Don't forget to declare the flag "volatile".
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Berlin
Offline Offline
Newbie
*
Karma: 0
Posts: 4
physicist, nerd, music-lover
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, if you say that even one AnalogRead is too long for the Interrupt, then i should go for a signal-polling, since the later full-scale version of this shall measure 16 Analog-Ins on an Arduino Mega.

Thanks for the hints guys!
« Last Edit: February 12, 2013, 08:54:00 am by sascha_held » Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6614
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Alternatively, just kick off the conversion in the interrupt service routine, and read the value when you get the conversion complete interrupt.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Berlin
Offline Offline
Newbie
*
Karma: 0
Posts: 4
physicist, nerd, music-lover
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, just a small thank you: Yesterday i had the time to try the new code (the interrupt only changes a "trigger" boolean while the main loop checks if this bool is set and then starts the AD-converter code.
It finally worked, now i can try out the prototype that we build.

Thanks for the support!
Logged

Pages: [1]   Go Up
Jump to: