Forum: Mikrocontroller und Digitale Elektronik ADC-Werte falsch nur im Watchdog-Interrupt


von Lee (Gast)


Lesenswert?

Hallo,
folgende Situation habe ich.

1. Ich versetze meinen ATMEGA168 in den Standby-Mode.
2. Der MCU wacht durch den Watchdog-Interrupt auf.
3. In der ISR(WDT_vect) rufe ich eine Funktion read_adc() zur 
Spannungsmessung. Und die Werte der Messung stimmen nicht.

Mit der gleichen Funktion read_adc() bekomme ich aber im Programm 
außerhalb der WDT-ISR richtige Messwerte.

Kann jemand mir bitte helfen?

Danke für Eure Antworten
Lee

von STK500-Besitzer (Gast)


Lesenswert?

Alle Werte oder nur der erste nach dem Aufwachen?

von Lee (Gast)


Lesenswert?

Der erste Wert ist fast immer falsch. Ansonstens wie geschrieben, alle 
Werte in der ISR stimmen nicht, eher zu niedrig. Denn ich will mit der 
Messung Spannungen auswerten. Wenn sie unter 11,7V liegen, sollen es 
piepsen. Aber im Interrupt piepst es immer noch bei Spannungen unter 
11,95 V.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Der erste Wert ist immer falsch, da hier der ADC initialisiert wird. 
Warte den ersten Wert ab, verwirf ihn und lass den ADC noch einmal 
messen.

von Lee (Gast)


Lesenswert?

So sieht die Funktion read_adc aus:
1
uint16_t read_adc(uint8_t adc_source)
2
{
3
  uint16_t adc_result; 
4
  uint8_t count;
5
  cli();  // stoppe alle ISR
6
  
7
8
  ADCSRA |= (0 << ADPS2) | (1 << ADPS1) | (0 << ADPS0); // 1MHz sysclk -> ADC-clk = 125 kHz
9
10
  // Referenzspannung
11
  ADMUX |= ADC_VREF_TYPE; // Internal 1.1V Voltage Reference with external capacitor at AREF pin
12
13
  // Quelle
14
  ADMUX |= adc_source;
15
16
  // ADC aktivieren
17
  ADCSRA |= (1 << ADEN);
18
              
19
  // AD-Umwandlung starten
20
  // dummy readout 5 mal!
21
22
  for( count = 0; count < 5; count++ )
23
  {
24
25
    ADCSRA |= (1<<ADSC);      // eine Wandlung "single conversion"
26
27
    while ( ADCSRA & (1<<ADSC) );  // auf Abschluss der Konvertierung warten
28
29
    adc_result = ADCW;        
30
  }                  
31
                    
32
  ADMUX = adc_source | ADC_VREF_TYPE;
33
34
  // Jetzt startet die eigentliche Messung
35
  adc_result = 0; 
36
  for( count = 0; count < 8; count++ )
37
  {
38
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
39
    while ( ADCSRA & (1<<ADSC) ) ;  // auf Abschluss der Konvertierung warten
40
    adc_result += ADCW;          // Wandlungsergebnisse aufaddieren
41
  }
42
  ADCSRA &= ~(1<<ADEN);               // ADC deaktivieren 
43
 
44
  adc_result = adc_result >> 3;  
45
  
46
  sei();  // setzte alle ISR fort
47
  return adc_result;
48
}

von Lee (Gast)


Lesenswert?

Ich habe
1
 ADMUX = adc_source | ADC_VREF_TYPE;
einmal zu viel. Habe die Zeile gelöscht aber es ändert sich nicht an den 
Ergebnissen.

von Lee (Gast)


Lesenswert?

1
  ADCSRA |= (0 << ADPS2) | (1 << ADPS1) | (0 << ADPS0); // 1MHz sysclk -> ADC-clk = 125 kHz
wird auf
1
  ADCSRA |= (0 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // 1MHz sysclk -> ADC-clk = 125 kHz
korrigiert, also Frequenzteilerfaktor = 8.
Sorry, war mein Fehler beim Kopieren.

von STK500-Besitzer (Gast)


Lesenswert?

>(0 << ADPS2)

Das kannst du dir auch sparen...
Guck die mal den Artikel zur Bitmanipulation an.

von Lee (Gast)


Lesenswert?

Ja, aber ich will es für mich ein bisschen deutlicher machen.

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.