Forum: Mikrocontroller und Digitale Elektronik ADC nicht ganz verstanden oder fehl Interpretation


von amle (Gast)


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
}

von Stefan F. (Gast)


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.

von amle (Gast)


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?

von Stefan F. (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.