oberallgeier
04.12.2018, 19:56
In einem laufenden Projekt messe ich ständig die aktuelle Versorgungsspannung. Dazu wird die Versorgungsspannung 1:1 über einen Spannungsteiler 10k-10k an den ADC geleitet. Nach ersten Läufen wurden die in der Bauform TQFP verfügbaren ADC-Kanäle aktiviert - und das Drama begann. Es endet mit der Frage:
Wieso funktioniert der ADC-Kanal 7 bei meinem ATmega328P/TQFP@20MHz fehlerhaft?
Aufbau:
Steckbrett mit angeschlossener Experimentierplatine, auf der Huckepack ein arduino-nano-Clone (mit mega328P/TQFP) sitzt. Quarzfrequenz 20 MHz. Labornetzteil, Versorgung 7,5V/max. 1,5A - aktuell Verbrauch rund 47 mA. Der komplette ADC-Port wird auf Eingang konfiguriert, die erwähnten Erscheinungen treten mit und ohne gesetzten internem Pullup auf (noch mehr Grübelgrübel).
Die übliche Initialisierung:
/ ================================================== =========================== =
// === Initialisierung fuer ADC mega328P/TQFP mit Interrupt
// .. input clock frequency between 50kHz and 200kHz to get maximum resolution ..
// === ADC auf 10 Bit, Interrupt ausgelöst <=> free running
void ADC_init (void) // ADC3, free runng, 10 Bit, I-rupt; Aufruf: main
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ADCSRA |= (1<<ADATE); // Auto Triggering Enable doc S 307 + 319
ADMUX |= (1<<REFS0); // Referenzspannung ist AVcc 317
// AVCC with external capacitor at AREF pin
// ADMUX |= (1<<MUX2)|(1<<MUX1)|(1<<MUX0); // Wandlung mit ADC7 318
ADMUX |= (1<<MUX2)|(1<<MUX1); // Wandlung mit ADC6 318
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Prescaler = clock/128 320
// Prescaler NUR für system clck ==> 83,2 µs, gemessen (Oszi Gould) 83,5 µs
// <=> 12 019,23/sec (6,009 kHz)
ADCSRA |= (1<<ADIE); // ADC Interrupt Enable 319
ADCSRA |= (1<<ADEN); // ADC Enable 319
ADCSRA |= (1<<ADSC); // Free Rung .. to start the first conversion 319
//
volatile uint8_t adc3cnt1; // ADC-Wert wird x mal aufaddiert
volatile uint8_t adc3cnt2; // ADC-Wert wird x mal aufaddiert, nochn Teiler
} // Ende void ADC3_10_init_irupt(void)
// ================================================== ============================ =
Die ISR liest den Wert aus und fängt Fehlfunktionen bei zu niedriger Spannung ab:
// ================================================== ============================ =
// === ISR für ADC mega328P/TQFP ============================================== =
// Aufruf alle 83,2 µs, siehe oben (gemessen Oszi Gould: 83,5 µs).
ISR(ADC_vect) //
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
adc3_dat = ADC; // Hole Wert
adcs = adc3_dat; // aktuell ausgelesener Wert wird hier gesichert
// - - - - - - - - - - - - - - - -
if (adc3_dat < ADCMMM) // Mindestspannungsschwelle ADC wählbar beim Start
{ // es folgt ein Notstop wegen low battery
sei();
uputs0 ("\r\tADC \t\t"); // Melde AKTUELLEN ADC- I S T -Wert inf
itoa (ADC, abc, 10); // aktuell (adc-s = sicher) erfasster ADC-Wert
uputs0 (abc); // ... ausgeben inf
uputs0 ("\r\tSTOP"); //
cli(); //
while (1) {} // Notstop bei Unterspannung
} // Ende if (adc3_dat < ADCMMM)
} // Ende ISR(ADC_vect)
// ================================================== ============================ =
Das "Drama":
Nach anfänglichen Tests mit ADC-Kanal 3 wurde auf den im TQFP verfügbaren Kanal 7 umgestellt, siehe Initialisierungsroutine. Es folgten dauernd Abbrüche (Anmerkung: Mindest-ADC-Wert für Spannungsmessung ist auf 592 gestellt - Variablenname ADCMMM). Gegenprobe mit Kanal 3 lief mit sonst identischem Code fehlerlos. Aktuell ist Kanal 6 angewählt der ebenfalls in der Bauform TQFP verfügbar ist und klaglos funktioniert, wie die frühere Variante auf Kanal 3. Mit einigen Codeänderungen habe ich festgestellt, dass der Kanal 7 bei ansonst identischer Beschaltung/Versorgung statt ADC=763+/-2 nur etwa ADC=560 bringt. Die restlichen Kanäle bringen die genannten Messergebnisse ADC=763+/-1. Die genannten Werte wurden mit einem anderen nanoClone nachgefahren und waren dort innerhalb der hier genannten Toleranzen.
Die erwähnte Fehlmessung des Kanal 7 existiert auch, wenn im Sekundenabstand zehn Messungen hintereinander erfolgen. Auch dieser Fehler ist auf den den Kanälen 3 und 6 nicht feststellbar.
Daher obige Frage:
Wieso funktioniert der ADC-Kanal 7 bei meinem ATmega328P/TQFP@20MHz fehlerhaft?
Nächste Frage:
Kennt jemand dieses oder ein ähnliches Problem?
Danke für Rat, Hilfe und Erklärung.
Wieso funktioniert der ADC-Kanal 7 bei meinem ATmega328P/TQFP@20MHz fehlerhaft?
Aufbau:
Steckbrett mit angeschlossener Experimentierplatine, auf der Huckepack ein arduino-nano-Clone (mit mega328P/TQFP) sitzt. Quarzfrequenz 20 MHz. Labornetzteil, Versorgung 7,5V/max. 1,5A - aktuell Verbrauch rund 47 mA. Der komplette ADC-Port wird auf Eingang konfiguriert, die erwähnten Erscheinungen treten mit und ohne gesetzten internem Pullup auf (noch mehr Grübelgrübel).
Die übliche Initialisierung:
/ ================================================== =========================== =
// === Initialisierung fuer ADC mega328P/TQFP mit Interrupt
// .. input clock frequency between 50kHz and 200kHz to get maximum resolution ..
// === ADC auf 10 Bit, Interrupt ausgelöst <=> free running
void ADC_init (void) // ADC3, free runng, 10 Bit, I-rupt; Aufruf: main
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ADCSRA |= (1<<ADATE); // Auto Triggering Enable doc S 307 + 319
ADMUX |= (1<<REFS0); // Referenzspannung ist AVcc 317
// AVCC with external capacitor at AREF pin
// ADMUX |= (1<<MUX2)|(1<<MUX1)|(1<<MUX0); // Wandlung mit ADC7 318
ADMUX |= (1<<MUX2)|(1<<MUX1); // Wandlung mit ADC6 318
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Prescaler = clock/128 320
// Prescaler NUR für system clck ==> 83,2 µs, gemessen (Oszi Gould) 83,5 µs
// <=> 12 019,23/sec (6,009 kHz)
ADCSRA |= (1<<ADIE); // ADC Interrupt Enable 319
ADCSRA |= (1<<ADEN); // ADC Enable 319
ADCSRA |= (1<<ADSC); // Free Rung .. to start the first conversion 319
//
volatile uint8_t adc3cnt1; // ADC-Wert wird x mal aufaddiert
volatile uint8_t adc3cnt2; // ADC-Wert wird x mal aufaddiert, nochn Teiler
} // Ende void ADC3_10_init_irupt(void)
// ================================================== ============================ =
Die ISR liest den Wert aus und fängt Fehlfunktionen bei zu niedriger Spannung ab:
// ================================================== ============================ =
// === ISR für ADC mega328P/TQFP ============================================== =
// Aufruf alle 83,2 µs, siehe oben (gemessen Oszi Gould: 83,5 µs).
ISR(ADC_vect) //
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
adc3_dat = ADC; // Hole Wert
adcs = adc3_dat; // aktuell ausgelesener Wert wird hier gesichert
// - - - - - - - - - - - - - - - -
if (adc3_dat < ADCMMM) // Mindestspannungsschwelle ADC wählbar beim Start
{ // es folgt ein Notstop wegen low battery
sei();
uputs0 ("\r\tADC \t\t"); // Melde AKTUELLEN ADC- I S T -Wert inf
itoa (ADC, abc, 10); // aktuell (adc-s = sicher) erfasster ADC-Wert
uputs0 (abc); // ... ausgeben inf
uputs0 ("\r\tSTOP"); //
cli(); //
while (1) {} // Notstop bei Unterspannung
} // Ende if (adc3_dat < ADCMMM)
} // Ende ISR(ADC_vect)
// ================================================== ============================ =
Das "Drama":
Nach anfänglichen Tests mit ADC-Kanal 3 wurde auf den im TQFP verfügbaren Kanal 7 umgestellt, siehe Initialisierungsroutine. Es folgten dauernd Abbrüche (Anmerkung: Mindest-ADC-Wert für Spannungsmessung ist auf 592 gestellt - Variablenname ADCMMM). Gegenprobe mit Kanal 3 lief mit sonst identischem Code fehlerlos. Aktuell ist Kanal 6 angewählt der ebenfalls in der Bauform TQFP verfügbar ist und klaglos funktioniert, wie die frühere Variante auf Kanal 3. Mit einigen Codeänderungen habe ich festgestellt, dass der Kanal 7 bei ansonst identischer Beschaltung/Versorgung statt ADC=763+/-2 nur etwa ADC=560 bringt. Die restlichen Kanäle bringen die genannten Messergebnisse ADC=763+/-1. Die genannten Werte wurden mit einem anderen nanoClone nachgefahren und waren dort innerhalb der hier genannten Toleranzen.
Die erwähnte Fehlmessung des Kanal 7 existiert auch, wenn im Sekundenabstand zehn Messungen hintereinander erfolgen. Auch dieser Fehler ist auf den den Kanälen 3 und 6 nicht feststellbar.
Daher obige Frage:
Wieso funktioniert der ADC-Kanal 7 bei meinem ATmega328P/TQFP@20MHz fehlerhaft?
Nächste Frage:
Kennt jemand dieses oder ein ähnliches Problem?
Danke für Rat, Hilfe und Erklärung.