Hallo,
ich möchte einen Temperatursensor LM75 über i²C auslesen und die
Temperatur auf einem 2x16 Zeichen-Display ausgeben. Meine Hardware ist
ein myavr mk2 Board mit Atmega8 und ein LCD-Add-on, ebenfalls von my
avr.Weiterhin habe ich einen LM75 (auf einer Laborplatine verlötet) mit
an das Board angeschlossen.
Hardwaremäßig funktioniert das ganze (mit der Software
mySmartusbTerminal kann ich den LM75 auslesen und auch Temperaturen für
den Schaltausgang zum LM75 schreiben; ich habe ein LED am Schaltausgang,
die geht also auch bei entsprechender Einstellung). Software soll in C
erstellt werden.
Da ich absoluter Einsteiger in die Materie bin, habe ich mir im Internet
Quellcode und Libs gezogen und ein eignes kleines Main geschrieben, aber
ich bekomme damit noch keine vernünftige Anzeige aufs Display, es steht
nur immer für den Temperaturwert "1636" und anschließend dann
abwechselnd irgendwelche Hieroglyphen auf dem Display.
Hier mal mein main:
#define F_CPU 3686400UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdint.h>
#include "lcd.h"
#include "I2C.h"
#include "lm75.h"
volatile unsigned short temp;
int main()
{
while(1)
{
lcd_init();
lcd_on();
lcd_clear();
lcd_goto(1,1);
itoa(lm75_get_temperature, temp, 10 );
lcd_write_s( "Temp:" );
lcd_goto(1,6);
lcd_write_s( temp );
lcd_goto(2,1);
lcd_write_s( "Grad Celsius" );
_delay_ms(3000);
}
return 0;
}
und dazu der Ausschnitt aus dem lm75c, (das ich aus dem Internet habe)
in dem der Sensor ausgelesen werden soll:
unsigned short lm75_get_temperature (unsigned char address)
{
unsigned short temperature = 0;
lm75_init ();
lm75_send_start ();
lm75_send_add_rw (address, 1);
temperature = (lm75_read_byte () << 8);
temperature |= lm75_read_last_byte ();
lm75_send_stop ();
/*returned value will be right-aligned and negative*/
if (temperature & (1<<15))
{
temperature >>= 7;
temperature |= 0xFEFF;
return temperature;
}
else
{
/*returned value will be right-aligned and positive*/
return (temperature >> 7);
}
ich versteh jetzt nicht so richtig, wohin eigentlich der ausgelesene
Wert aus dem Temperaturregister abgespeichert wird (nach meinem
rudimantären C-Verständnis müßte es doch eine Variable geben, in die der
ausgelesene Wert abgespeichert wird?) "temperature" kennt allerdings das
main nicht als globale Variable, hab jetzt mal den Namen der Funktion
(lm75_get_temperature) im main aufgerufen. So wie ich das verstehe, ist
das lm75.c ein Unterprogramm, dass sich seinerseits wieder am
Unterprogramm für die i²C-Kommunikation bedient und mir einen "fertigen"
Wert für die Temperatur übergibt, den ich dann im main nur noch mit itoa
umwandeln muss, damit er als ASCII-Code ins Display geschrieben werden
kann? Vielleicht kann mir jemand weiterhelfen? Bei Bedarf kann ich auch
mal mein Projekt-Datei (ich arbeite mit AVR-Studio 4.18) hochladen.
Gruß
Ok, Danke erstmal.
Ich habe das jetzt mal so gemacht und bekomme nun "361" als ausgabe, ist
schonmal besser als das vorher ;-)
Hab jetzt beim itoa-Befehl mal Basis 2 also:
itoa(lm75_get_temperature, temp, 2)
eingegeben und dann die Anzeige: "101101001" bekommen. Beim Vergleich
mit dem Datenblatt des LM75 passt es ja insofern, als das es 9 Bit mit
Informationen sind, da ja (wenn ich das richtig verstanden habe) Bit 0-6
des Temperaturregisters nicht belegt sind, erst ab Bit 7 gehts los und
Bit 15 ist das Vorzeichen, sprich eigentlich hätte ich jetzt
Minus-Temperaturen? Ich weiß halt nicht, wie die Temperatur in dem
Register des LM 75 kodiert ist, weil es passt ja weder mit bcd-Code,
noch wenn ich es als 8-Bit Dualzahl lese und in einenDezimalwert
umrechne. Ich dachte eigentlich, dass die Umkodierung schon im lm75.c
erfolgt? jedenfalls ist dort die Abfrage nach dem 15.Bit wegen dem
Vorzeichen drin.
Gruß
Interpretier mal das erste ausgelesene Byte (MSB) als int8_t. Das ist
dann die Temperatur in °C als 2er-Komplement.
Daniel S. schrieb:> Ich dachte eigentlich, dass die Umkodierung schon im lm75.c> erfolgt?
Zeig mal den Code.
Gruß Oliver
Hallo Daniel,
ich bin auch grad am LM75 und habe auch Probleme.
Ich kann zwar Werte auslesen, doch diese haben 16er
Sprünge(0..16...32...48..64...80..96..112..0...16...usw..)
Man muss diesen Ascii Code in Dezimal umwandeln.
Du kannst mal deinen Code schicken.
Hier ist meiner
Gruss
Marcus
>temp.low >>=1;>temp.high<<=9;>ganzzahl= temp.low | temp.high;
Ich sage mal vorsichtig: das kann nicht richtig sein.
Ich würde an deiner Stelle Folgendes tun:
1. Mal nach 2er-Komplement googeln.
2. Genau überlegen was in einem 8-Bit-Wert bei einem Shift um 9 Stellen
nach links alles herausfällt.
3. Nochmal das Datenblatt des LM75 zu Rate ziehen und schauen, ob auch
wirklich ein Shift um eine Stelle reicht, um das LSB an die richtige
Stelle zu bringen.
4. Genau überlegen, ob es auch wirklich notwendig ist das assemblermäßig
über Shiftoperationen zu machen.
5. Abwägen ob es nicht eventuell reicht die Auflösung zu halbieren und
das MS-Byte als Temperatur in °C zu interpretieren.
Gruß Oliver
Hallo,
hier mal der Code von der c-Datei für den LM75 (den hab ich wie gesagt
so aus dem Internet übernommen). Außerdem das komplette AVR Studio
Projekt. Wenn ich das Byte, bzw. meine 9 Bit komplementär betrachte,
passt es leider immer noch nicht:
also ich hatte:
101101001 macht komplemenatär
010010110
geh ich jetzt mal davon aus, dass das MSB das Vorzeichen ist, passt das
zwar (0 entspricht positiver Temperatur), aber der Rest passt nicht,
BCD-Code würde Dezimal 96° ergeben, als 8-Bit-Wert Dezimal 150°. Im
Datenblatt stehen ja auch Beispiele:
+125°C 0 11111010
+25°C 0 00110010
+0.5°C 0 00000001
0°C 0 00000000
— 0.5°C 1 11111111
auch wenn ich hier das Komplement nehem, z.B. bei 25° komm ich nicht auf
den Dezimalwert, weder BCD noch als zusammenhängende 8 Bit. Das einzige,
was passt, wäre das LSB als 1. Nachkommastelle zu lesen, d.h. bei 0 sind
es xxx,0° ; bei 1 wären es xxx,5°.
dann hätte ich aus irgendeinem Grund noch ca. die doppelte Temperatur
(361=36,5=18,5°?), das deckt sich dann in etwa mit meinem Temometer hier
im Zimmer?
Gruß
Was mir grad noch aufgefallen ist:
-wenn der MCU neu gestartet wird, erscheint beim ersten
Schleifendurchlauf die zweite Zeile im Display (so will ich das
eigentlich auch haben), nachdem das erste Mal die Delay-Zeit abgelaufen
ist, wird nur noch die erste Zeile geschrieben, jemand ne Idee, woran
das liegt?
-der Wert von 361 wird nicht aktualisiert, ich habe den Sensor mal
erwärmt und abgekühlt, mit dem mySmartUSBTerminal reagiert die
Temperatur entsprechend, in meinem Programm passiert nichts, es sthet
immer nur 361 auf dem Display. Durch die Schleife im main müßte doch
etwa alle 3s der Wert neu abgefragt werden? oder ich frag irgendwas
andres ab, aber nicht wie gewollt das Temperatur-Register?
Gruß
Guten Morgen,
danke auch für den Denkanstoss von Oli !
ich hab´s gestern abend kurz vor 12 Uhr noch geschafft.
Es funktioniert jetzt.. logischerweise über das 9Bit Muster.
+125°C 0 1 1 1 1 1 0 1 0
VZ 64 32 16 8 4 2 1 0,5
@Daniel
Wenn du den Code haben möchtest, schreib mir eine Sms.
bin aber bald in Skiurlaub ! (grins)
Gruss
Marcus
Hallo,
ich habe gerade das gleiche Problem, dass ich den Wert 185 auf LCD habe.
Der Wert aktualisiert sich nicht und ist immer der gleiche. Deer
Raumtemp. bei uns ist so etwa 25 °C. Kann mir jemdand helfen die
richtige Temperatur anzeigen zu lassen.
Danke
Alex