Hallo, Ich hab einen DS18B20 (als Fühler im Edelstahlgehäuse) mit einem Atmega 16 mit C programmiert und das Ergebnis auf einem LC-Display 2X16 Zeilen ausgeben. Der Sensor wird extern Versorgt(kein Parasit-Modus). An den Pull Up 4,7k hab ich auch gedacht. Laut Oszilloskop werden sowohl die Function- wie auch die Rom-Commands in der Zeittoleranz des Sensors übertragen. Der Sensor schickt jedoch garnichts zurück. Selbst der 64 Bit Erkennungscode des Sensors wird nicht übertragen. Das Programm ist sehr einfach gehalten, könnte das ein Problem sein? Am gesamten PortA ist nur der Sensor angeschlossen, deswegen wird der Port komplett Low gesetzt. Die Ausgabe des Displays funktioniert soweit mit Test HEX-Werten. Die Hex-Werte rechne ich mit dem Befehl itoa() in dezimal um. Ist Mein Programm korrekt? Ist der Sensor vielleicht defekt? Kann mir jemand Tipps, Lösungen geben?
Guten abend, Hab vor ein paar tagen auch meinen ersten ds1820 (jedoch 18s20) an einem atmega8 in betrieb genommen. Anfangs hatte allerdings die selben schwierigkeiten jedoch lag es nur an verbindungsproblemen zum sensor und an der pin einstellung. Jetzt läuft alles problemlos. Hast du die funktionen selbst nach datenblatt gesxhrieben oder aus einer bestehenden lib? Wenn ja, welche?
Megamax schrieb: > Das Programm ist sehr einfach gehalten, könnte das ein Problem sein? Am > gesamten PortA ist nur der Sensor angeschlossen, deswegen wird der Port > komplett Low gesetzt. > Die Ausgabe des Displays funktioniert soweit mit Test HEX-Werten. Die > Hex-Werte rechne ich mit dem Befehl itoa() in dezimal um. Den Code selber geschrieben?
Ja der Code ist selbst geschrieben. Julian kannst du deinen Code bitte Online stellen, damit ich den Sensor testen kann? Ich hab auch einen ds18s20 und einen atmega 8 hier.
julian schrieb: > Anfangs hatte allerdings die selben schwierigkeiten jedoch lag es nur an > verbindungsproblemen zum sensor und an der pin einstellung. Jetzt läuft > alles problemlos. Erstmal Danke für den Hinweis, der Sensor ist an PA2 angeschlossen und die Datenleitung über 4,7kOhm auf +5V angeschlossen. Ich habe die Zeiten beim Ein- und Auslesen des Sensors jetz schon mehrmals geändert und anderen Beiträgen zu dem Sensor angepasst. Alles ohne Erfolg. Die aktuellste Version meines Programms ist im Anhang.
China Fake-Sensor erwischt? btw: for (i=0; i<11; i++) //200ms * 10 = 2000ms --> das sind 11 Durchläufe #define F_CPU 1000000L --> gehört ins Makefile void init_sequnez() --> init_sequence() Sensor ist auch gemäß Datenblatt angeschlossen?
:
Bearbeitet durch User
Danke du hast recht die Schleife war zu lang. Pete K. schrieb: > China Fake-Sensor erwischt? Ich hab mitlerweile 3 DS18B20 hier, hoffentlich sind alle 3 keine Fake China Ware. Wo finde ich Produkte von seriösen Händler? Pete K. schrieb: > #define F_CPU 1000000L --> gehört ins Makefile Makefile? Wie finde ich die? Pete K. schrieb: > void init_sequnez() --> init_sequence() Wenn ich das ändere bekomme ich folgende Warnings: Warning 4 control reaches end of non-void function [-Wreturn-type] Warning 1 data definition has no type or storage class [enabled by default] Warning 3 return type defaults to 'int' [enabled by default] Warning 2 type defaults to 'int' in declaration of 'init_sequnez' Pete K. schrieb: > Sensor ist auch gemäß Datenblatt angeschlossen? VDD an +5V, GND an GND und DQ an PA2 vom atmega16
Ich habe jetzt sowohl einen ds18b20 wie auch einen ds18s20 bei Reichelt bestellt. Bei meinen anderen Sensoren zeigt der Sensor jetzt nur noch 0xFF an. Vielleicht ein Timing Problem? Außerdem schicke ich bei den Commands und Functions das LSB zuerst, ist das korrekt? Anbei das geänderte Programm
:
Bearbeitet durch User
Maximilian S. schrieb: > Bei meinen anderen Sensoren zeigt der Sensor jetzt nur noch 0xFF an. > Vielleicht ein Timing Problem? Dann prüft man das, indem man eine Schleife macht. und das Einschalten einer LED in die Schleife mit einschließt. Dann sieht man schon, ob die im sec-Rhythmus geschaltet wird. Maximilian S. schrieb: > Ich habe jetzt sowohl einen ds18b20 wie auch einen ds18s20 bei Reichelt > bestellt. Bei diesen Fehlermeldungen braucht man keine Ersatz-DS zu bestellen. Erst mal die Fehler in der Software beheben. Maximilian S. schrieb: > Ich habe jetzt sowohl einen ds18b20 wie auch einen ds18s20 bei Reichelt > bestellt. Auch fakes funktionieren fast immer. Ihre Datenblattwerte (Genauigkeit, Betriebsspannungsbereich, Stromverbrauch usw. ) dürften halt nicht immer eingehalten sein. Das eher tückische bei fakes ist, dass sie unter Extrembedingungen ihren Geist aufgeben und im Normalbetrieb scheinbar richtig arbeiten. Das timing beim DS18x20 ist halt diffizil. Da kommt es auf jede Flanke auf diesem Ein-Draht-Signal an. Ich selbst hab es erst nach einiger Zeit, mit Scope-Unterstützung, hinbekommen. Und zwar erstmal NUR den DS18x20 zusammen mit einer Ergebnisanzeige (Inhalt r3,r2 per I2C ausgeben) Erst diese fertige Funktion wurde dann ins eigentliche Projekt übernommen.
:
Bearbeitet durch User
Peter R. schrieb: > Dann prüft man das, indem man eine Schleife macht. und das Einschalten > einer LED in die Schleife mit einschließt. Dann sieht man schon, ob die > im sec-Rhythmus geschaltet wird. Laut Oszilloskop stimmen die Zeiten der Signale 480us reset-Impuls, kurzes Pull-up, dann bekomme ich einen presence-Impulse von ca 110us und warte dann noch 300us. Danach werden die "0" Sequenzen mit 60us Low, dann 40us High und die "1" Sequenzen mit 8us Low und 92us High übertragen.
Das timing ist ziemlich straff und deinen code habe ich auch nicht angesehen. Wenn du ein scope hast, dann generiere erst mal einen exakten Resetimpuls und schau ob der DS18xx antwortet. Ist das der Fall kannst du darau aufbauen. Alle Befehle beginnen mit Reset. Das timing ist ja im Gesangbuch des DS18xx beschrieben. Ich habe es so gemacht, das ich erst mal die einzelnen Routinen zusammen gestellt und geteste habe.
Wie gesagt den presence Impuls bekomme ich vom Sensor. Hier der Teil indem der Reset- und Presence-Impuls initialisiert wird. void init_sequnez() { DDRA=0xFF; // PortA als Ausgang PORTA=0x00; //Pull low _delay_us(480); DDRA=0x00; // PortA als Eingang _delay_us(480); }
1 | init_sequnez(); //initalisierungs sequenz |
2 | write(skiprom); //aktiviere slave |
3 | write(convertt); //temperatur umwandlung |
4 | for (i=0; i<4; i++) //190ms * 4 = 760ms |
5 | {
|
6 | _delay_ms(190); //ms delay schleife geht höchsten bis 262ms => 262 ms/F_CPU MHZ |
7 | }
|
8 | init_sequnez(); |
9 | write(skiprom); |
10 | write(wscratchpad); //slave beschreibt speicher |
write Scratchpad? Das hat hier nichts verlren. Mit write scratchpad kann dein Programm Werte an den DS1820 übergeben. Warum probierst du denn nicht einfach mal eine andere, nachweislich funktionierende Lib aus? Ja ich weiss, du willst selber schreiben. Aber man kann auch einiges lernen, wenn man funktionierenden Code analysiert, wie die das machen.
Ah ok Danke, es funktioniert aber ohne write scratchpad auch nicht. Welche Lib ist den zu empfehlen?
Maximilian S. schrieb: > Ah ok Danke, es funktioniert aber ohne write scratchpad auch nicht. > Welche Lib ist den zu empfehlen? Ursprünglich wollte ich dir die PeDa Version aus der Codeammlung nahelegen. Aber ein Blick ins Zip-File im ersten POsting zeigt, dass PeDa da wieder mal in die vollen gegenangen ist. Sein Code kann auch mit mehreren DS1820 am Bus umgehen. Kurzes Goggeln brachte als einen der ersten Treffer die hier http://sicklinger.com/microcontroller-avr/58-atmel-avr-atmega-ds18x20-library-in-c.html Der zugehörige Code http://sicklinger.com/downloads/func-startdown/4 sieht mir auf die Schnelle nicht so schlecht aus. (PS: Und mach dir Hilfsfunktionen für deine LCD Ansteurung. So etwas
1 | ...
|
2 | schreibe('T'); |
3 | schreibe(':'); |
4 | schreibe(' '); |
5 | ...
|
ist doch grober Unfug. Einen String an ein LCD auszugeben braucht praktisch jedes Programm. Daher schreibt man sich eine Funktion, die das kann
1 | void lcd_string( const char* str ) |
2 | {
|
3 | while( *str ) |
4 | schreibe( *str++ ); |
5 | }
|
und benutzt die dann:
1 | ...
|
2 | lcd_string( "T: " ); |
3 | ...
|
aufbauend auf der String Funktion ist die nächste dann eine Funktion, die einen int ausgeben kann
1 | void lcd_int( int value ) |
2 | {
|
3 | char txt[8]; |
4 | itoa( value, txt, 10 ); |
5 | lcd_string( txt ); |
6 | }
|
Auf die Art entstehen dann erst mal ein paar Hilfsfunktionen, die einem bei der eigentlichen Arbeit das Leben viel leichter machen)+ )
Danke für die vielen Hinweise jetzt kann es weiter gehen! Ich melde mich wenn alles getestet ist.
Sowas
1 | if (temp_lsb<0x0A) // kleiner 10 |
ist doch Quatsch. Wenn dir nicht klar ist, dass 0x0A dasselbe wie dezimal Zehn (nur in einem anderen Zahlensystem) ist, dann ist das kein Beinbruch. Die Frage ist: warum verwendest du an dieser Stelle dann Hex? Schreib das doch gleich in Dezimal
1 | if (temp_lsb < 10) |
und gut ists. Welches Zahlensystem du benutzt um Konstanten hinzuschreiben, richtet sich nach dem was du in dieser Zeile vermitteln willst und was am natürlichsten ist! Dem Compiler ist das egal, denn sowohl 0x0A als auch 10 münden im selben Bitmuster. Das eine ist durch das andere austauschbar!
1 | c = 0x61; |
2 | c = 97; |
3 | c = 'a'; |
4 | c = 0b01100001; |
ist alles dasselbe! Die Variable c wird mit dem Bitmuster 01100001 geladen. Lediglich die Art und Weise, wie du dieses Bitmuster in deinem Programm ausdrückst unterscheidet sich, aber es ist immer dieselbe Operation mit demselben Ergebnis. Je nachdem in welchem 'Umfeld' man diese Zuweisung einsetzt, wird man sich für eine der möglichen Darstellungen des Wertes entscheiden. Man nimmt die, die in diesem Umfeld die naheliegenste ist. Du willst, dass dein Programm bei 24 Grad etwas macht, zum Beispiel die Heizung abschaltet. Für dich bedeutet an dieser Stelle der Zahlenwert 24 etwas. Wie diese Zahl aufgebaut ist, welche Bits auf 1 sind und welche auf 0, das ist dir völlig gleichgültig. Wichtig ist, dass es 24 Grad sind. Dann schreib das auch so!
1 | if( temperatur > 24 ) |
2 | Heizung_aus(); |
Hier macht weder eine Angabe in Hex noch eine Angabe in Binär irgendeinen Sinn. Und auch das Zeichen, dessen ASCII Code 24 wäre, interessiert dich nicht. Daher nimmst du keine dieser Möglichkeiten sondern schreibst die 24 so wie sie sind einfach hin. )
:
Bearbeitet durch User
Der Teil ist für die Ausgabe des Buffers, welcher mit der itoa()-Funktion beschrieben wird.
Maximilian S. schrieb: > Der Teil ist für die Ausgabe des Buffers, welcher mit der > itoa()-Funktion beschrieben wird. Ist mir schon klar. Und im Endeffekt wird das auch wegfallen, denn im Grunde braucht das keiner, wenn du eine String-Ausgabefunktion hast. Mir geht es an dieser Stelle mehr darum, dass du etwas dabei lernst: Das verwendete Zahlensystem ist nicht in Stein gemeisselt sondern es wird situationsbezogen das "Zahlensystem" ausgewählt, welches der Aufgabenstellung an dieser Stelle im Code angemessen ist.
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.