Forum: Compiler & IDEs LM 35 misst nur Nullen


von M. V. (bmtil)


Angehängte Dateien:

Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

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?

von M. V. (bmtil)


Lesenswert?

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

von Markus (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von M. V. (bmtil)


Lesenswert?

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).

von (prx) A. K. (prx)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
}

von M. V. (bmtil)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> Heute hab ich auf meiner Testplatine

Und die sieht wie aus?

AVcc ist angeschlossen?
ARef hat einen 100nF Kondensator gegen GND (und sonst nichts)?

von Karl H. (kbuchegg)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von Sebastian M. (compressed)


Lesenswert?

Ist der ADC Pin als Eingang deklariert?

von M. V. (bmtil)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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
 }

von MoritzS (Gast)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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.

von M. V. (bmtil)


Lesenswert?

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
Noch kein Account? Hier anmelden.