Hallo zusammen,
ich habe ein Problem bei einer ADC-Messung. Ich benutzte das
Entwicklungsboard AL-ERAM128_CAN, mit dem Controller AT90CAN128. Der ADC
Eingang ist wie auch im Tutorial beschrieben über eine Spannungsteiler
beschaltet.
Temperaturmessung erfolgt über einen KTY81-210.
Am ADC Eingang messe ich bei Raumtemperatur ca. 2,15V, ich nutze die
interne Referenzspg.
Beim debuggen des Programms bleibe ich immer in der Loop-Schleife hängen
weil das ADSC Bit nicht mehr auf 0 gesetzt wird also die Wandlung nicht
beendet wird.
Hier mal mein Code:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<stdio.h>
4
5
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
egal in welcher Reihenfolge ich die Register initialisiere, ich bleib
immer wieder bei der Loop schleife stehen.
ich weiss nicht mehr wo ich noch ansetzen kann, die Initialisierung
denke ich, ist soweit korrekt und die Funktionen für die messungen auch.
ich habe zum test alles andere was nicht zur adc-wandlung gehört aus dem
code rausgenommen, um andere fehler auszuschließen.
Florian schrieb:> Beim debuggen des Programms bleibe ich immer in der Loop-Schleife hängen> weil das ADSC Bit nicht mehr auf 0 gesetzt wird also die Wandlung nicht> beendet wird.
Welches AVR Studio ?
Ich glaube ADC und TWI kannst du nicht im Simulator abarbeiten.
Programmiere dein Chip, es wird schon gehen.
holger schrieb:> Mach das mal so rum>> ADCSRA |= (1<<ADEN); // ADC aktivieren> ADCSRA |= (1<<ADSC); // eine ADC-Wandlung "single conversion"
Wäre auch mein erster Gedanke gewesen, aber das Schlimme ist: Es
funktioniert sogar auch in umgekehrter Reihenfolge in diesem Code...
Begründung: Beim ersten Warmlaufen lassen des ADC wird noch keine
Messung gestartet sondern nur der ADC auf Enable gesetzt. Da er nie
ausgeschaltet wird läuft es ab da...
Ich würde sogar einen Schritt weiter gehen und die letzte Zeile der
"adc_init":
> ADCSRA &= ~(1<<ADEN); // ADC wieder deaktivieren
durch
ADCSRA |= (1<<ADEN); // ADC aktivieren
ersetzen.
Da die erste Wandlung direkt auf die Initialisierung folgt, sehe ich
keinen Vorteil, den nochmal kurz auszuschalten und dann gleich wieder
ein. Dannach wird er ja eh nichtmehr ausgeschaltet...
Dann fällt auch die Zeile:
> ADCSRA |= (1<<ADEN); // ADC aktivieren
komplett aus der "adc_read" raus.
Marc Vesely schrieb:> Florian schrieb:>> Beim debuggen des Programms bleibe ich immer in der Loop-Schleife hängen>> weil das ADSC Bit nicht mehr auf 0 gesetzt wird also die Wandlung nicht>> beendet wird.>> Welches AVR Studio ?> Ich glaube ADC und TWI kannst du nicht im Simulator abarbeiten.> Programmiere dein Chip, es wird schon gehen.
Würde ich auch sagen.
Hab das eben mal schnell in Atmel Studio 6.2 geworfen und auf ein
ATMega2560 (achja das liebe ArduinoMega 2560rev3...)gespielt.
Resultat:
Das Programm läuft wie es soll und A/D-wandelt fleißig. Ob es richtige
Werte aufnimmt kann ich aber nicht sagen... Hab jetzt nichts an den ADC
gehangen.
Bernhard F. schrieb:> Würde ich auch sagen.> Hab das eben mal schnell in Atmel Studio 6.2 geworfen und auf ein> ATMega2560 (achja das liebe ArduinoMega 2560rev3...)gespielt.
Irgendwie ist "ältere Version" aus dem Beitrag rausgefallen.
Ich habe 6.2 deinstalliert, weil der unbedingt ins VS2010 wollte,
fahre wieder Version 4.
Und gegen ArduinoMega hab ich gar nichts...
ich benutze das avr-studio4 v.4.19
ich werde jetzt mal meine lcd Routinen dazu nehmen und lasse mir den adc
wert mal auf dem lcd ausgeben, dann sehe ich ja ob es funktioniert oder
nicht.
Hallo zusammen, ich habe nun mal wieder etwas Zeit gehabt und weiter
gemacht. Funktioniert soweit alles super, ich Messe sie Temperatur und
das sogar ziemlich genau.
Jetzt mein Problem, beim adc wert auslesen "adc1 = adc_read_avg(0_64)"
ist es nicht möglich die ganze Rechnung anzuhängen.
Mache ich eine extra Rechnung und speichere das Ergebnis in eine
variable, bleibt diese ja immer gleich. Wie kann ich die Rechnung
ständig wiederholen, sodass immer der aktuelle adc wert benutzt wird?
Danke für eure Hilfe
florian schrieb:> Mache ich eine extra Rechnung und speichere das Ergebnis in eine> variable, bleibt diese ja immer gleich. Wie kann ich die Rechnung> ständig wiederholen, sodass immer der aktuelle adc wert benutzt wird?
Deine Fragestellung ist unklar.
Denn bei
wird ja genau die Sequenz ADC_einlesen -> Temperatur_errechnen ->
Temperatur_ausgeben immer wieder aufs neue wiederholt und führt
natürlich dazu, dass
* bei jedem Durchlauf der dann vorliegende ADC Wert ermittelt
* daraus die damit verbundene Temperatur errechnet
* und die auch ausgegeben wird
Ok, mein Fehler. Die Rechnung funktioniert und wird ständig mit
aktualisieren der ADC-Messwerte ausgeführt. Ich denke ich komme einfach
nicht mit den Datentypen und der LCD-Ausgabe klar.
Ich gebe die Daten ans LCD mit dieser Funktion aus:
florian schrieb:> Ich denke ich komme einfach> nicht mit den Datentypen und der LCD-Ausgabe klar.
du musst dich daran gewöhnen, genau zu beobachten und zu beschreiben,
was du siehst.
Ich denke mal, was dich momentan verblüfft, dass ist das die Ausgaben
manchmal 'seltsame' Zahlen ergeben. Kühlst du den KTY ab, dann hast du
zb plötzlich 90 auf der Ausgabe stehen.
Das liegt daran, dass die Funktion lcd_print_itoa nur genau das ausgibt,
was sich aus der Zahl ergibt. Errechnest du zb 10 Grad, dann schreibt
die Funktion auch 10 hin. Errechnet sie aber nur 9 Grad, dann wird auch
nur 9 hingeschrieben. Das führt dann dazu, dass die Ausgabe des Textes
"9" nur genau den Text auf dem LCD überschreibt, der seiner Länge
entspricht. Steht auf dem LCD vorher "10"
1
+----------------------------+
2
|10 |
3
| |
4
+----------------------------+
dann wird durch die Ausgabe des Textes "9" da nur 1 Zeichen neu
geschrieben. Denn länger ist der Text ja nicht. D.h. aber der 0-er von
"10" wird nie überschrieben und bleibt stehen. Obwohl der Text für "9"
korrekt ausgegeben wird, sieht dein LCD danach so aus
1
+----------------------------+
2
|90 |
3
| |
4
+----------------------------+
Die 9 stehen korrekt dort, aber der 0-er von vorher steht auch noch dort
und ganz automatisch liest du daher 90 (neunzig).
-> du musst dafür sorgen, dass auch alle Textposition überschrieben
werden!
Im besten Fall geschieht das dadurch, dass du zb vor einer Zahl
entsprechend viele Leerzeichen ausgibst, die dafür sorgen, dass die
'Zahl' eine immer gleiche Textlänge hat. Das hat dann auch den Vorteil,
dass dir auf dem LCD der Text nicht ständig hin und her wandert, sondern
die Einerstelle immer an derselben Position stehen bleibt, was das
Ablesen deutlich erleichtert.
Im einfachsten Fall (wenn auch nicht der speichersparendste oder
schnellste) benutzt du die Funktion sprintf, mit der man Ausgaben
wunderbar formatieren kann. Zum Beispiel auf immer gleiche Feldbreite
(=Textlänge bei Zahlen)
1
...
2
while(1){
3
ADCausgabe1=(adc_read_avg(0,64));
4
aktspg=(GRADausgabe1*5000);
5
deltaspg=aktspg/1024;
6
temp1=(deltaspg-2731);
7
8
sprintf(buffer,"%4u Grad",temp1);
9
lcd_set_cursor(0,2);
10
lcd_string(buffer);
11
}
Wenn das nicht dein Problem ist, dann beschreibe dein Problem besser!
Karl Heinz schrieb:> Wenn das nicht dein Problem ist, dann beschreibe dein Problem besser!
PS: Temperaturen als unsigned?
Du warst offenbar noch nie in Österreich. Da ist es ganz normal, dass es
im Winter auch mal Temperaturen unter 0 Grad Celsius hat. Etwas mehr
über Datentypen nachdenken und was sinnvoll ist. Für Temperaturen wird
wohl unsigned nicht so prickelnd sein.
Bei meiner Anwendung wird es zu keinen negativen Temperaturen kommen
deshalb ohne Vorzeichen 8-)
Mein Problem nochmal, angenommen mein adc wert ist 610, berechne ich in
meinen Programm (((610*5000)/1024)-2731)=247,515625
uint16_t ADCausgabe1;
uint32_t aktspg;
uint32_t deltaspg;
uint16_t temp1;
ADCausgabe1 = (adc_read_avg( 0,64));
aktspg=(ADCausgabe1*5000);
deltaspg=aktspg/1024;
temp1=(deltaspg-2731);
lcd_set_cursor(0,2);
lcd_print_itoa(temp1);
Abgesehen davon dass ich jetzt eine KommaZahl in einen integer schreibe,
sollte doch wenigstens 247 ausgegeben werden. Ich bekomme aber -2697