Hi Hab mal wieder ein kleines Problem. Bin gerade dabei mit meinem Atmega32 4 ADC werte einzulesen das klappt auch alles einwandfrei wenn ich immer nur 1 ADC benutze. Sobald ich aber mehrere benutze und die Kanäle wechsele bekomme ich sehr merkwürdige Werte. Hab im Anhang ein Teil meiner Platine (jedoch sind die Dioden im moment nur brückendrähte. Wie im Toturial beschrieben nutze ich eine einfache variante, denn Spannungsteiler. Wenn ich jedoch jetzt die Kanäle ändere ist auf allen Kanälen +- 20 jeder wert gleich und eine änderung bring so gut wie keine veränderung mehr. Jetzt die Frage: Kann es sein das dadurch dass alle ADC Kanäle die gleiche Masse nutzen der Wert verfäscht wird und das ich dies durch Dioden verhindern kann? Wie gesagt wenn ich die Kanäle nicht ändere geht alles einwandfrei nur wenn sie geändert werden spinnt auf einmal alles. Ach ja bevor ich es vergesse: Selbst wenn nur an einem Kanal meine Spannung anliegt gibt er mir den richtigen Wert aus wenn ich nur diesen Messe, sobald ich jedoch mehrere (Kanal wächsele) Messen will spinnt wieder alles.
Daniel H. wrote: > Hi > > Hab mal wieder ein kleines Problem. > > Bin gerade dabei mit meinem Atmega32 4 ADC werte einzulesen das klappt > auch alles einwandfrei wenn ich immer nur 1 ADC benutze. Sobald ich aber > mehrere benutze und die Kanäle wechsele bekomme ich sehr merkwürdige > Werte. Es ist meist sinnvoll (auch wenn es nicht explizit im Datenblatt steht) nach dem Umschalten auf einen anderen Kanal eine kurze Wartezeit einzufügen (ein paar zig µs). Versuch das mal. > Hab im Anhang ein Teil meiner Platine (jedoch sind die Dioden im > moment nur brückendrähte. Es gibt in EAGLE die Möglichkeit, sogenannte Junctions an den Verbindungspunkten von Signalen zu platzieren, damit man sehen kann, dass an der Stelle tatsächlich eine Verbindung vorliegt und keine Kreuzung. Bei Dir ist überhaupt nicht erkennbar, wo da Verbindungen sind und wo nicht. Kleiner Tip: Ziehe die Signale im Schaltplan nicht mit Wire sondern mit Net. Dann werden die Junctions automatisch gemacht. > Wie im Toturial beschrieben nutze ich eine einfache variante, denn > Spannungsteiler. Wenn ich jedoch jetzt die Kanäle ändere ist auf allen > Kanälen +- 20 jeder wert gleich und eine änderung bring so gut wie keine > veränderung mehr. > > Jetzt die Frage: > > Kann es sein das dadurch dass alle ADC Kanäle die gleiche Masse nutzen > der Wert verfäscht wird und das ich dies durch Dioden verhindern kann? Nein, wenn die "Masse" die selbe Masse wie das AGND des Controllers ist, dann kann das eigentlich nicht sein und die Dioden werden da auch nichts bewirken. Aber auch das ist dem Schaltplanschnipsel nicht zu entnehmen...
Schonmal Danke für den Eagle Tip. Werde ich gleich mal Testen. Also Brauche ich die Dioden doch nicht. Warte Zeit hab ich schon ca 300 Ms da er die Werte über den selben lcd Ausgeben soll. Kann das ja nicht so schnell machen sonnst kann mann es ja nicht lesen.
Das ist echt ziemlich komisch. Wenn ich zum Beispiel 2 Messungen durchführe beide auf ADC 0 kein Prob alles geht oder 2 Messungen auf ADC 1 ebenfalls kein Prob. Sobald ich aber eine auf ADC 0 mache und die andere auf ADC 1 dann simmt nichts mehr. jemand nee Idee? Gruß Daniel
Daniel H. wrote: > Das ist echt ziemlich komisch. Wenn ich zum Beispiel 2 Messungen > durchführe beide auf ADC 0 kein Prob alles geht oder 2 Messungen auf ADC > 1 ebenfalls kein Prob. Sobald ich aber eine auf ADC 0 mache und die > andere auf ADC 1 dann simmt nichts mehr. > > jemand nee Idee? Wie sieht denn Deine Messung softwaremäßig aus? Könnte ja sein, dass da der Hase im Pfeffer liegt... ...
Die oben angesprochene Wartezeit (von ca. 120µs) MUSS zwischen Umschalten des MUX oder der Betriebsart (single-ended oder differentiell) eingehalten werden. Also erst MUX umschalten, dann die Displayausgabe, dann messen. Dann sollte es funktionieren.
Ok es gibt schon wieder neuigkeiten. Also wegen den Pausen hab da ein delay von 250ms drinne darann denke ich kann es nicht liegen. Code kann ich Posten ist aber schon ein Stücken (300 Zeilen). Ich Schalte jetzt nach jeder Messung den ADC ab und jetzt sieht man wenigstens einen deutlichen unterschied. Jedoch beeinflussen sich die beiden Messungen doch irgendwie. Wenn ich die Spannung an ADC0 verändere dann steigt ADC1 mitjedoch nicht gleich sondern nur im verhältnis. Alle Messschaltungen (Sensor + Teilerwiederstand) nutzen eine gemeinsame Masse und Spannungsversorgung wie in der Zeichnung dargestellt.
Du hast aber nicht immer nur einen Eingang beschaltet und alle Anderen Eingänge sind offen? Das würde einiges erklären ...
Im moment sind nur 2 mit Sensoren bestückt der Rest nicht die liegen brach was bedeutet das keine externen Sensoren dran hängen.
Daniel H. wrote: > Im moment sind nur 2 mit Sensoren bestückt der Rest nicht die liegen > brach was bedeutet das keine externen Sensoren dran hängen. Dann solltest Du die nicht benutzten Eingänge auf definiertes Potential (z.B. GND) legen. ...
@ Hannes Hab ich doch gemacht. Aber leider bringt das auch nichts. Wenn ich ein Sensor komplett weglasse geht es einwandfrei. Kennt jemand eine schaltung mit mehreren Sensoren aus dem Kopf die hier im Netz rumschwebt wo ich einfach mal nachgucken könnte?# MFG Daniel
Daniel H. wrote: > @ Hannes > > Hab ich doch gemacht. Aber leider bringt das auch nichts. Wenn ich ein > Sensor komplett weglasse geht es einwandfrei. Irgendwie verstehe ich nicht, wie Du das meinst. Was verstehst Du unter "weglassen"? Wenn ein Eingang abgefragt ist, sollte er auch beschaltet sein. Ansonsten wird Müll eingelesen. > > Kennt jemand eine schaltung mit mehreren Sensoren aus dem Kopf die hier > im Netz rumschwebt wo ich einfach mal nachgucken könnte?# Was für Sensoren?? Wenn Potis zwischen GND und AVCC auch (im weitesten Sinne) als sensoren akzeptiert werden, dann kenne ich eine Schaltung samt Software: http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html Bei der sind die eingelesenen ADC-Werte recht stabil, obwohl weder Oversampling noch Mittelwertberechnung angewendet wird. ...
Hallo, wenn gar nicht anders verwende nur einen AD-Kanal und einen externen Multiplexer, welchen du über Portpins ansteuerst.
Also als sensoren meine im moment PT100 oder Poti (ein veränderbaren Wiederstand). Mit weglassen ist gemeint: immer 2 Kontakte an x2, x3 ,x4 gehören zusammen. Versorgungsspannung wird über die Leiste rausgegeben durch z.B.PT100 durchgeleitet und dann an den ADC eingang weitergeleitet. Gleichzeitig wird mit jeweils einem Wiederstand ein Spannungsteiler aufgebaut um einen Spannungsteiler aufzubauen (PT100 + Wiederstand). Die Dioden auf meinem Bild werden ja nich benötigt und sind somit durch Brückendraht ersetzt worden und verbinden den Spannungsteiler somit an meine Masse.
Daniel H. wrote:
> Code kann ich Posten ist aber schon ein Stücken (300 Zeilen).
abspecken, abspecken.
Um 2 ADC abzufragen reichen 20 Zeilen ebenfalls.
Die LCD Routinen kannst du beim Posten weglassen,
wir glauben dir auch so, dass die funktionieren.
PT100 (mit Widerstand als Spannungsteiler) direkt am AVR-ADC-Eingang? Auf diese Idee wäre ich nie gekommen. Ich habe den PT100 zwar noch nicht benutzt, gehe aber davon aus, dass seine temperaturabhängige Widerstandsänderung zwar sehr linear, aber recht klein ist. Ich vermutete also, dass der Aufwand der Signalaufbereitung den Nutzen übersteigt. In einem Temperatur-Regler für einen alten E-Boiler nutze ich als Sensor einen Heißleiter, ist zwar nicht ganz linear, aber für den Zweck gut genug. Ist aber nur eine Mess-Stelle, auch kein Mega32 (ich mag nicht immer gleich mit Kanonen auf Spatzen schießen), sondern nur ein Mega48 mit LCD 2x16 und 4 Tasten. ...
Die übliche PT100-Anwendung wäre: Konstantstrom (1mA) über den Fühler und den Spannungsabfall über dem Sensor messen (Vierleitertechnik). Das (mV-) Messsignal verstärken und einen Offset abziehen (Bereich auf 0..5V anpassen), dann ist es vernünftig mit einem AVR zu messen. Die Linearisierung (falls nötig) ist mit µC auch kein Problem, z.B. mit Look-up-Tabelle.
Das ist ja nur ein Beispiel. Im moment betreibe ich 2 Potentiometer um veränderbare Wiederstande zu simulieren. Den Code Poste ich gleich mal in abgespeckter fassung. Ist ja nicht alles wichtig für den ADC
Code: void adc_init (void) { // ADC init ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); // ADC aktiviert, Prescaler auf 32, ADC Interrupt enabled ADMUX = (1<<MUX1) | (1<<MUX0); // ADC Channel 3 ADMUX |= (1<<REFS0); // AVCC als Referenzspannung nutzen ADCSRA |= (1<<ADSC); // erste Wandlung Starten zum justieren while ( ADCSRA & (1<<ADSC)); // Warten bis die Wandelung abgeschlossen ist int tata = ADCW; } int adc (int mux) { // ADC Wert auslesen adc_init(); int result=0; ADMUX |= mux; // Channel wählen for( int i=0; i<6; i++ ) { ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" while ( ADCSRA & (1<<ADSC) ) { ; // auf Abschluss der Konvertierung warten } result += ADCW; // Wandlungsergebnisse aufaddieren } result = result / 6; // Summe durch sechs teilen = arithm. Mittelwert ADCSRA = 0; return result; } void testmode (void) { // Test Mode zum testen der Signale int save = 0; sei(); // Global Interrupt enabled while(1) //Endlos schleife { lcd_clrscr(); lcd_gotoxy(0,0); lcd_puts("Wert 1:"); lcd_gotoxy(0,1); lcd_puts("Wert 2:"); save = adc(3); // Wert 1 holen lcd_gotoxy(11,0); lcd_puts(" "); lcd_gotoxy(11,0); itoa (save, buffer, 10); lcd_puts(buffer); pause (1000); save = adc(2); // Wert 2 holen lcd_gotoxy(11,1); lcd_puts(" "); lcd_gotoxy(11,1); itoa (save, buffer, 10); lcd_puts(buffer); pause (1000); } } void powerup (void) { // Start Sequenz lcd_init(LCD_DISP_ON); // Display Initalisierung DDRC = 0x00; // PORT C als Eingang deklariert PORTC = 0x00; // Pull up Wiederstand aus lcd_clrscr(); // LCD Komplett Löschen timer_init(); // Timer starten adc_init(); // ADC starten testmode(); } int main(void){ // Main powerup(); while(1) { } return 1; } So das ist er nun in abgespeckter Fassung. ICP fehlt und ein paar kleinigkeiten.
Hallo, vielleicht eine C-Übung für mich (mache sonst nur ASM)... int adc (int mux) { // ADC Wert auslesen adc_init(); int result=0; ADMUX |= mux; // Channel wählen 1. Aufruf mit mux = 1 (Kanal 1), also 0b00000001 2. Aufruf mit mux = 2 (Kanal 2), also 0b00000010 ADMUX ist also 1, ADMUX |= mux; sollte also 3 ergeben, vermutlich nicht das, was Du erwartest. Von ADMUX also erst alle MUX-Bits ausblenden, ADMUX = (ADMUX & 0xF0) | mux Muß mal bitte ein C-User in die richtige Syntax bringen. Gruß aus Berlin Michael
Du musst darauf achten dass du FRÜHESTENS 40µs nach der Umschaltung des MUX die Wandlung einleitest (nach ändern der Betriebsart single-ended <=> differentiell sogar 120µs). Diese Zeit braucht der Analogschalter (MUX) zum Durchschalten. Andernfalls wird es immer Hausnummern geben.
Hallo, das passt aber nicht sonderlich zum Datenblatt. MUXX und REFS werden bei Beginn der Wandlung übernommen, nur die Änderung von REFS versaut die erste Wandlung, die zweite ist schon ok. Klappt bei mir auch ganz praktisch so. Zumindest bei den gängigen ATMega 8/16/32. Gruß aus Berlin Michael
Das mit MUX steht gar nicht drin, ist aber so. Wenn du eine Dummy-Wandlung vorausschickst hast du nix anderes als 'ne Pause gemacht. ;-)
Michael U. wrote: > Von ADMUX also erst alle MUX-Bits ausblenden, > ADMUX = (ADMUX & 0xF0) | mux; > > Muß mal bitte ein C-User in die richtige Syntax bringen. Perfekt
Hier mal eine Version von mir, auch wenn durch den _delay-Befehl Zeit verplempert wird: ;-)
1 | double ADC_conversion(unsigned char mux, unsigned char MW) // Spannung messen (single ended) |
2 | {
|
3 | ADMUX = mux; // Multiplexer-Modus einstellen |
4 | delay_us(40); // Pause bis Multiplexer eingestellt ist |
5 | double Messwert = 0; |
6 | unsigned int ADC_temp; |
7 | unsigned char i = 1; |
8 | |
9 | do
|
10 | {
|
11 | ADCSRA |= (1<<ADSC); // 'single conversion' einleiten |
12 | while(!(ADCSRA & 0x10)); // auf ende der Wandlung warten, ADIF flag '1' |
13 | ADC_temp = ADCL; // ADCL Register lesen |
14 | ADC_temp += (ADCH << 8); // ADCH Register lesen |
15 | Messwert += ADC_temp; // Ergebnisse der Messungen addieren |
16 | i++; // Schleifenzähler erhöhen |
17 | }
|
18 | while (i <= MW); // MW Messungen für bessere Genauigkeit |
19 | Messwert = Messwert/MW; // Mittelwert der Messungen der double-Variable zuweisen |
20 | |
21 | return (Messwert); |
22 | }
|
Hallo, @Power: Atmel sagt, daß der MUX vor Beginn der Wandlung gesetzt werden soll. Frühestens 1 ADC-Takt nach Beginn der Wandlung kann der MUX bereits wieder umgeschaltet werden, übernommen wird die Einstellung mit dem nächsten Start einer Wandlung. Das ging bisher auch immer bei mir. Ein Dummy-Zyklus wird nur nach Ändern der Betriesart oder der Referenzspannung gefordert, unabhängig von Wartezeiten. Es heißt nur, daß das erste Wandlungsergebnis nach Änderung von AREF ungültig sein kann und man besser verwerfen soll. Bis jetzt haben meine AVR das Datenblatt offenbar auch gelesen. ;-))))) Gruß aus Berlin Michael
Michael U. wrote:
> Bis jetzt haben meine AVR das Datenblatt offenbar auch gelesen. ;-)))))
Meine auch, meist besser als ich...
8-)
...
OK hab mal wieder etwas Zeit gefunden um weiter zu machen. Michael U. du hast recht zusammen mit Karl Heinz Buchegger. Hat an der einen kleinen Zeile gelegen. Das einzigste was mir noch fehlt ist das mir einer mal kurz erklärt was eigentlich in der Zeile passiert: ADMUX = (ADMUX & 0xF0) | mux; Ich dachte immer wenn ich ADMUX |= mux eingebe dan ändert er nur die Bits dessen Wert mux hat? Gruß und nochmals Danke Daniel
> Ich dachte immer wenn ich ADMUX |= mux eingebe dan ändert er nur die > Bits dessen Wert mux hat? Richtig. Aber Du löschst nicht die vorher anders gesetzten Bits. Damit bleiben alle jemals gesetzten Bits gesetzt.
Hallo, > Ich dachte immer wenn ich ADMUX |= mux eingebe dan ändert er nur die > Bits dessen Wert mux hat? Einfach unpräzise ausgedrückt und sicher auch gedacht. ;) Es ist eine Oder-Verknüpfung, die Veränderung besteht also darin, das die Bits in MUX einzeln mit den Bits in ADMUX OR-Verknüpft werden. Das heißt aber ja letztlich: es sind hinterher alle Bits in ADMUX gesetzt, die vorher bereiits gesetzt waren ODER die in mux gesetzt sind. 0000 0001 ADMUX OR 0000 0010 mux ------------- 0000 0011 ADMUX hinterher... Gruß aus Berlin Michael
Super danke für die erklärung. Damit hab ich es jetzt verstanden und wünsche allen ein erholsames WE. Gruß Daniel
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.