Hallo hab eine ADC Konvertierung und kriege auch fleißig Daten. Nur bei der Berechnung stimmt was nicht. Beispiel: Am ADC Eingang habe ich eine Spannung von 3,22V und eine Referenzspannung von 5V. Daraus folgt bei dem 10bit Wandler des Atmega164PA, das dies ein theoretischer Wert von 660 ist. Aber die Ausgabe am UART zeigt mir einen Wert von 639 an. Übersehe ich einen Offset, ist die Formel ADC-Wert = (U_adc * 1024) / U_ref falsch?
void AdcInit (void) { ADMUX=(1<<REFS0); ADCSRA = (1<<ADPS1)|(1<<ADPS2); /* ADC-Takt Prescaler = 64 */ ADCSRA = (1<<ADEN)|(1<<ADSC);/* ADC Enable und ADC Interrupt Enable setzen */ } und mit folgender Funktion lese ich diese aus uint16_t AdcRead (uint8_t ADC_Kanal) { /* Kanal waehlen, ohne andere Bits zu beeinflußen */ ADMUX = (ADMUX & ~(0x1F)) | (ADC_Kanal & 0x1F); ADCSRA |= (1<<ADSC); while (ADCSRA & (1<<ADSC) ) {} return ADC; }
Folgend wird dann der Wert ausgewertet: ADC_wert = AdcRead(PINA1); if (ADC_wert>=645 && ADC_wert<=758) { //tu was } else if (ADC_wert<=644 && ADC_wert>=600) { // tu was anderes } else if (ADC_wert<=599) { // tu was ganz anderes }
Wie genau ist die 5V Referenzspanning ? Die '5V' von USB ist oft nicht sehr genau. Check auch mal ob es einen pull-up Widerstand gibt am Eingang.
Die 5V kommen aus einem Linearregler und sind, ich sag mal vorsichtig relativ glatt. Naja sind dann auch net 5V sondern 4,96V. Pull-up versteh ich net ganz. Aber die DDR-REgister des ADC Ports werden nirgendsweiter im Code angefasst, falls du das damit meinst.
Rafi Dafi schrieb:
1 | > ADMUX=(1<<REFS0); |
2 | > ADCSRA = (1<<ADPS1)|(1<<ADPS2); /* ADC-Takt Prescaler = 64 */ |
3 | > ADCSRA = (1<<ADEN)|(1<<ADSC);/* ADC Enable und ADC Interrupt Enable |
Hiermit setzt Du die DAC-Frequenz auf F_CPU/2; die erste Zeile "ADCSRA=..." ist für die Konversion wirkungslos. Bei einer 10Bit-Konversion sollte die DAC-Frequenz < 200 kHz sein.
der bereich der ADC Frequenz soll ja zwischen 50 und 200 kHz. da ich mit einem Quarz von 7,3728Mhz arbeite, ergeben sich folgende min und max Werte für den Prescaler: 36,864 und 147,456, daraus folgt für den Prescaler entweder 64 oder 128. Laut Tabelle 23-5 ADC Presclaer selctions auf seite 260 aus dem Datenblatt des atmega 164PA muss adps1 und adps2 auf high gesetzt werden für 64 bzw. adps 1-3 auf High für 128. ich hab mich jetzt für 64 entschieden, werde aber morgen das mal mit 128 testen. schönen tag noch.
Rafi Dafi schrieb: > Laut Tabelle 23-5 ADC Presclaer selctions auf seite 260 aus dem > Datenblatt des atmega 164PA muss adps1 und adps2 auf high gesetzt werden Genau das tust du aber nicht (oder besser gesagt nur für sehr kurze Zeit), weil die Zeile danach beide wieder auf 0 setzt.
Du hast Dich zwar für einen Teilerwert von 64 entschieden, aber Dein Code repräsentiert das nicht, denn mit
1 | ADCSRA = (1<<ADPS1)|(1<<ADPS2); /* ADC-Takt Prescaler = 64 */ |
2 | ADCSRA = (1<<ADEN)|(1<<ADSC);/* ADC Enable und ADC Interrupt Enable |
setzt Du ADPSx effektiv auf 0, also auf F_CPU/2.
>Pull-up versteh ich net ganz. Aber die DDR-REgister des ADC Ports werden
nirgendsweiter im Code angefasst, falls du das damit meinst.
Ok das ist was ist meinte. Ich habe selber mal ein solches problem gehat
weil ich die Pull-Ups aktiviert hatte (oder das die standard aktiviert
sind, weisz ich nicht mehr). Aber dann erwartete man eine abweichung in
andere richtung.
Dabei habe ich noch gesehen das der ADC problemen geben kann bei 0V oder
5V aber das ist hier auch nicht der fall...
ja, da du aber ein "=" anstatt einem "|=" hast, wird der Prescaler wieder gelöscht
639 zu 660 für einen unkalibrierten AD ohne bandgap Vref ist doch nicht schlecht. Ein Blick in die Glaskugel ... 21.7.3 Offset Compensation Schemes The gain stage has a built-in offset cancellation circuitry that nulls the offset of differential mea- surements as much as possible. The remaining offset in the analog path can be measured directly by selecting the same channel for both differential inputs. This offset residue can be then subtracted in software from the measurement results. Using this kind of software based offset correction, offset on any channel can be reduced below one LSB.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.