-         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: Temperatur via I2C

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.04.2007
    Beiträge
    114

    Temperatur via I2C

    Anzeige

    Ich versuche mich gerade an der Programmierung meiner Terrarium Steuerung, aber komme leider bis jetzt noch nicht sehr weit.
    Was mir besonders großes kopfzerbrechen berreitet, ist das auslesen der Temperatur Sensoren (DS1621).
    Wie lese ich die Sensoren im Program aus? Wie weise ich jedem Sensor auch seine Temperatur zu (Adreesierung der Sensoren)?
    Habe leider keine Tourials oder Anleitung über I2C gefunden.

    Danke,
    ciao Hannes

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    46
    Beiträge
    2.236
    Hallo,
    Das ist denkbar einfach(Dattenblatt zu DS hast Du ?), so ein DS1621 hat 3 ? Adresspins,
    wenn alle 3 auf Low liegen hat er die adresse 0x90, Du kannst auch welche auf High legen, dadurch änderst Du die Adressen(steht im Dattenblatt, wie die Werte zusammenkommen)
    Wichtig ist, daß Du keine 2 mit gleicher Adresse hast
    Dann besorgst Du Dir die i2cmaster lib von hier
    Es gibt da zwar TWI und USI, je nach Controller, aber die lib von Peter Fleury ist erste Sahne; klein, schnell, gut.
    Jetzt mußt Du alle DS1621 "in den Hintern treten" um die Messung zu starten.
    Man sendet 0xEE an alle Bausteine.
    Mit der lib von Fleury z.B. so:
    Code:
    #define I2CTHERMO 0x90
    #define STARTCONVERT 0xEE
    ...
    unsigned char i2cstatus; 
     i2cstatus = i2c_start(I2CTHERMO+I2C_WRITE);
      if (i2cstatus){
        LCD_puts("Error");
        i2c_stop();
      } else {
        i2c_write(STARTCONVERT);
        i2c_stop();
        LCD_puts("Convert starting...");
    so Werte abholen:
    Code:
    #define GETTEMP 0xAA
    ...
    ...
     	i2c_start_wait(I2CTHERMO+I2C_WRITE);
    	i2c_write(GETTEMP);
    	i2c_rep_start(I2CTHERMO+I2C_READ);
    	i2cpuffer[0] = i2c_readAck();
    	i2cpuffer[1] = i2c_readNak();
    	i2c_stop();
    in i2cpuffer[0] steht die Temperatur drin, in i2cpuffer[1] die 0,5 Grad
    Einfach ?
    Am besten probierst Du erstmal mit einem Baustein...
    Und die Pullups am Bus nicht vergessen, sonst klappt es nicht!
    Gruß Sebastian

    P.S. Es gibt noch andere schöne Sachen, die Du mit dem DS1621 machen kannst, wie Thermostatfunktion usw.
    Was man Ihm dann zuflüstern muß kannst Du auch in Dattenblatt nachschlagen.

    Wenn noch fragen offen sind, dann frag einfach
    Software is like s e x: its better when its free.
    Linus Torvald

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.04.2007
    Beiträge
    114
    Super, hast mir erstmal echt weiter geholfen.
    Nur verstehe die zeilen noch nicht so ganz die du da Programmiert hast, z.B. "LCD_puts("Error");"
    Sehe ich das richtig, das diese Zeile für ein LCD display vorgesehen ist? (Will erstmal keins verwenden, nur die Temperatur Regeln)

    Ja, das Datenblatt habe ich, aber habe da nix gefunden von der Adressierung.
    Die Pullup Widerstände sind meine ich schon auf meinem Board (ATMEL Evaluations-Board Version) drauf

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    46
    Beiträge
    2.236
    Ja, das Datenblatt habe ich, aber habe da nix gefunden von der Adressierung.
    Doch,doch, habe gerade das Dattenblatt rausgehollt Seite 8 unter Slave Address oder so.
    Die Adresse setzt sich wie folgt zusammen:
    1 0 0 1 A2 A1 A0 0
    wobei A2-A0 die 3 vorhingenannten Pins sind.
    Legst Du alle auf LOW sieht die Adresse so aus 10010000 was 0x90 ergibt
    Legst Du A2 auf HIGH bekommst Du 10011000 was 0x98 gibt usw.
    Der Letzte Bit LSB gibt die Dattenrichtung, das erledigt aber sie Software, für Adresseberechnung nimmst Du immer 0...
    Sorry, die LCD_puts Funktion habe ich nicht rausgelöscht, es sollte nur zur Debugzwecken drin stehen, wenn alles klappt, braucht man das natürlich nicht

    Achso in der i2clib mußt Du noch Deine Pins einstellen, schau mal in der i2cmaster.S ganz am Anfang, bei mir steht da z.B.
    Code:
    ;***** Adapt these SCA and SCL port and pin definition to your target !!
    ;
    #define SDA     	5		// SDA Port D, Pin 4   
    #define SCL		4		// SCL Port D, Pin 5
    #define SDA_PORT        PORTE           // SDA Port D
    #define SCL_PORT        PORTE           // SCL Port D
    Das ist dann alles, was Du einstellen mußt...
    die i2cmaster.S muß noch im Makefile unter
    ASRC=i2cmaster.S stehen und in Deinem Hauptprogramm mußt Du
    #include"i2cmaster.h" reinschreiben.
    Beide Dateien im gleichem Ordner wie Dein Hauptprogramm !
    Sorry, aber ich kenne Deinen Wissenstand nicht, und bevor Du fragen mußt...

    Viel erfolg

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.04.2007
    Beiträge
    114
    Zitat Zitat von izaseba

    Sorry, aber ich kenne Deinen Wissenstand nicht, und bevor Du fragen musst...
    Nix für ungut, hast das schon richtig erkannt, habe noch nicht wirklich die Ahnung^^.

    Habe jetzt aber noch eine Frage, wie bekomme ich die beiden werte zusammengefügt?
    i2c_readAck();
    i2c_readNak();
    Habe das jetzt so verstanden, das der i2c_readAck() die vor Komma stelle ausließt und der i2c_readNak() die nach Komma stelle ausließt. Die sollten Praktischer weise zu einer Zahl zusammen gefügt werden.
    Muss ich dafür eine Variable anlegen? Wenn ja was für eine? Eine float?

    ciao Hannes

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    46
    Beiträge
    2.236
    i2c_readAck();
    i2c_readNak();
    Habe das jetzt so verstanden, das der i2c_readAck() die vor Komma stelle ausließt und der i2c_readNak() die nach Komma stelle ausließt. Die sollten Praktischer weise zu einer Zahl zusammen gefügt werden.
    Das hast Du richtig verstanden, es hat aber was mit I2C Protokol zu tun, wenn Du mit i2C_readAck() liest, sendet der Master noch ein ACK Puls an den Slave, um zu sagen,
    "Hallo wir sind noch nicht fertig, ich will weitere Daten lesen"
    Mit i2c_read(Nack) wird halt kein Ack erzeugt womit der Master sagt, "wir sind jetzt fertig, will nichts meh von Dir" darauf folgt Stop und der Bus wird wieder Freigegeben

    Tja, das zusammenfügen...
    kommt drauf an, was Du willst...
    Auf den LCD willst Du sie nicht darstellen(hast Du oben schon gesagt)
    Über UART versenden ? dann mußt Du das ganze in ASCII wandeln
    Rechnen ? Da stellt sich die Frage, wie genau ?
    Muß es bis auf 0,5 Grad genau gehen ?
    Mann könnte das ganze in float wandeln, frage ist nur, ob es lohnt, float ist so eine Sache bei AVR, aber hier ein Beispiel, wie das gehen könnte
    Code:
    float temperatur;
    temperatur = i2cpuffer[0];
    if (i2cpuffer[1])
       temperatur +=0.5;
    Eventuell muß man bei der ersten Zuweisung ein cast machen (float)i2cpuffer[0] ?

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.04.2007
    Beiträge
    114
    Es wäre schon schöner wenn ich die 0,5°C genau messen könnte, aber zu not geht es erstmal auch ohne Kommar Stelle.
    Will die ganze vorgehensweise erstmal verstehen.

    Hier mal mein "Progamm" was ich bis jetzt geschrieben habe, bzw. mit deinen Codes zusammen geflickt habe ^^
    Kannst du bitte mal gucken ob es totaler unsin ist, oder was ich da noc ändern muss?

    Code:
    #include <stdio.h>
    #include <avr/io.h>
    
    #include"i2cmaster.h"
    
    #define GETTEMP 0xAA
    #define I2CTHERMO 0x90 
    #define STARTCONVERT 0xEE 
    
    
    int Temp;  			/* Variable für Temperatur */
    Temp=i2cpuffer[0];	/*Temperatur Wert des Seonsors der Variablen zuweisen*/
    
    DDRA = (1 << DDA0); /*Pin0 am Port A als ausgang setzten*/
    
    int main(void)
    {
     if (Temp >= 1900h)	/*Bedinung, solange Temperaturwert von 25°C noch nicht erreicht ist*/
     {
      PORTA |= (1<<PA0);/*soll Ausgang PA0 ein sein (Heizung an)*/
     }
     else
     {
      PORTA &= ~(1<<PA0);/*Wenn Temperatur erreicht ist soll Ausgang PA0 wieder ausgeschaltet werden*/
     }
     endif; /*Ende der if bedinung*/
     return 0;
    }  
    
     i2c_start_wait(I2CTHERMO+I2C_WRITE); 
     i2c_write(GETTEMP); 
     i2c_rep_start(I2CTHERMO+I2C_READ); 
     i2cpuffer[0] = i2c_readAck(); 
     i2cpuffer[1] = i2c_readNak(); 
     i2c_stop();
       
       
    
    unsigned char i2cstatus; 
     i2cstatus = i2c_start(I2CTHERMO+I2C_WRITE); 
      if (i2cstatus)
      { 
        LCD_puts("Error");-
      } 
      else 
      { 
        i2c_write(STARTCONVERT); 
        i2c_stop(); 
        LCD_puts("Convert starting...");
      }
      endif;
    Danke, ciao Hannes

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    46
    Beiträge
    2.236
    Hallo Hannes,
    das sieht schonmal gut aus
    Hast Du das Programm durch den Kompiler gejagt ?
    Kommst Du aus der Basic Welt ?
    also endif gibt es in dieser Weise nicht bei C, es gibt zwar die Präprozessordirektive
    #endif, das ist aber etwas anderes...
    und if (temp >=1900h) sagt mir auch nichts, was heißt h ?
    Hexadezimal oder wie?
    Nicht so kompliziert denken
    if(temp >=25) wäre hier besser gewesen...

    ich schreibe Dir einfachmal das Programm, versuch es zu verstehen
    Code:
    #include <avr/io.h>
    #include "i2cmaster.h"
    #define GETTEMP 0xAA 
    #define I2CTHERMO 0x90 
    #define STARTCONVERT 0xEE
    
    int main(void) {
       char i2cpuffer[2];
       DDRA = (1<<PA0);
       i2c_start(I2CTHERMO+I2C_WRITE);
       i2c_write(STARTCONVERT);
        i2c_stop();
       for(;;) {
          i2c_start_wait(I2CTHERMO+I2C_WRITE);
          i2c_write(GETTEMP);
          i2c_rep_start(I2CTHERMO+I2C_READ);
          i2cpuffer[0] = i2c_readAck();
          i2cpuffer[1] = i2c_readNak();
          i2c_stop();
          if (puffer[0] >= 25)
             PORTA |=(1<<PA0);
          else
             PORTA &=~(1<<PA0);
         }
         return 0;
    }
    So in etwa, es kann sein, daß da irgendwo sich ein Fehler versteckt, habe bitte Gnade mit mir, ich habe es eben so zusammengetippt...

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    24.04.2007
    Beiträge
    114
    Danke,
    ne hab es erstmal nur in winAVR eingetippt.
    Hab uhrsprünglich C++ gelernt, ist allerdings schon ca. 4 Jahre her.
    Den wert 1900h hab ich ausm Datenblatt vom DS1621. Dachte das müsste ich in Hexa oder so eingeben.
    Brauche ich den #include <stdio.h> nicht?

    ciao Hannes

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    46
    Beiträge
    2.236
    Den wert 1900h hab ich ausm Datenblatt vom DS1621
    Hmmm, hex schreibt man in C (und auch C++) 0x** und nicht mit h am Ende.
    H am Ende schreibt man in Basic(glaub ich), naja, egal Du kannst auch hex schreiben, wenn Du willst, aber 1900 in hex paßt ja nie in eine 8Bit Variable rein.
    stdio.h ? nein, für das kleine Programm nicht, auf dem AVR auch sehr selten,
    wenn Du Funktionen, wie printf usw. brauchst dann sollte man stdio.h einbinden, ich habe es noch nie gebraucht...
    Sowas braucht man eher auf dem PC.
    Das Programm ist auch nicht ganz optimal, es fehlt eine Hysterese usw. aber für die ersten Schritte sollte es wohl mehr als ausreichen,,,

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •