DS1620

In manchen Anwendungsfällen kann es wichtig sein, die aktuelle Temperatur zu kennen und entsprechend darauf zu reagieren. Dazu benötigt man ein Thermometer. Das DS1620 ist ein digitales Thermometer mit Thermostatfunktion. Temperaturen zwischen -55°C und 125°C können mit einer Auflösung von 0.5°C in ein 9-Bit-Wort gespeichert und seriell gelesen werden. Außerdem können im DS1620 Schwellwerte gespeichert werden, mit denen man die Thermostatfunktionen einstellt. Dafür kann eine untere und eine obere Schranke eingestellt werden. Nach unter- bzw. überschreiten dieser Schranken werden die entsprechenden Ausgänge des DS1620 auf HIGH gesetzt. Zusätzlich werden im Speicher des DS1620 Flags auf 1 gesetzt, um die Zustände der Thermostatfunktionen seriell auslesen zu können. Leider werden diese Flags, sobald sie einmal auf 1 gesetzt sind, nicht mehr zurückgesetzt bei einer Zudstandsänderung, obwohl die Ausgänge wieder auf LOW zurück gehen. Man kann mit den Flags folglich nur überprüfen, ob die Schranken irgendwann während des Betriebs unter- bzw. überschritten wurden. Abhilfe kann das manuelle Überschreiben der Flags bei einer Zustandsänderung schaffen.
In diesem Beispiel werde ich im 3-Sekundentakt die Temperatur auslesen und auf der Konsole ausgeben. Außerdem werde ich eine untere Schranke 17°C und eine obere Schranke 19°C einstellen, um die Thermostatfunktionen zu testen. Bei Unterschreiten von 15°C wird das Programm terminieren und die Messung stoppen. Es wird auf der Konsole ausgegeben, ob die Schranken während des Betriebs mindestens einmal unter- bzw. überschritten wurden, also die Flags gesetzt sind. Mit einem Kühlpack werde ich die Temperatur zum Experimentieren entsprechend anpassen.

Inhalt


Material

  • DS1620
  • Drei 330 Ohm Widerstände
  • Drei LEDs
  • Diverse Kabel
  • Steckbrett

Aufbau

Beim DS1620 handelt es sich um einen sehr kleinen Baustein mit nur 8 Anschlüssen.

DS1620
Die Anschlüsse VCC und GND verstehen sich von selbst. In CLK gibt man ein Clock-Signal. Über DQ findet der Datentransfer zwischen DS1620 und Raspberry Pi statt. Es können Kommandos an den Baustein gesendet werden, um beispielsweise eine Messung zu initiieren oder um die Schwellwerte für die Thermostatfunktionen zu setzen. Außerdem kann beispielsweise die aktuelle Temperatur gelesen werden. Man muss folglich während des Betriebs beim DQ zwischen Ein- und Ausgang hin und her schalten. Nur wenn RST auf HIGH ist, ist ein Datentransfer möglich. Die Anschlüsse TH, TL und TC sind für die Thermostatfunktionen zuständig. Es können zwei Schwellwerte gespeichert werden. Wenn der Schwellwert für TL unterschritten wird, dann geht TL auf HIGH. Wenn der Schwellwert für TH überschritten wird, dann geht TH auf HIGH. Wenn TH auf HIGH geht, dann geht auch TC auf HIGH. TC bleibt solange auf HIGH, bis der Schwellwert für TL unterschritten wird.

Das Experiment hat folgenden Aufbau:

Gesamtaufbau
Für die Thermostatfunktionen habe ich die entsprechenden Ausgänge des DS1620 an LEDs angeschlossen. Theoretisch können die Ausgänge an das Raspberry Pi angeschlossen werden für intelligente Reaktionen auf unter- bzw. überschreiten der Schwellwerte, wie beispielsweise eine Hitzequelle automatisch ein- oder auszuschalten.

Programm

Während der Aufbau des Experiments relativ simpel ist, ist das Programm für diesen Aufbau leider recht komplex. Als Erstes beginnt man wie immer mit der Initialisierung der Anschlüsse:
#define DQ 29
#define CLK 28
#define RST 27

void init() {
    pinMode(DQ,  OUTPUT);
    pinMode(CLK, OUTPUT);
    pinMode(RST, OUTPUT);

    digitalWrite(DQ,  LOW);
    digitalWrite(CLK, HIGH);
    digitalWrite(RST, LOW);
}
Nach Messung der Temperatur liegen die Daten in einem 9-Bit langen Wort vor, dessen Wert sich in 0.5°C Schritten ändert. Beispielsweise wird 0°C mit 0, 0.5°C mit 1, 20°C mit 40, 20.5°C mit 41 usw. dargestellt. Negative Werte liegen im Zweierkomplement vor. Nach dem seriellen Auslesen der Daten müssen sie in eine Temperatur umgewandelt werden. Zum Schreiben einer Temperatur auf das DS1620, beispielsweise für die Schranken, muss sie in das entsprechende 9-Bit-Format umgewandelt werden.

Folgende zwei Funktionen dienen zur Umrechnung der Daten:
float ds_to_temp(short ds) {
    short msb = ds & (1 << 8);

    if(msb) {
        return ((ds-512)/(2.0f));
    }
    else {
        return ds/2.0f;
    }
}

short temp_to_ds(float temp) {
    if(temp >= 0) {
        return static_cast<short>(temp*2);
    }
    else {
        return static_cast<short>(temp*2)+512;
    }
}
Sowohl zum Lesen, als auch zum Schreiben muss RST auf HIGH gesetzt werden. Das niedrigste Bit wird immer zuerst gelesen bzw. geschrieben. Kommandos haben eine Länge von 8-Bit, während Temperaturen, wie weiter oben erwähnt, eine Länge von 9-Bit haben.

Zum Schreiben von Daten muss das entsprechende Bit in DQ bei der fallenden Flanke an CLK liegen. Folgende Funktionen dienen zum Schreiben von Daten auf das DS1620:
#define CMDLENGTH 8
#define TEMPLENGTH 9

void send_data(long data, int bits) {
    for(int i = 0; i < bits; i++) {
        if((data >> i)&(0x01)) {
            digitalWrite(DQ, HIGH);
        }
        else {
            digitalWrite(DQ, LOW);
        }
        digitalWrite(CLK, LOW);
        digitalWrite(CLK, HIGH);
    }
}

void send_command(char cmd) {
    send_data(static_cast<long>(cmd), CMDLENGTH);
}

void send_temp(float temp) {
    send_data(static_cast<long>(temp_to_ds(temp)), TEMPLENGTH);
}
Zum Lesen der Daten muss man DQ vor der steigenden Flanke von CLK auslesen. Vor dem Lesen muss ein Kommando gesendet werden, um zu signalisieren, dass die nächsten 8-9 CLK-Signale Daten gelesen werden. Wie diese Kommandos aussehen, steht gut beschrieben im Datenblatt.

Folgende Funktionen dienen zum Lesen einer Temperatur oder zum Lesen der Config, in der die Flags für die Thermostatzustände stehen:
#define DELAYCONST 200

short read_data(int bits) {
    short retValue = 0;

    pinMode(DQ, INPUT);

        for(int i = 0; i < bits; i++) {
            digitalWrite(CLK, LOW);
            short bit = digitalRead(DQ);
        digitalWrite(CLK, HIGH);
        retValue |= (bit << i);
    }

    pinMode(DQ, OUTPUT);

    return retValue;
}

float read_temp() {
    digitalWrite(RST, HIGH);
    send_command(0xAA); // Kommando zum Lesen der Temperatur
 
    short ds = read_data(TEMPLENGTH);

    digitalWrite(RST, LOW);
    delay(DELAYCONST);

    return ds_to_temp(ds);
}

char read_config() {
    digitalWrite(RST, HIGH);
    send_command(0xAC); // Kommando zum Lesen der Config

    char conf = read_data(CMDLENGTH);

    digitalWrite(RST, LOW);
    delay(DELAYCONST);

    return conf;
}
Bevor das Messen mit dem Thermometer losgeht, muss dieser entsprechend eingestellt werden. Man muss einstellen, ob die Temperatur einmalig oder kontinuierlich gemessen werden soll. Zusätzlich muss eingestellt werden, ob das Modul von extern vom Raspberry Pi über DQ gesteuert werden soll oder ob es eigenständig laufen soll. Wir wollen kontinuierliche Messungen und eine externe Steuerung. Dadurch ergibt sich folgende Funktion zum Einstellen des DS1620:
void ds_init() {
    digitalWrite(RST, HIGH);

    send_command(0x0C); // Zum Einleiten der Konfigurierung des Bausteins
    send_command(0x0A); // CPU Bit setzen und 1shot abschalten.

    digitalWrite(RST, LOW);

    delay(DELAYCONST);
}
Ebenfalls muss ein Kommando gesendet werden, dass den DS1620 dazu bewegt, kontinuierlich Messungen durchzuführen. Nach Ende des Programms stoppen die Messungen nicht. Es muss ein weiteres Kommando gesendet werden, wenn die Messungen gestoppt werden soll.
void measure_temp() {
    digitalWrite(RST, HIGH);
    send_command(0xEE); // Kommando zum Einleiten von Messungen
    digitalWrite(RST, LOW);
    delay(DELAYCONST);
}

void stop_measure_temp() {
    digitalWrite(RST, HIGH);
    send_command(0x22); // Kommando zum Stoppen von Messungen
    digitalWrite(RST, LOW);
    delay(DELAYCONST);
}
Folgende Funktionen dienen dazu, die Schranken für die Thermostatfunktionen zu definieren:
void set_th(float temp) {
    digitalWrite(RST, HIGH);

    send_command(0x01); // Kommando zum Schreiben der oberen Schrank
    send_temp(temp);

    digitalWrite(RST, LOW);

    delay(DELAYCONST);
}

void set_tl(float temp) {
    digitalWrite(RST, HIGH);

    send_command(0x02); // Kommando zum Schreiben der unteren Schrank
    send_temp(temp);

    digitalWrite(RST, LOW);

    delay(DELAYCONST);
}
In der main-Funktion wird nun im 3-Sekundentakt die Temperatur gemessen und auf der Konsole ausgegeben. Bei Unterschreiten der 15°C bricht die Progammschleife ab und es wird die Messung gestoppt. Zum Schluss werden die Thermostatflags in der Config ausgewertet.
int main() {
    if(wiringPiSetup() == -1) {
        return 0;
    }

    init();
    ds_init();

    set_tl(17.0f);
    set_th(19.0f);

    measure_temp();
 
    while(1) {
        delay(3000);
        float temp = read_temp();
        std::cout << temp << "°C" << std::endl;

        if(temp <= 15.0f) {
            break;
        }
    }

    stop_measure_temp();

    char conf = read_config();

    if(conf & THFLAG) {
        std::cout << "TH mindestens einmal überschritten." << std::endl;
    }

    if(conf & TLFLAG) {
        std::cout << "TL mindestens einmal unterschritten." << std::endl;
    }
 
    return 0;
}
Beim Kühlen mit einem Kühlpack wird man feststellen, wie die LEDs entsprechend den eingestellten Schranken ein- und ausgehen. In seltenen Fällen gehen bei mir beim Auslesen der Temperatur einige Bits kaputt und es werden unrealistische Temperaturen auf der Konsole ausgegeben. Ich bin mir nicht sicher woran das liegt. Vielleicht lese ich DQ zu schnell aus und man müsste das CLK-Signal etwas verlangsamen. Versuche nach einer Flanke die nächsten Schritte mit delay zu verzögern, haben zu nichts geführt. Eine mögliche Lösung könnte es sein, das Ergebnis der letzten Messung abzuspeichern und bei der nächsten Messung auf zu große Sprünge zu überprüfen. Insgesamt funktioniert das DS1620 sehr gut, insbesondere die Thermostatfunktionen.

Ich hoffe dieses Tutorial hat euch bei der Verwendung des DS1620 weitergeholfen oder euch seinen Nutzen näher gebracht und euch zum Kauf angeregt. Für weitere Informationen zum DS1620 siehe:

Keine Kommentare:

Kommentar veröffentlichen

Hinweis: Nur ein Mitglied dieses Blogs kann Kommentare posten.