ADC nicht ganz verstanden oder fehl Interpretation

Gast #6596885
Lesenswert?

Guten Tag
Ich habe hier etwas code betreffend einer Abfrage des ADC von Arduino, 
der soweit funktioniert. Jedoch wenn ich 2 ADC Abfrage sind die 
Variablen analgValue0/1 vertauscht, warum?

Siehe demarkieren von !!!!!!!! (ADMUX = ADCH1;)
Kann mir da jemand helfen?
Danke.
1
#include <Arduino.h>
2
#define ADC0 0
3
#define ADC1 1
4
#define ADCH0 ((1 << REFS0) | ADC0)
5
#define ADCH1 ((1 << REFS0) | ADC1)
6

7
volatile int analogValue0;
8
volatile int analogValue1;
9
void setup() {
10
  Serial.begin(115200);
11
  ADC_Init();
12
}
13

14
void loop() {
15
   Serial.print("Value1: ");
16
   Serial.print(analogValue0);
17
   Serial.print("   Value2: ");
18
   Serial.println(analogValue1);
19
}
20

21
// Function:    snaAdcIntSetup()
22
// Description: This funtion sets up the ADC for generating interrupts.
23
// Arguments:   None
24
// Returns:     None
25
void ADC_Init() {
26
  // Set for the first ADC channel.
27
  ADMUX = ADCH1;
28
  // 0=2,1=2,2=4,3=8,4=16,5=32,6=64, 7=128
29
  ADCSRA = (1 << ADEN) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); 
30
  ADCSRB = 0;
31
  sei();
32
  ADCSRA |= (1 << ADSC);
33
}
34

35
// The ADC interrupt function.
36
ISR(ADC_vect) {
37
  int iCannel = ADMUX & ((1 << MUX3) | (1 << MUX2) | (1 << MUX1) | (1 << MUX0));
38
  switch (iCannel) {
39
    case ADC0:
40
      analogValue0 = ADCL | (ADCH << 8);
41
      // !!!!!!!!!!!!! für den zweiten kanal unmarkieren, dann sind die werte vertauscht
42
      //ADMUX = ADCH1;
43
      break;
44
    case ADC1:
45
      analogValue1 = ADCL | (ADCH << 8);
46
      ADMUX = ADCH0;
47
      break;
48
  }
49
  //ADCSRA |= (1 << ADSC);
50
}
Gast #6596916
Lesenswert?

> analogValue0 = ADCL | (ADCH << 8);

Kleiner Tipp: Das kannst du einfach  "analogValue0 = ADC" schreiben.

Nur zur Erklärung deines Phänomens:

Dein ADC läuft im Free-Running Modus, er misst also fortlaufend. Sobald 
eine Messung fertig ist, wird die ISR aufgerufen. Du schaltest dort den 
Kanal um, aber während dessen läuft bereits die nächste Messung. Der 
Kanalwechsel wirkt sich daher erst auf die  Messung danach aus.

Bei zwei Kanälen läuft es also daher auf die von dir beobachtete 
Vertauschung hinaus. Wenn du mehr als zwei Kanäle hättest, würdest zu 
einen Zirkulären Versatz um 1 Position beobachten.
Gast #6596980
Lesenswert?

Ja danke, das dachte ich mir und ja den Versatz um 1 habe ich bemerkt, 
leider.

Aber das vorgehen ist doch richtig oder mache ich da was falsch?
Getrennt kann man die IRQ ja nicht definieren ohne grösseren Aufwand?
Gast #6597004
Lesenswert?

amle schrieb:
> Aber das vorgehen ist doch richtig oder mache ich da was falsch?

Ja das ist richtig. Gegen den Versatz kannst du im free-running Modus 
nichts machen. Der wäre nur bei Einzelmessungen vermeidbar, die übrigens 
auch Interrupts nutzen könnten.

Wenn du den ADC innerhalb der ISR jedes mal neu starten würdest, hättest 
du weniger Messungen pro Sekunde. Und jedes mal wenn ISR kurz gesperrt 
sind, würde es sich entsprechend verzögern.

Ob das so zu deiner Anwendung passen würde, musst du selbst entscheiden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren