Guten Morgen. Heute hab ich auf meiner Testplatine einen LM35 Temperatursensor angelötet. Halt den mittleren Vout Pin an meinen PA0 Pin, wo der ADC akiviert ist, dann eben den aüßersten an die GND und den linken aüßeren (wenn man auf die flache Seite des Sensors draufschaut) an die Vcc. Leider mess ich nur Nullen. Mit einem Multimeter hab ich nachgemessen ob der Sensor richtig verlötet wurde, und er kriegt aufjedenfall Strom. Gestern wo ich die Software fuer die ADC-Messung geschrieben hab, hab ich zwischen Masse und PA0 nur Nullen gemessen erwartungsgemäß, zwischen Vcc und PA0 nur 1'en, von daher geh ich mal davon aus dass die Software richtig ist. Hier sind trotzdem nochmal der Code angehangen. Kann es sein dass der Sensor beim Löten zerstört wurde?
Mikhail V. schrieb: > Leider mess ich nur Nullen. Mit einem Multimeter hab ich nachgemessen ob > der Sensor richtig verlötet wurde, und er kriegt aufjedenfall Strom. Was liefert der Sensorausgang, wenn er nicht am Controller angeschlossen ist, als Spannung ans Multimeter? Wenn da auch dauerhaft 0 ist, dann ist er falsch verbaut, wurde durch minutenlanges Löten gegrillt oder die Testplatine hat einen Kurzen.
Also, zwischen Masse und Sensorausgang mess ich zwischen 0,28-0.33V und zwischen Vcc und Sensorausgang sinds 4,62V So langsam nervt mich das bloede Teil.
Entschuldigung fuer den Doppelpost, hab nochmal was merkwuerdiges. Wenn ich in dem Codestuecken:
1 | adc_wert = adc_read(0); |
die 0 veraender, dann kommen im Hterm sehr merkwuerdige werte an. Allerdings nur wenn ich die 0 zu einer 4 oder höher mach. Grueße.
Mikhail V. schrieb: > Also, zwischen Masse und Sensorausgang mess ich zwischen 0,28-0.33V Entspricht ja 28-33°C. Wo ist grad so schönes Wetter? Der Sensor tut also was er soll.
Ilmenau, und bei mir im Labor sind es 22° (jha naja mit den ganzen abweichungen der messgeraete wird es schon hinkommen..) Der Sensor misst Mist. Mich wundert es aber trotzdem wieso er mir Hterm nur 0'en anzeigt. Ist vllt. das Programm falsch (vermutlich, da Programmieren zu meinen großen Schwaechen gehoert)? Hoechstwahrscheinlich liegt es an diesem Codeabschnitt (die einzige Schnittstelle zwischen der UART und ADC Routine)
1 | while(1) |
2 | { |
3 | adc_wert = adc_read(0); //kanal 0 gewaehlt |
4 | |
5 | if (overflowzahl==1) |
6 | { |
7 | USART_Transmit(adc_wert>>8); |
8 | USART_Transmit(adc_wert ); |
9 | USART_Transmit(0x0A); |
10 | |
11 | overflowzahl=0; |
12 | |
13 | |
14 | } |
15 | } |
da ich den code aus dem tutorial 1 zu 1 zwischenzeitlich uebernommen hab, habe ich trotzdem nur 0'en rausbekommen, und leider weiss ich gerade echt nicht wie ich das besser machen soll.
Kurze Frage dazu: siehst Du die Nullen nur auf Deinem Terminal oder auch mit dem Debugger? Kann es also ggf. auch an der seriellen Schnittstelle liegen und nicht am ADC?
Ich denke mal es liegt daran dass ich den Teil wo ich die ADC Werte an die UART uebergebe falsch programmiert hab. Wie meinst du das "die Nullen mit dem Debugger sehen?". Ich denke mal der ADC ist vollkommen in Ordnung, da ja auch mit dem Code aus dem Tutorial nur Nullen angezeigt wurden Muss also an der Uebergabe der ADC Werte an die UART liegen, halt an der Stelle, die ich ueber deinem Post gezeigt hab. Grueße
Besitzt Du einen Debugger, mit dem Du Dir Werte anschauen kannst. Dann wüßtest Du nämlich genau, wo der Fehler liegt und musst nicht mutmaßen.
Mikhail V. schrieb: > USART_Transmit(adc_wert>>8); > USART_Transmit(adc_wert ); > USART_Transmit(0x0A); Binär über die UART geht schief. Bastel Dir mit sprintf nen ordentlichen String und sende den. Peter
Den string zu senden funktioniert auch nicht. Das richtig bloede ist, dass wenn ich den Sensor mit meinen Fingern erwaerme, es zu keiner Veraenderung in den erhaltenen Daten kommt. (Wenn ich natuerlich dann messe von Masse nach Sensorausgang und dabei den Sensor erwaerme, seh ich auf den Voltmeter eine Veraenderung, naemlich wie erwartet eine Erhoehung der Spannung).
Mikhail V. schrieb: > Den string zu senden funktioniert auch nicht. > Das richtig bloede ist, dass wenn ich den Sensor mit meinen Fingern > erwaerme, es zu keiner Veraenderung in den erhaltenen Daten kommt. Auch nicht mit dem Multimeter? Wenn du dir bei der Software unsicher bist, dann kontrolliere immer erst ob das Signal vom Sensor ok ist. Wenn der nichts brauchbares liefert, dann wird das die Software nicht ausbügeln können.
A. K. schrieb: > Auch nicht mit dem Multimeter? Wenn du dir bei der Software unsicher > bist, dann kontrolliere immer erst ob das Signal vom Sensor ok ist. Wenn > der nichts brauchbares liefert, dann wird das die Software nicht > ausbügeln können. Naja auf dem Multimeter wird ja alles richtig angezeigt, der Sensor und die Hardware funktionieren, nur die Software bringt mich eben zu verzweifeln, habe alles schon versucht. Bin echt kein Informatiker/Programmierer.
So, habs nochmal alles ueberarbeitet und versucht strings zu senden mit der uart (halt ertmal die adc daten zum string zusammenbauen und dann mit puts senden). Hab wieder nur Mist erhalten und die Werte haben sich nicht veraendert wenn ich den Sensor erwaermt hab. Die Baudratenberechnungen, Quarz, Schaltung sind alle in Ordnung und richtig. Haette vllt. jemand ein Beispielcode wie die Uart ADC Daten an den Hterm sendet? Weil so langsam bin ich kurz davor den Rechner mitsamt Schaltung und Netzteil aus dem Fenster zu feuern. Grueße.
Mikhail V. schrieb: > So, habs nochmal alles ueberarbeitet und versucht strings zu senden mit > der uart (halt ertmal die adc daten zum string zusammenbauen und dann > mit puts senden). > Hab wieder nur Mist erhalten Schön langsam frag ich mich, ob deine UART überhaupt funktioniert. Kannst du einen Text senden und den am Terminal sehen puts( "Hallo\n" ); > Haette vllt. jemand ein Beispielcode wie die Uart ADC Daten an den Hterm > sendet? Weil so langsam bin ich kurz davor den Rechner mitsamt Schaltung > und Netzteil aus dem Fenster zu feuern.
1 | ...
|
2 | int main() |
3 | {
|
4 | uint16_t adc_wert; |
5 | char buffer[20]; |
6 | |
7 | ...
|
8 | |
9 | while(1) |
10 | {
|
11 | adc_wert = adc_read(0); |
12 | |
13 | sprintf( buffer, "ADC: %d\r\n", (int)adc_wert ); |
14 | |
15 | puts( buffer ); |
16 | }
|
17 | }
|
Guten Morgen Karl Heinz Buchegger schrieb: > Schön langsam frag ich mich, ob deine UART überhaupt funktioniert. > Kannst du einen Text senden und den am Terminal sehen > > puts( "Hallo\n" ); Ja natuerlich, deswegen habe ich ja das Programm geschrieben mit dem ich ueber die UART die LED ansteuern konnte, das hat mir auch dann den entsprechenden Text gesendet. Naja bei dem Code wuerde ich ja "ADC: 0 'komisches Zeichen'" auf den Schirm bekommen. Und nicht den Temperaturwert den ich die ganze Zeit suche. Grueße.
Mikhail V. schrieb: > > Naja bei dem Code wuerde ich ja "ADC: 0 'komisches Zeichen'" auf den > Schirm bekommen. Und nicht den Temperaturwert den ich die ganze Zeit > suche. Bei meinem Programm kriegst du den Wert so wie er vom ADC kommt auf den Bildschirm. Ich wüde dir raten damit erst mal anzufangen um zu sehen, welche Werte vom ADC kommen. (Und das komische Zeichen ist ein Zeilenvorschub. Wenn das Terminal richtig eingestellt ist, dann siehst du den nicht bzw. nur insofern, dass das Terminal eine neue Zeile anfängt) Wenn du dann siehst, dass sich die ADC Werte verändern, kannst du sie immer noch in eine Temperatur umrechnen. Aber erst mal die einfache Variante, dann die komplexere.
Und wenn du dir nicht sicher bist, ob der Sensor noch funktioniert, dann nimm ihn raus und löte erst mal ein Poti an. Mittlerer Potipin an den ADC Eingang. Die beiden äusseren an Vcc bzw. GND. Dann kannst du mit dem Poti eine Spannung zwischen 0 und VCC einstellen. (Ein 10k Poti ist ok. Aber auch jeder andere Wert zwischen 1k und 1M. Das ist nicht kritisch). Spätestens dann musst du an den Ausgaben sehen, wie sich der Wert verändert.
Ich bin mir sicher dass der Sensor funktioniert (heute frueh hab ich wieder den Sensor erstmal mit dem Multimeter ausgemessen). Das mit dem Zeichen hab ich jetzt auch am Terminal richtig eingestellt, wayr nur bisschen verwirrt so frueh am Morgen. Da der Sensor und die UART anscheinend richtig sind, liegt es wohl an der ADC Programmierung. Und das ist das frustrierende weil ich mich komplett an das Tutorial hier und streng an das Datenblatt des AtMega16 gehalten hab. Da ich also im Terminal nicht sehe wie sich die ADC Werte veraendern muss es daran liegen. Grueße.
Entschuldigung fuer den Doppelpost. ich hab mir mal den Spaß angetan und hab den Ausgang des Sensors an verschiedene Pins des ADC wandlers bei AtMega16 drangehangen. Nur am ersten Pin PA0 hatte ich die bloeden Nullen. An anderen Pins hat mir Terminal eine 1023 angezeigt. Nun, irgendwie kann ich mit diesem Messergebnis nichts anfangen. Grueße.
> Heute hab ich auf meiner Testplatine
Und die sieht wie aus?
AVcc ist angeschlossen?
ARef hat einen 100nF Kondensator gegen GND (und sonst nichts)?
Mikhail V. schrieb: > Nun, irgendwie kann ich mit diesem Messergebnis nichts anfangen. Du probierst relativ planlos einfach rum. Manchmal hat man dadurch Ideen, was man testen könnte. Aber oft führt das zu nichts.
Karl Heinz Buchegger schrieb: > Und die sieht wie aus? > > AVcc ist angeschlossen? > ARef hat einen 100nF Kondensator gegen GND (und sonst nichts)? Genau so sieht die aus. AVcc ist wie im Datenblatt beschrieben ueber eine Drossel mit Vcc verbunden und GND, Aref hat auch nur einen 100nF und sonst nichts gegen GND. Naja wenn man keine Ideen mehr hat was man machen koennte (und google.de bis jetzt auch zu keinem Erfolg gebracht hat) probiert man eben planlos rum.
So, hab jetzt die Zeile "adc_wert = adc_read(0); " aus der hauptloop rausgeschmissen und nur in die main gepackt. Und siehe an, der ausgelesene ADC Wert ist 831 (in ASCII), seltsamerweise erhoeht sich dieser trotzdem nicht wenn ich den Sensor mit meinen Fingern erwaerme. Grueße.
Sebastian Möller schrieb: > Ist der ADC Pin als Eingang deklariert? Sind die Pins bei AtMega16 nicht "per default" als Eingang deklariert? Aufjedenfall krieg ich da jetzt einen Wert, bloed ist nur dass sich dieser nicht veraendert bei Erwaermung.
So, hier nochmal die bis jetzt "finale" Code-Version, die allerdings auch nicht funktioniert. Immerhin mess ich jetzt eine unveraenderbare "767".
1 | #include <avr/io.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <avr/interrupt.h> |
5 | #include "uart_komplett.h" //meine uart |
6 | #include "timer1.h" //meine timer funktion, sorgt dafür dass die uart ausgabe nur alle 2 sekunden erfolgt (overflows halt) |
7 | |
8 | //Dinge definieren |
9 | #define LED_DDR DDRC //definieren der LED DDR |
10 | #define LED_PORT PORTC //defintion des genauen ports für die DDR |
11 | #define LED_PORTPIN1 PC1 //definition der roten LED |
12 | #define LED_PORTPIN0 PC0 //definition des gruenen LED |
13 | |
14 | //Variablen definieren |
15 | |
16 | uint16_t adc_wert = 0; //Wert des ADC |
17 | volatile uint8_t overflowzahl = 0; //zaehlt die overflows, wichtig für den timer und die uart ausgabe (zwei sekunden takt halt) |
18 | |
19 | //Funktionen definieren |
20 | void adc_init() |
21 | { |
22 | uint16_t result; //ergebnis variable festlegen, uint16 wegen 10 bit ergebnis |
23 | |
24 | ADMUX = (1<<REFS1)|(1<<REFS0); //die interne Referenzspannung nehmen |
25 | ADCSRA = (1<<ADPS1)|(1<<ADPS0); // Frequenzvorteiler bei 8 |
26 | ADCSRA |= (1<<ADEN); //ADEN "enabled" ADC |
27 | ADCSRA |=(1<<ADSC); //analog zu digital wandlung aktivieren |
28 | |
29 | |
30 | while (ADCSRA & (1<<ADSC)) // eine "sinnlos" Wandlung durchfuehren um den eventuellen Mist |
31 | { // aus dem Wandler rauszuschmeissen |
32 | |
33 | } |
34 | result = ADCW; // das ergebnis der wandlung steht in ADCL und ADCH (sind die Result Register) |
35 | //dabei wird immer von ADCL nach ADCH gelesen/ |
36 | //muss einmal gelesen werden, sonst wird das ergebnis der naechsten wandlung nicht gelesen |
37 | } |
38 | |
39 | //Einzelne ADC Messung und "Lesung" des Wertes |
40 | |
41 | uint16_t adc_read (uint8_t channel) |
42 | { |
43 | ADMUX = (ADMUX & 0b11000000) | (channel & 0b00111111); //kanal waehlen |
44 | |
45 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" |
46 | while (ADCSRA & (1<<ADSC) ) |
47 | { |
48 | } // s.o. |
49 | return ADCW; |
50 | } //geb mir das ergebnis, ADCW is das selbe wie result = ADCL, zusaetzlich zu result += (ADCH<<8) |
51 | |
52 | int main(void) |
53 | { |
54 | |
55 | LED_DDR |= (1<<LED_PORTPIN1)|(1<<LED_PORTPIN0); //PC1 und PC0 Pins als ausgang festlegen und einschalten |
56 | |
57 | |
58 | |
59 | LED_PORT = 0x01; //rote LED an |
60 | |
61 | DDRA = 0x00; //explizit den PortA als Eingang deklarieren |
62 | uint16_t adc_wert; |
63 | char buffer[20]; |
64 | |
65 | |
66 | usart_init(); |
67 | timer1_init(); |
68 | adc_init(0); |
69 | |
70 | sei(); //interrupts aktivieren |
71 | |
72 | adc_wert = adc_read(0); //zuweisung der Wert - Variable der "Auslese-Funktion" |
73 | |
74 | while(1) |
75 | { |
76 | |
77 | adc_wert = adc_read(0); //zuweisung der Wert - Variable der "Auslese-Funktion" |
78 | |
79 | if (overflowzahl==1) //UART Uasgabe nur wenn ein Overflow stattfinden |
80 | { |
81 | |
82 | sprintf ( buffer, "ADC: %d\r\n", (int)adc_wert ); //string rausgeben, hier leider nur "ADC: 0 "endzeichen"" |
83 | |
84 | uart_puts( buffer ); //puts fuer den string |
85 | |
86 | overflowzahl=0; //die zählung der overflows wieder auf 0 setzen, in der ISR fuer den Timer steht drin: "overflowzahl++;", damit die |
87 | // if-Bedienung dieser main-loop erfuellt wird |
88 | |
89 | |
90 | |
91 | } |
92 | |
93 | } |
94 | } |
Ich finde es absolut unbegreiflich, wie aus so einer Code-Wurstelei was vernünftiges rauskommen kann. Absolut grundlegend für selbst ein 10-Zeilen-Programm ist vernünftiges Einrücken. Davon abgesehen: Ist das dein komplettes Programm, oder fehlt da noch was? Wenn nicht, wieso enablest du die Interrupts ohne irgendeine Interruptroutine? Wenn ja, wäre es schon gut, alles zu posten, wenn du sagst, dass du alles postest. Wieso so kompliziert mit der (fehlenden) Timer-Routine? Um erstmal Funktionalität zu erreichen, lass den ADC doch einfach so schnell rennen, wie er kann. Jeder ADC-Wert wird dann über den UART ausgegeben. Also den ganzen "overflowzahl" Quatsch erstmal raus oder mindestens auskommentieren - genauso wie die Timer-Routine und die Interrupts.
MoritzS schrieb: > Ich finde es absolut unbegreiflich, wie aus so einer Code-Wurstelei was > vernünftiges rauskommen kann. Absolut grundlegend für selbst ein > 10-Zeilen-Programm ist vernünftiges Einrücken. Akzeptiert, sieht schlecht aus. > Davon abgesehen: Ist das dein komplettes Programm, oder fehlt da noch > was? Wenn nicht, wieso enablest du die Interrupts ohne irgendeine > Interruptroutine? > Wenn ja, wäre es schon gut, alles zu posten, wenn du sagst, dass du > alles postest. Wozu die Interrupts sind und die Variable "overflowzahl" steht in den Kommentaren. > Wieso so kompliziert mit der (fehlenden) Timer-Routine? Um erstmal > Funktionalität zu erreichen, lass den ADC doch einfach so schnell > rennen, wie er kann. Jeder ADC-Wert wird dann über den UART ausgegeben. > Also den ganzen "overflowzahl" Quatsch erstmal raus oder mindestens > auskommentieren - genauso wie die Timer-Routine und die Interrupts. Die Timerroutine fehlt nicht. Zweitenes: lass ich den so schnell laufen wie er kann, dann gibt der ADC immer noch diese Drecks 767. Die ISR macht das was sie soll und das gut, ich kann zumindest vernuenftig verfolgen was der ADC mir da ausgibt.
Ich habe jetzt nur das ADC Beispiel aus dem GCC - Tutorial auf meinen µC draufgespielt. Trotzdem sendet er mir eine 767 statt irgendwas zwischen 90 und 100. Grüße.
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.