Forum: Mikrocontroller und Digitale Elektronik Problem beim auslesen den IIC


von TemperaturDS1621 am LCD ausgeben mit ATmega644 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle zusammen

Ich bin mir sicher dass das problem bei mir ein kleines ist jedoch bitte 
ich euch mir zu helfen da ich noch recht neu bin hier:

Ich will mir meinem ATmega 644 die Temperatur mittel DS1621 am LCD 
ausgeben( in C)

Wenn ihr denkt das ich mich noch niergends durchgegoogelt hab stimmt das 
nicht:
Hab schon alles probiert was ich meiner macht steht und halte mich jetzt 
an peter fleury libary auserdem hatte einer schon mal ein ähnliches 
problem:


Beitrag "Atmega8 - DS1621 auslesen ( über TWI[ i2c])"

Bei mir hängt das Programm wenn er auf einen Interrupt wartet (TWI)
Von dort geht das Programm nicht mehr weiter.
Außerdem hab ich probeirt die Pins für meinen ATMGEA zu denfinieren 
damit er ja weiß wo ich die SDA UND SDL hab. auserdem sind die Adress 
Pins A0-A4 alle auf GND was heißt das ich die BiTS SDA und SDL mit 0x90 
und 0x91 defnier...

Ich bitte euch mir zu helfen weil ich echt nicht merh weiter weiß, wieso 
er bei der routinen warte hängen bleibt...

Das Projekt kann ich gerne per Email schicken

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> auserdem sind die Adress
> Pins A0-A4 alle auf GND was heißt das ich die BiTS SDA und SDL mit 0x90
> und 0x91 defnier...

Der DS1621 hat keine Adresspins A3 und A4. Er hat nur A0, A1 und A2.
http://www.datasheetdir.com/DS1621+Temperature-Sensors
Wie ist der Sensor wirklich angeschlossen, wo und wie groß sind die 
Pullups (Schaltplan)?

Widersprüchlicher Kommentar in main.c
1
#define SDA       1    // SDA Port D, Pin 1
2
#define SCL    0    // SCL Port D, Pin 0
3
#define SDA_PORT        PORTC           // SDA Port C
4
#define SCL_PORT        PORTC           // SCL Port C

Du musst SDA an PC1 hängen und SCL an PC0 und NICHT an Port D wie im 
Kommentar oben.

Erste Anweisung in main() ein sei()???
1
int main(void)  {
2
3
    sei();
4
...
Das brauchst du sicher nicht.

Vielleicht magst du mal auf die Seite 
Pollin Funk-AVR-Evaluationsboard: Temperaturmessung mit DS1621 gehen. 
Dort sind Debugausgaben eingebaut. So etwas könntest du in deinen Code 
einfügen und berichten wo genau das Programm hängt - vor while(1) oder 
danach...?

von TemperaturDS1621 am LCD ausgeben mit ATmega644 (Gast)


Angehängte Dateien:

Lesenswert?

Danke erst mal für deine schnelle antwort

Das mit SDA und SDL ist einer miener hauptprobleme denke ich denn ich 
habe ja die libary übernommen non peter f und das kommentar mit port D 
hab nur nicht geändert tut mir leid...nur wo stell ich eben ein das sich 
alles auf port c abspielt ???
Ich denke mein Hauptproblem besthet darin, dass sich der Tempsensor 
nicht angesprochen füllt..

die zeilen
#define SDA_PORT        PORTC           // SDA Port C
#define SCL_PORT        PORTC           // SCL Port C
hab ich aus peter f´s i2cmaster.S rauskopiert weil ich snst niergends im 
programm auser in der datei i2cmaster.S eine deklaration für den Port 
gefunden habe Brauch ich die überhaupt..??

Da mein Programm beim debuggen bei  der zeile im twimaster.c bei der 
programzeile
  // wait until transmission completed
  while(!(TWCR & (1<<TWINT)));
unendlich lange warte dahcte ich mir die interrupts sind nicht 
eingeschaltet was ich mit sei() machen wollte...

Im Anhang siehst du meine Pinbelegung für den Tempsensor in Eagle
Pullups mit 4,7 kohm wurdn berücksichtigt

von Stefan B. (stefan) Benutzerseite


Lesenswert?

TemperaturDS1621 am LCD ausgeben mit ATmega644 schrieb im Beitrag 
#1679615:

> Das mit SDA und SDL ist einer miener hauptprobleme denke ich denn ich
> habe ja die libary übernommen non peter f und das kommentar mit port D
> hab nur nicht geändert tut mir leid...nur wo stell ich eben ein das sich
> alles auf port c abspielt ???

Das wird von der Library automatisch gemacht. In der Library werden die 
entsprechenden Makros aus dem AVR spezifischen Includefile verwendet, 
die an dem jeweiligen AVR auf die SDA und SCL Pins im Datenblatt gehen. 
Die Library ist nicht dafür gemacht den I2C auf zwei beliebige Pins zu 
legen. Der Anwender (du) muss dafür sorgen, dass das I2C Bauteil an den 
TWI Pins SDA/SCL richtig angeschlossen ist.

> Ich denke mein Hauptproblem besthet darin, dass sich der Tempsensor
> nicht angesprochen füllt..

Sehe ich auch so und deshalb auch die Frage nach dem Schaltplan. Leider 
kann ich das proprietäre Format *.SCH nicht lesen. Ein Screenshot wäre 
für mich einfacher zu betrachten (Bildformate beachten).

> die zeilen
> #define SDA_PORT        PORTC           // SDA Port C
> #define SCL_PORT        PORTC           // SCL Port C
> hab ich aus peter f´s i2cmaster.S rauskopiert weil ich snst niergends im
> programm auser in der datei i2cmaster.S eine deklaration für den Port
> gefunden habe Brauch ich die überhaupt..??

Ich denke die brauchst du nicht.

> Da mein Programm beim debuggen bei  der zeile im twimaster.c bei der
> programzeile
>   // wait until transmission completed
>   while(!(TWCR & (1<<TWINT)));
> unendlich lange warte dahcte ich mir die interrupts sind nicht
> eingeschaltet was ich mit sei() machen wollte...

Mit was debuggst du?

von TemperaturDS1621 am LCD ausgeben mit ATmega644 (Gast)


Angehängte Dateien:

Lesenswert?

ok bilddatei is im anhang

Hardwaremäßig sollte aber wirklich alles korrekt sein...
sprich: SDA und SDL gehen auf PC0 bzw PC1 des AVR's.
Also müsste ich wohl auch noch die iom644.h Datei einfügen oder reicht 
die normale avr/io.h?
Desweiteren bin ich mir auch nicht wirklich sicher ob ich auch die 
interrupt.h brauche!?

Die Zeilen
#define SDA_PORT        PORTC           // SDA Port C
#define SCL_PORT        PORTC           // SCL Port C
habe ich rausgelöscht

Ich verwende AVR Studio4 mit Gnucc und habe mria uch jetzt nochmal genau 
das Datenblatt den ATmegas durchgelesen und hab das programm jetzt im 
debugger zum laufen gebracht. Dazu habe ich einfach das Interrupt Bit 
des TWI gesetzt. Das Programm leif dann Weiter bis zr Zeile:

  // wait until stop condition is executed and bus released
  while(TWCR & (1<<TWSTO));

Laut Datenblatt muss TWSTO auf Null Rückgesetzt werden( ob das von der 
Hardware oder Software erledigt wird, weiß ich nicht)

Also läuft das Programm jetzt doch...eben nur Hardwaremßig geht nix weil 
eben  denke das das Interrupt Flag nicht gesetzt wird..
Vielleicht endeckst du ja zufällig was bei der Beschaltung..

von stephan_ (Gast)


Lesenswert?

Zum Schaltplan TempDS1621.GIF

I2C_Regel: SDA und SCL brauchen je einen 1k8 (ggf. auch 2k2) Pullup nach 
+5V, sind die auf dem µC-Board schon drauf? Der 5k6 ist kontraproduktiv.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die "Pullups" R1 und R2 sind falsch installiert. Das durfen keine 
Serienwiderstände sein wie im Bild gezeigt. Richtig installiert gehen 
die von der SDA (bzw. SCL) Leitung zu Vcc. 
http://www.i2c-bus.org/i2c-primer/

von TemperaturDS1621 am LCD ausgeben mit ATmega644 (Gast)


Angehängte Dateien:

Lesenswert?

Danke Stephan_ und Stefan =)
Habe jetzt die Widerstände wie es gehört umgezeichnet
Siehe Anhang
Nur kann ich nicht verstehen wieso ich jetzt einen 2k2 Widerstand nehmen 
soll und nicht so wie in PeterF Libary beschriebenen 4,7 ohm nehmen 
soll,Im Datenblatt des DS1621 hab ich nirgends über den Widerstand 
gelesen. Welche auswirkung hat den ein falscher Widerstandswert?

Dann werd ich mich heute noch gleich ans ätzen der Platine machen...und 
mein Glück dann versuchen
Nur:
Auf was wolltest du den genau hinaus Stefan, wie du fragtest welchen 
Debugger ich verwende. Und wie sieht es denn jetzt mit den Interrupts 
aus?
Muss ich sie jetzt irgdnwie noch im Programm einbauen/verwenden?

Danke für eure schnellen Antworten...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Debugger

Ich fragte, weil ich wissen wollte, ob du überhaupt eine Chance hast, 
einen Wechsel in TWCR zu sehen.

Wenn du nur den AVR Studio Debugger aka Simulator hast, hast du keine 
Chance. Du simulierst nur die Software im PC und nicht im AVR. Die 
konkrete Hardware hat darauf keinen Einfluß. Du könntest den weiteren 
Programmablauf nur simulieren/debuggen, wenn du selbst die Registerwerte 
änderst (manuell oder per Steuerdateien s. AVR Simulation).

Um die Wechselwirkung AVR <-> DS1621 real zu debuggen bräuchtest du 
einen On-Chip-Debugger z.B. über JTAG (Kapitel 22 im Atmega644 
Datenblatt).

Pullups

Die Größe der Pullups (min./max. Werte) ist in den Beschreibungen von 
I2C diskutiert: http://www.nxp.com/documents/user_manual/UM10204.pdf

Man kann die dortigen Berechnungen machen oder in der Praxis bewährte 
Werte nehmen. Peter Fleury nennt 4K7, anderswo findet man 2K2... IMHO 
werden beide Werte funktionieren, das ist an der Stelle erstmal nicht 
sooo kritisch. Selbst deine 5K6 werden wohl funktionieren. Wenn du dein 
System auf "lange" Leitungen ausbaust und ein schnelle Übertragungsrate 
haben willst... dann musst du dir an dieser Stelle wahrscheinlich 
Gedanken machen.

Grob falsche Pullups im Verhältnis zum Signaltiming verschleifen dir die 
Signale (s. PDF oben) und die Übertragung auf dem Bus wird unzuverlässig 
bis unmöglich.

Platine ätzen

Baust du nicht zuerst den Prototypen auf dem Steckbrett oder frei 
fliegend auf? Ätzen stünde bei mir erst am Ende der Entwicklung.

Interrupts

Brauchst du für den gezeigten Quellcode nicht. Sie stören aber die 
Library auch nicht grundsätzlich, wenn du später dein Programm mit 
Interrupts/Timern für andere Zwecke erweitern willst.

von TemperaturDS1621 am LCD ausgeben mit ATmega644 (Gast)


Lesenswert?

Debuggen
Beim Debuggen habe ich wie bereits erwähnt die  Registerwerte
einzeln verändert--> Resulatat war, dass das Programm lief..
Ob ich jetzt noch die Pogrammzeile zum Testen des TWI brauche?

Ausgabe an LCD
Desweiteren stellt sich mir die Frage ob, die Ausgabe des Inhalts der 
Temperatur (siehe Programm-->variable data) ohne weiters so ausgeben 
kann wie ich es im programm machen. Oder muss ich das Ergebnis noch 
irgendwie umwandlen etc??
Da ich ja nur von plusgrade anzeigen möchte und auch auf komma zahlen 
verzichten kann hab ich mir gedacht ich kann das eben so einfach machen 
(siehe programm)

Werte der Widerstände
Da ich relative kurze Leitungen habe (6 cm) wird es wohl nicht ganz 
ausschlaggegebnd sein wenn ich mal 4k/ nehme =)

Ätzen
Da ich ein wenig unter Zeitdruck stehe und diese Temperaturauslesen  in 
wenigen tagen fertig sein sollte , und neben bei den ganzen tag schule 
habe
werde ich nicht die zeit haben das aufn nem steckbrett zu testen...da 
der materialaufwand mir auch nix kostet...den rest kannste die ja 
denken...auserdem bin ich fast gelcih schnell =)

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Selbstverständlich brauchst du die Zeile bei der echten Hardware. Die 
Zeile ist ja dafür verantwortlich, dass die Daten komplett zwischen 
dem DS1621 und dem Atmega644 übertragen werden.

> Ausgabe an LCD
> Desweiteren stellt sich mir die Frage ob, die Ausgabe des Inhalts der
> Temperatur (siehe Programm-->variable data) ohne weiters so ausgeben
> kann wie ich es im programm machen. Oder muss ich das Ergebnis noch
> irgendwie umwandlen etc??

Auf jeden Fall musst du das DS1621 Ergebnis noch aufarbeiten. Zunächst 
liest du zwei 8-Bit Werte TempH und TempL. Anders als in deiner Source 
musst du beide Bytes zu einem 16-Bit Wert zusammensetzen 
(Temp=TempH*256+TempL) und anschliessend in ASCII umwandeln. Den 
ASCII-Text kannst du dann ausgeben. Siehe dazu 
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F. 
In meinem Link Zum Pollin-Funkboard oben kannst du das Prinzip auch 
erkennen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Stefan B. schrieb:

> Zunächst
> liest du zwei 8-Bit Werte TempH und TempL. Anders als in deiner Source
> musst du beide Bytes zu einem 16-Bit Wert zusammensetzen
> (Temp=TempH*256+TempL)...

Korrektur: http://pdfserv.maxim-ic.com/en/ds/DS1621.pdf

Wenn du nur eine Auflösung von 1°C brauchst (der Sensor kann 0,5°C), 
reicht es das Highbyte auszulesen. Das Lowbyte kannst du dann verwerfen, 
so wie in deiner Source. Die Umwandlung in eine Dezimalzahl im 
ASCII-Format brauchst du weiterhin.

von Alex (Gast)


Lesenswert?

Hab mir den Artikel hier durchgelesen den du mir gepostet hast.
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
Naja klingt garnicht so schwer nur beim schreiben habberts dann ein 
wenig:

Ich mag mich auch ein wenig schlau gemacht und hab herausgefunden, dass 
ich diese Ausgabe entweder mit der string.h-datei machen kann oder 
nicht:

wenn nicht muss ich wie du gesagt hast sagen wir jetzt wenn ich 
beispielweise25,5 grad ausgeben will Temp=TempH*256+TempL schreiben..

Um nun in ASCII zu formatieren muss ich auch noch "Temp" auf die 
einzelnen Zahlen aufspalten und dann 32 dazuaddieren (zu jeder zahl da 
im ASCII-Code Zahlen erst ab 32+n anfangen) danach jede Zahl 
nachainander ausgeben dann sollte ich den Tempert haben oder?
Stellt sich mir auch noch die Frage wie was mit dem + bzw - passiert. 
möchte das ja weg einfach lassen...

Oder ist es doch einfacher eine libary dazu zu verwenden wenn es die 
gibt zb.: string.h?

MFG

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Es ist im Prinzip wurscht, wie du es machst. Bei der Eigenkreation sieht 
ein anderer halt eher, ob du das Prinzip verstanden hast :)

Wie sich die Varianten in Codegröße und Ausführungsgeschwindigkeit 
unterscheiden kannst du ja einfach prüfen...

Das einfache "Aufaddieren" funktioniert nur, wenn du nur die 
Ausgangswerte 0...9 hast, bei den Hexwerten A..F in den Rohdaten (z.B. 
bei +125°C mit 0x7D in TempH) klappt das nicht ohne weiteres! Durch 
Divisionen mit Zehnerpotenzen wie in meinem Pollinbeispiel kann man 
diese Randbedingung sicherstellen.

Jetzt zu deinem konkreten Beispiel und zwei möglichen Herangehensweisen 
(ohne Anspruch auf besondere Eleganz oder Effizienz)

Bei 25,5°C liefert der DS1621 ja dieses Bitmuster:
(http://pdfserv.maxim-ic.com/en/ds/DS1621.pdf Tabelle 2)

1. Byte  2. Byte
00011001 10000000

Dein 1. ausgelesenes Byte könnte TempH zugewiesen werden und ist 
0b00011001 in Binärdarstellung (bzw. 0x19 in Hexdarstellung und 25 in 
Dezimaldarstellung)

Das 2. ausgelesenes Byte könnte TempL zugewiesen werden und ist 
0b10000000 in Binärdarstellung (bzw. 0x80 in Hexdarstellung und 128 in 
Dezimaldarstellung)

Du hast jetzt mehrere Möglichkeiten wie du weitergehen kannst. Hier ein 
Weg für den Umgang mit platzsparender Ganzzahlrechnung:

Fixkommarechnung

1. Byte  2. Byte
00011001 10000000
^

Das markierte Bit sagt dir, welches Vorzeichen auszugeben ist: 1 dann 
negative Zahl, 0 dann positive Zahl.

if ( TempH & 0x80 )
{
  lcd_data('-');
  TempH = -TempH; // negative Zahl ins positive wandeln
}
else
  lcd_data('+'); // oder nix ausgeben. "Geschmackssache sagt der Affe"

1. Byte  2. Byte
00011001 10000000
^^^^^^^^

Das 1. Byte sagt dir, welche Vorkommazahl auszugeben ist.

// % siehe modulo Operator
lcd_data( (TempH / 100) + '0' ); // Hunderterstelle ausgeben
TempH %= 100;                    // Hunderterstelle entfernen
lcd_data( (TempH / 10) + '0' );  // Zehnerstelle ausgeben
TempH %= 10;                     // Zehnerstelle entfernen
lcd_data( TempH + '0' );         // Einerstelle ausgeben

1. Byte  2. Byte
00011001 10000000
         ^

Das markierte Bit sagt dir, ob du eine .5 oder eine .0 als 
Nachkommazahl ausgeben sollst. 1 dann .5, 0 dann .0

lcd_data( ',' );         // Komma ausgeben
if ( TempL & 0x80 )
  lcd_data('5');
else
  lcd_data('0');

Fertisch mit Vorzeichen und Nachkomma. Wenn du Feinheiten einbauen 
willst, kannst du dir überlegen, wie du führende Nullen bei der 
Hunderterstelle und Zehnerstelle unterdrücken kannst.

Fließkommarechnung

Hier wird der Wert aus dem 1. und 2. Byte zusammengesetzt, in eine 
Gleitkommazahl umgewandelt und durch Division so rechtsbündig gemacht.

{
  float Temp = (float)(TempH*256 + TempL) / 256;
  char puffer[42]; // Länge geschätzt
  sprintf(puffer, "Temperatur %f Grad C", Temp);
  lcd_string(puffer);
}

Diese Variante benötigt besondere Projekteinstellungen für die 
Fließkomma-Libraries (s. FAQ).

von Alex (Gast)


Lesenswert?

So: hab das jetzt ales so programmiert...und es funktioniert 
einwandfrei!!!

Danke für deine sehr schnelle und tolle und ausführliche Hilfe Stefan!!!
1
tempa[0]=(char)Temp/100+'0';                  //Umwandlung der 16Bit in ASCII Zeichen
2
                  tempa[1]=(char)(Temp-(tempa[0]-'0')*100)/10+'0';
3
                  tempa[2]=(char)Temp-(tempa[0]-'0')*100-(tempa[1]-'0')*10+'0';
4
                  
5
                  
6
7
        
8
                  set_cursor(1,3);      //Setzte Cursor des LCD's in Zeile 3 Balken 1
9
10
                  if(tempa[0]!='0')      //Stellenabfrage 
11
                    {  
12
                      lcd_data(tempa[0]);
13
                    }
14
15
16
                    lcd_data(tempa[1]);      //Ausgabe der Umgewandelten Zeichen an des LCD-Display
17
                  lcd_data(tempa[2]);
18
                  lcd_data(',');
19
                  
20
                  if(data==0x80)  
21
                    {            //Abfrage des Kommawertes 
22
                      lcd_data('5');
23
                    }
24
25
                  else 
26
                    lcd_data('0');
27
                    
28
                  
29
      
30
31
32
                  set_cursor(7,3);
33
                  lcd_string("Grad Celsius");

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.