Hallo zusammen,
ich verwende eine DS18B20 Lib von Stefan Sicklinger Link:
http://www.sicklinger.com/en/atmel-avr-atmega-ds18x20-library-in-c.html
Ich bin quasi blutiger Anfänger und bin zu blöd den Temperaturwert an
mein Display zu übergeben. Mein genaues Problem habe ich unten im Code
kommentiert.
Bitte Helft mir.
hier mein Main:
temp_po=ds1820_read_temp(DS1820_pin_po);//Get temperature from DS1820 Lufttemp
46
47
sprintf(temp_po_str,"%.0f",temp_po);//Convert temp. Lufttemp to string
48
49
unsignedchari;
50
unsignedchara;
51
52
53
charmsg[]="Hallo";
54
55
//Anstatt Hallo, wollte ich den Temperatur Wert Temp_po_str an das Char //Array msg übergeben.
56
57
//Nur leider bekomme ich nur ein völliges Wirwar angezeigt. Ich möchte die //Temperaturwerte auf einre Nachkommastelle und mit Vorleichen angezeigt //bekommen. Aber ohne das eigentliche Komma. z.B. +12,7°C = +127 oder //-6,9°C = -69
58
59
//Pins und Ports habe ich geändert und das Signal ist gut messbar auf der //Datenleitung.
60
61
//Verwende DS18B20 und Atmega16 bei 16 MHz
62
63
64
i2c_init();
65
if(i2c_start(SLAVE_ADDRESS2|I2C_WRITE)!=0)
66
{
67
DDRB|=(1<<0);// falls Addresse 0 dann LED an PORTB.0 an.
Basti schrieb:> Hardware?? 10k pullup ??
Also wie gesagt: Das Signal ist gut messbar und ich verwende 4,7k Pullup
an PA1 des Atmega16. Sensor ist ein DS18B20 Temparatursensor.
Ich bräuchte ledeglich jemand der sich mit der Umwandlung von Datentypen
auskennt.
char msg []= "Hallo";
Anstatt Hallo (Funktioniert), wollte ich den Temperatur Wert Temp_po_str
an das Char
Array msg übergeben.
Nur leider bekomme ich nur ein völliges Wirwar angezeigt.
Ich weiß nicht welche Art von Daten der String beinhaltet.
Ich möchte die Temperaturwerte auf einre Nachkommastelle und
mit Vorleichen angezeigt bekommen.
Aber ohne das eigentliche Komma. z.B. +12,7°C = +127 oder
-6,9°C = -69
Hi
dein Problem ist nicht AVR oder DS18B20-Spezifisch sondern ein
generelles C-Problem. Ich würde dir daher empfehlen, das was du tun
willst, außerhlb des AVR mit einem normalen C-Compiler zu testen.
In C sind Strings Null-Terminiert. Hast du also ein Array-of-Char das so
ausschaut:
[H, a, l, l, o, \0, x, y, z]
wird dir strlen den Wert 5 zurückgeben, denn der String endet am
Null-Byte.
Wenn du ein array-of-char mit fester Größe allozierst (in deinem Code
z.B. temp_po_str[8]), musst du darauf achten, dass maximal 7 Zeichen
darin gespeichert werden und das 8. ein Null-Byte ist. dein sprintf-Call
kann aber durchaus länger werden und dann über die Grenzen des Arrays
hinaus schreiben.
Verwende daher lieber snprintf, gib die Länge als -1 deines
array-of-char an und schreibe manuell an das ende des strings ein
null-byte.
So viel zur Theorie.
In deinem Code ist temp_po_str ja bereits ein Array-of-char, also ein
String. Du kannst es anstatt msg verwenden.
Lg, Peter
Hallo leluno,
vielen Dank für deine Unterstützung! Könntest du deinen Code etwas
kommentieren, damit ich es besser verstehen kann? Das wäre toll!
Hallo Peter,
ich habe jetzt temp_po_str direkt für msg verwendet.
temp_po_str erzeuge ich jetzt so:
snprintf(temp_po_str, sizeof(temp_po_str-1), "\0", temp_po);
aber da scheint noch ein Fehler versteck zu sein.
"Hallo" ist ja ein Char String oder?
bei:
char msg []= "Hallo";
oder auch
char msg []= "123456789";
wird ja keine länge vorgegeben...
mein Display hat vier Stellen und wenn der String länger als 4 Zeichen
ist, wird msg unten im Code immer um "eins" erhöht und so als
laufschrift dargestellt.
Vielen Dank schon mal!
Übergibst Du 'temp_po_str' direkt an Deine Ausgabefunktion, oder willst
Du 'temp_po_str' erst in 'msg' kopieren und dann 'msg' mit Deiner
Ausgabefunktion ausgeben?
Du würdest uns einen gewaltigen Gefallen tun, wenn:
a. der Code anständig formatiert waere
b. die Variablen bezeichner haetten, die sich selbst erklären würden
c. du auf "Magische Nummern" verzichten würdest, z.B.
if (++i > strlen(msg) - 4) i = 0;
versteht kein Schwein.
Nimms mir nicht übel, aber in so einer Wüste helf ich niemanden
Freiwillig.
@ Roland: die zweite Variante wäre mir lieber.
@ Praktikant:
Ich habe jetzt mal das hier geschrieben aber es seint aucht nicht zu
funktionieren :-(
temp_po = ds1820_read_temp(DS1820_pin_po);
int buf[10];
char msg(3,13,dtostrf(temp_po,3,1,buf));
was mache ich falsch?
Vielleicht hast du auch den falschen Sensor oder die falsch lib zu
diesem Sensor.
Hatte mal DS18*B*20 bestellt (dachte ich zumindest) und dann habe ich
den DS18*S*20 bekommen. Kam auch nur Mist raus, weil für den S musste
noch was umgerechnet werden.
Vielleicht hilft das weiter?
@ F. Fo:
Daran habe ich auch schon gedacht und deshalb auch den Ersteller der Lib
für den DS18B20 oder DS18S20 kontaktier aber leider noch keine Antwort
erhalten.
Ich Finde die Lib recht übersichtlich und für mich leicht zu verstehen.
Ich kann zwar so nur einen Sensor pro Pin nutzen aber das reicht mir.
Vielleicht kennt ihr ja eine gute Lib für den DS18B20 bei der sich der
Pin leicht einstellen lassen kann und den Temperatur Wert in Form eines
Char String ausspuckt.
Grüße Björn
Habe es jetzt mal so versucht:
snprintf(temp_po_str, sizeof(temp_po_str-1), "12.5");
anstatt der float Variablen temp_po habe ich jetzt mal "12.5" eingefügt.
Ergebnis = Mist
was kann ich da eintragen um einen definierten "float" Wert zu haben?
Laut library ist der Rückgabewert vom Typ unsigned char temp_po_str[8]
und muss nicht weiter konvertiert werden.
Vielleicht mal mit Ausgaben an RS232 debuggen?
Pete K. schrieb:> Laut library ist der Rückgabewert vom Typ unsigned char temp_po_str[8]> und muss nicht weiter konvertiert werden.>> Vielleicht mal mit Ausgaben an RS232 debuggen?
Die Float lib ist mit drinnen.
Was meinst du mit Ausgabe an RS232 debuggen?
Grüße Björn
Björn Hiekel schrieb:> Ich kann zwar so nur einen Sensor pro Pin nutzen aber das reicht mir.
Hä? Das ist One-Wire, da kannst du so viele dran hängen wie du willst.
Ich hatte das mit Arduino gemacht, bei C bin ich noch nicht so weit,
deshalb überlasse ich das mal den anderen dir hier weiter zu helfen.
Hast du das Datenblatt mal gelesen? Da sind gar nicht viele Befehle.
Bei Dallas gibt es ne Lib, aber ich glaube Peter Danegger hat da wohl
was besseres geschrieben.
Ist schon fast zwei Jahre her, seit ich mich damit auseinander gesetzt
habe. Für meine Fritzbox brauchte ich noch mal einen, das habe ich dann
aber mit Arduino gemacht. Da ist das alles Pipifax, weil alles im Grunde
fertig ist.
Björn Hiekel schrieb:> snprintf(temp_po_str, sizeof(temp_po_str-1), "12.5");>> anstatt der float Variablen temp_po habe ich jetzt mal "12.5" eingefügt.>> Ergebnis = Mist
Du hast nun die float-Variable 'temp_po' durch eine Zeichenkette ersetzt
"12.5". Wenn musst Du 12.5 übergeben, ohne "".
Wenn das zutrifft
Pete K. schrieb:> Laut library ist der Rückgabewert vom Typ unsigned char temp_po_str[8]> und muss nicht weiter konvertiert werden.
Dann musst du schreiben
1
msg=ds1820_read_temp(DS1820_pin_po);
Irre ich mich, oder muss msg nicht vorher noch irgendwie die anzahl der
Felder bekommen? z.B.: msg[10]
Björn Hiekel schrieb:> Was meinst du mit Ausgabe an RS232 debuggen?
Er meint, dass du dir die Variblen über die serielle Schnittstelle
anschauen sollst.
Terminalprogramm öffnen. Mit deinem µC verbinden und der soll dir dann
über die RS232 die Variableninhalte an das Terminalprogramm senden
F. Fo schrieb:> Hä? Das ist One-Wire, da kannst du so viele dran hängen wie du willst.
Die Lib ist so konzipiert, dass sie nur ein Gerät am Bus unterstützt.
Für mehrere Geräte, müssen halt mehrere Busse (Pins) verwendet wrden.
Das ist alles.
du scheinst Anfänger zu sein. deswegen vergiss float. werDein Ansatz,
die Kommas wegzulassen, ist zur Vereinfachung richtig.
der ds1820 liefert dir einen 16bit Wert temp. dieser muss in einen
Integerwert umgesetzt werden:
dieser Integerwert muss für dein Lcd aufbereitet werden. Einen
Integerwert zerlegt man zur Anzeige auf dem Lcd in einzelne Ziffern, die
dann als char auf dem Lcd dargestellt werden. Dafür gibt es fertige
Funktionen. Als Anfänger sollte man sich darüber keinen Kopf machen. Die
Funktion findest du in der lib, aus der du deine lcd-Ansteuerung
genommen hast.
Ich habe das ganze jetzt so gelöst und es wird mir auch was angezeigt
nur leider nicht meine Zimmer Temperatur. Es werden in etwa - 51C°
angezeigt und bei Erwärmung steigt es auch. k. A. woran es liegt...
vielleicht habe ich doch den falschen Sensor. Wie kann ich das
herausfinden bzw. wo könnte ich in meinem Code einen Testwert eintragen?
z.B. 1111 1111 1111 1000 für -0.5C°
Grüße Björn
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include "i2cmaster.h"
#include <stdio.h>
#include <stdlib.h>
#include "ds18x20lib.h"
#include "delay.h"
#define SLAVE_ADDRESS1 0xa0
void Display_1(char cmd, char data) //Funktion für Datenübermittlung an
Display 1
{
i2c_start(SLAVE_ADDRESS1 | I2C_WRITE);
i2c_write(cmd);
i2c_write(data);
i2c_stop();
}
void WriteStr_D_1(char *s) // Funktion bei längeren Zeichenketten als
vier Buchstaben (Laufschrift)
{
char i;
for (i = 0; i < 4; i++)
Display_1(0x20 | i, s[i]);
}
void START_DISPLAY (char i) //Funktion Display Start
{
i2c_init();
i2c_start(SLAVE_ADDRESS1 | I2C_WRITE) != 0;
i2c_stop();
Display_1(0x01, 0xFF); // Intensität 10
Display_1(0x02, 0xFF); // Intensität 32
Display_1(0x03, 0x01); // scan limit
Display_1(0x04, 0x01); // kein shutdown
Display_1(0x07, 0x01); // display test mode on
_delay_ms(4000); // 4 Sekunden Displaytest
Display_1(0x07, 0x00); // display test mode off
_delay_ms(200); // 200m Sekunden warten
for (i = 0x60; i < 0x64; i++)
Display_1(i, 0); // schreibe D0, D1
}
void main(void) //Main
{_delay_ms (4000);
unsigned char i;
unsigned char temp_S1_LUFT_Str[8];
float temp_S1_LUFT;
START_DISPLAYS(i);
while(1)
{
ds1820_init(DS1820_pin_po); //Initialize DS1820 Sensor 1 Luft
temp_S1_LUFT = ds1820_read_temp(DS1820_pin_po); //temperature
from
Sensor 1 Luft(float)
char WERT_Temp_Luft[8];
dtostrf(temp_S1_LUFT,3,1,WERT_Temp_Luft); //Float zu ASCII
_delay_ms(5000);
WriteStr_D_1(WERT_Temp_Luft); // schreibe vier Zeichen
_delay_ms(250);
}
return 0;
}
Björn Hiekel schrieb:> = ds1820_read_temp(DS1820_pin_po); //temperature
Der DS1820 liefert dir einen 16bit Integer-Wert. Was willst du da mit
float?
temp_S1_LUFT muss ein 16bit integer sein.
lass es dir direkt anzeigen, rechne es in binär um -calc.exe-, vergleich
es mit dem Manual, dann weißt du ob dein Sensor richtig arbeitet.
Danach kommt die Umrechnung in Celsius.
@Leluna
Die *.lib liefert ihm einen float Wert. Ergo macht er schon alles
richtig
Björn Hiekel schrieb:> Hallo zusammen,>> ich verwende eine DS18B20 Lib von Stefan Sicklinger Link:> http://www.sicklinger.com/en/atmel-avr-atmega-ds18x20-library-in-c.html
Klick auf den Link und staune. Unter Punkt 4 steht:
"Der Rückgabewert von ds1820_read_temp(uint8_t DS1820_pin) ist float."
@ Björn:
Initialisiere mal die Variable 'WERT_Temp_Luft' als int und nicht als
char.
Bei mir funzt das nämlich nur mit int.
Guten Morgen zusammen,
also wie bereits erläutert, bekomme ich einen float Wert.
@Praktikant:
Ich habe die Initialisierung jetzt auf Int umgestellt nur ändert sich
leider nichts. Jetzt zeigt es mir -70C° an. Ich habe einfach mal den
Temperatursensor DS18S20 anstatt DS18B20 bestellt. Es steht zwar
geschrieben, dass die lib für DS18x20 ist - also für beide aber in der
lib selber lese ich immer nur DS18s20.
Hätte man mit sicherheit ganz einfach umprogrammieren können, aber wie
gesagt ich bin froh das es überhaupt schon mal was anzeigt. ;-)
Ich melde mich wieder mit dem neuen Sensor in der Hand.
Danke!
leluno schrieb:> hast du die Umrechnung auf Celsius:> //CelsiusTemp=> CelsiusTemp=> ((temp & 0xf000) | (temp>>4) )*10+((temp - (temp & 0xfff0))*10+8)/16;>> ??
Meinst du das so?
@leluno
Wo soll er denn die Umrechnung einbauen? Die Funktionsbeschreibung sagt
doch ganz klar, dass die Funktion die Temperatur als float mit einer
Nachkommastelle zurückgibt.
Das Problem könnte wirklich im falschen Typen begründet liegen.
Laut Datenblatt arbeitet der S-Typ mit 9 Bit Auflösung.
Der B-Typ startet immer mit 12 Bit.
Wenn du den B-Typ mit der Funktion für den S-Typ ausliest, dann ist das
wohl die Erklärung warum deine Temperaturwerte nicht passen.
lass den negativ-Teil erstmal weg.
aus dem Manual ergibt sich die Umrechnung des 16bit Integer-Werts in °C:
die ersten 12bits für den Vorkommawert die letzten 4bits für den
Nachkommawert
lass den Nachkommawert auch weg.
Die Temperatur in °C ergibt sich dann, indem du deinen Wert
temp_S1_Luft um 4 Stellen nach rechts schiebst:
temp_S1_Luft = temp_S1_Luft>>4
Wenn das funktioniert kümmerst du dich als nächstes um die
Nachkommastellen und die negativen Werte