Anfänger 1-wire DS1820

  • Hallo und einen guten Abend noch

    Seit ein paar Tagen besitze ich einen RPI. Nun wollte ich mit mit 2 1-Wire mal zwei Temperaturen messen. Wie die Sensoren geschaltet werden, weiß ich, da ich diese schon einmal an einem Microcontroller betrieben habe (was aus klappte). Die Module, die notwendig sind, habe ich in etc/modules eingetragen. Nun bin ich auf der Suche nach einem C++ code mit dem ich zwei oder auch mehrere sensoren auslesen kann. Kann mir bitte jemand eine Link sagen (hier einstellen) wo ich sowas finde.

    Der Code, den ich auf der Seite
    http://bradsrpi.blogspot.de/2013/12/c-prog…ure-from-1.html

    gefunden habe, funktioniert nicht. Es kommt mehrmals die Fehlermeldung unused variable.

    Danke schon einmal für die Hilfe

    Grüße
    Martin

  • ... funktioniert nicht. Es kommt mehrmals die Fehlermeldung unused variable.

    Diese Fehlermeldung ist eine Wanrung des Compilers und bestimmt nicht der Grund warum das Programm nicht funktioniert.

    Deine Fehlerbschreibung ist mehr als düftig. Mit diesem Informationsdefinzit kann Die keiner helfen :no_sad:

  • Guten Morgen,

    gibt es hier vielleicht im Forum eine c++ code, den ich zum auslesen nutzen kann. Ich habe leider keinen gefunden. Betimmt weil ich nicht die richtigen Suchwörter verwendet habe.

    Grüße
    Martin

  • Hallo Martin,

    welche Suchwörter hast Du denn benutzt?

    Hast Du es auch schon einmal so probiert:

    Code
    Raspberry Pi 1wire DS18B20 C++

    Andere Suchkriterien nutze ich selber, um zum Datenblatt zu kommen, in dem in der Regel Schaltungsvorschläge sowie Informationen enthalten sind, aus denen der Algorithmus der Programmierung hervorgeht. Also suchst Du nach

    Code
    DS18B20 Datenblatt


    oder

    Code
    DS18B20 datasheet

    Im Fall von 1wire wird eine Datei auf dem Raspberry Pi angelegt, die einfach nur ausgelesen zu werden braucht. Hier musst Du eigentlich nur wissen, wie die Datei denn heißt - und wie Dateien in C++ ausgelesen werden können. Hier wirst Du mit Stichworten wie

    Code
    C++ Dateien lesen Beispiel Code


    richtig weit kommen.

    Wenn Du die DeviceTrees deaktivierst (weitere Stchworte!), dann funktionieren auch Tutorials zum Auslesen der Temperatur mittels DS18B20, die vor Einführung der DeviceTrees geschrieben wurden (Kenel 3.12 ohne DeviceTrees, Kernel 3.18 mit DeviceTrees).

    Hier gibt es ein berühmtes Tutorial, dass Du so suchst

    Code
    Raspberry Pi Device Tree Tutorial raspiprojekt


    und finden wirst.

    Dann noch einen Tipp: Bevor ich an die Programmierung in einer Hochsprache herangehe, überzeuge ich mich durch simple Linux-Kommandos, ob der Sensor überhaupt irgendwas macht, das sich einer späteren Programmierung erschließt. Hier würde ich so suchen

    Code
    Raspberry Pi DS18B20 bash Skript Pipe


    Hier findest Du u.a. eine soge. Pipe (Einzeiler, den Du in der Konole eingeben kannst), um Dich davon zu überzeugen, dass der Sensor
    a) richtig angeschlossen ist
    b) mit Strom versorgt wird
    c) die Datei erzeugt
    d) eine plausible Temperatur anzeigt (halte mal die Finger an den Sensor - die Temperatur wird steigen)
    Die Pipe lässt sich übrigens auch in C++ einsetzen - so Du es möchtest.

    Da der Temperatursensor DS18B20 abfragemäßig identisch mit DS1820 ist, kannst Du auch nach diesen Sensor analog suchen.


    Beste Grüße

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Habe unter erweitert mit 1-wire und "andere Programmiersprachen" gesucht.

    Ja, die Suchparameter, di müssen passen. Meine Suche war wohl :(

    Mit googel habe ich schon nach

    -raspberry 1-wire c++
    -1-wire mit c++ auslesen c++
    -1 wire raspberry cpp
    DS1820 auslesen raspberry c++

    und vieles andere gesucht. Im forum hier hatte ich nur wie bereits geschrieben mit 1-wire und andere Programmiersrachen gesucht.

    Einmal editiert, zuletzt von martin66119 (27. Mai 2015 um 12:03)

  • Hallo Martin,


    ...
    Der Code, den ich auf der Seite
    http://bradsrpi.blogspot.de/2013/12/c-prog…ure-from-1.html
    ...


    also ich kann in dem Code aus dem Link jetzt keinen gröberen Fehler finden und dei Warnung kannst Du, wie Andreas schon schrieb, ignorieren.
    Das Einzige, was mir aufgefallen ist, ist die Tatsache, dass der Autor des C-Programms voraussetzt, dass die Sensor-Einträge alle mit "28-" beginnen - das muss nicht unbedingt sein.
    Änder das halt mal ab und probier's dann einfach noch mal.
    cu,
    -ds-

  • Einen schönen guten Abend.

    Habe im Forum nochmals gesucht und folgendes gefunden. Wenn ich diesen mit geany als c++ compiliere und ausführe, dann wird ca. jede sekunde ein Wert ausgegeben. z.B. 38,xx usw obwohl ich keinen DS1820 angeschlossen habe.

    Kann ich mit einem Befehl prüfen, ob ein Sensor richtig angeschlossen ist und der Wert korrekt ausgegeben wird.


    #include <iostream>
    #include <fstream>
    #include <string>
    #include <stdlib.h>
    using namespace std;


    /* Entry Point */
    int main (int argc, char **argv)
    {
    ifstream datei;
    int temperatur;
    float variable1;
    string text;
    int abort = 0;

    while ((abort != 1))
    {
    datei.open("/sys/class/thermal/thermal_zone0/temp", ios::in);
    if ((datei.fail()))
    {
    cout << "Konnte datei nicht öffnen!";

    /* Man könnte hier auch break nehmen um die schleife abzubrechen. */
    /* break; */
    return 0;
    }

    /* Zeiger Position immer auf 0, wir haben nur eine Zeile zum lesen ... */
    datei.seekg (0, datei.beg);

    getline(datei, text);

    temperatur = atoi(text.c_str());

    variable1 = ((float)temperatur) / 1000.0f;

    /* Wenn er hier keine nach Komma stellen anzeigt, versucht */
    /* printf("%f\n", variable1); */

    cout << variable1 << "\n";

    datei.close();

    sleep(1);
    }

    /* Mit break geht es hier weiter mit der ausführung. */

    //::getchar();

    return 0;
    }

    Habe noch was vergessen:
    Entsprechend der Seite http://www.kompf.de/weather/pionewiremini.html
    habei ich folgendes noch gemacht:

    Folgendes ergänzt:

    /boot/config.txt : dtoverlay=w1-gpio,gpiopin=4,pullup=on

    # /etc/modules:
    w1-gpio pullup=1
    w1-therm

    Einmal editiert, zuletzt von martin66119 (27. Mai 2015 um 22:48)

  • Wenn Du mal die Suchmaschine Deines Vertrauens mit

    Code
    /sys/class/thermal/thermal_zone0/temp


    fütterst, wirst Du feststellen, dass es sich dabei um die Temperatur der CPU handelt ... also nix mit einem Dallas-Teil zu tun hat.
    Du kannst nachschauen, ob Du unter

    Code
    pi@raspberrypi ~ $ ls -l /sys/bus/w1/devices/
    28-000006462371/ 28-0000064713ea/ 28-000006474dd8/ 28-0000064823bd/
    28-00000646b132/ 28-000006473adb/ 28-00000647545e/ w1_bus_master1/
    28-00000646c420/ 28-000006474b19/ 28-00000647ab89/ 
    pi@raspberrypi ~ $ ls -l /sys/bus/w1/devices/


    diverse Sensoren angezeigt bekommst ... eine andere Methode festzustellen, ob der/die Sensor(en) richtig angeschlossen ist/sind kenne ich jetzt nicht.
    Im obigen Fall habe ich einen Verteiler mit 10 DS18B20-Sensoren angeschlossen, die auch brav erkannt werden.
    Mit z.B. (in meinem Fall)

    Code
    pi@raspberrypi ~ $ cat /sys/bus/w1/devices/28-0000064823bd/w1_slave 
    8d 01 4b 46 7f ff 03 10 03 : crc=03 YES
    8d 01 4b 46 7f ff 03 10 03 t=24812
    pi@raspberrypi ~ $


    bekommst Du die Temperatur angezeigt ... und nichts anderes macht auch das C-Programm.

    cu,
    -ds-

  • Guten Morgen,

    so, nun habe ich 2 DS1820 angesteckt und unter /sys/bus/w1/devices/ nachgeschaut.
    Da sind nun 3 Ordner. Diese haben folgende Bezeichnung

    28-000003aa64a7
    28-000003c06b4e
    w1_bus_master1

    Wenn ich nun z.B. den Ordner 28-000003aa64a7 öffne sind in diesem wieder folgende Ordner bzw. Dateien enthalten.

    Driver
    power
    subsystem

    id
    name
    uevent
    w1_slave

    Wenn ich nun die Datei w1_slave mit leafpad öffnet stehen da zwei Zeilen drin, die inhaltlich so ausschauen:

    8d 01 4b 46 7f ff 03 10 03 : crc=03 YES
    8d 01 4b 46 7f ff 03 10 03 t=24812

    Und nun zum guten Schluss.

    Wenn ich nun das Programm starte wird 0.007 angezeigt (den Pfad auf die richtige Datei habe ich, ich hoffe, korrekt geändert). Also nicht die Temperatur der von einem sensor gemessen wird. Was ist denn da falsch?

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <stdlib.h>
    using namespace std;


    /* Entry Point */
    int main (int argc, char **argv)
    {
    ifstream datei;
    int temperatur;
    float variable1;
    string text;
    int abort = 0;

    while ((abort != 1))
    {
    datei.open("/sys/bus/w1/devices/28-000003aa64a7/w1_slave", ios::in);
    if ((datei.fail()))
    {
    cout << "Konnte datei nicht öffnen!";

    /* Man könnte hier auch break nehmen um die schleife abzubrechen. */
    /* break; */
    return 0;
    }

    /* Zeiger Position immer auf 0, wir haben nur eine Zeile zum lesen ... */
    datei.seekg (0, datei.beg);

    getline(datei, text);

    temperatur = atoi(text.c_str());

    variable1 = ((float)temperatur) / 1000.0f;

    /* Wenn er hier keine nach Komma stellen anzeigt, versucht */
    /* printf("%f\n", variable1); */

    cout << variable1 << "\n";

    datei.close();

    sleep(1);
    }

    /* Mit break geht es hier weiter mit der ausführung. */

    //::getchar();

    return 0;
    }

  • Hallo nochmal,

    da ich nun weiß, wo die Temperatur steht, stellt sich natürlich die Frage, wie ich diese am besten/einfachsten auslesen kann.

    Da ich noch nicht viel programmiert habe fällt mir nur ein.

    while(!datei.eof())
    {

    getline(datei,zeile)

    Im String Zeile den teilstring "t =" suchen
    wenn gefunden dann Position und länge des String ermitteln
    Teilstring ab dieser Position bis zum ende in Hilfsstring kopieren
    Hilfsstring in float wandeln und diesen durch 1000 teilen.

    }

    oder gibt es einen besseren und einfacheren weg?

    vielleicht zeile 1 und zeile 2 in einen String zusammenführen und dann zuerst schauen ob CRC einen gültigen wert anzeigt

    Grüße
    Martin

  • Hallo Martin,

    es geht einfcher:

    Du weißt, dass die Datei immer nur zwei Zeilen hat. Dann geht das so:
    1. Datei zum Lesen öffnen
    2. Erste Zeile auslesen und auf Inhalt YES prüfen
    3. Wenn kein YES dann 5.
    4. Zweite Zeile auslesen und alles hinter t= in eine Fließpunktzahl wandeln
    5. Datei schließen

    Das gleiche für den nächsten Sensor wiederholen. Das bedeutet, dass sich in Deine Fall eine Funktion anbietet, der der Dateiname übergeben wird, die durch den 1Wire-Sensor erzeugt wird. Bei Einsatz einer Funktion zum Auslesen hättest Du dann noch
    6. Temperatur als Fließpunktzahl zurückgeben.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (28. Mai 2015 um 14:27)

  • Guten abend,

    ich finde leider nicht den passenden Befehl in c++ um aus dem String

    8d 01 4b 46 7f ff 03 10 03 t=24812

    ab der Postion t=
    bis ans ende des strings alles in einen neuen String zu kopieren.

    StringNeu = 24812

    Welchen befehl gibt es denn da

    Danke bereits jetzt für die Hilfe

    Martin

    Juchhu!!

    gefunden.

    teilstr= substr("pos");

    Einmal editiert, zuletzt von martin66119 (28. Mai 2015 um 21:57)

  • Guten Morgen,

    nun komme ich nicht mehr weiter.

    Wie lese ich denn alle Dateinamen ein, die von den 1wire erezugt werden, damit ich dann die Temperaturen auslesen kann. Es kann ja nur ein 1wire oder auch 12 eingesteckt sein.

    Hoffe jemand hat eine Beispielcode, den ich verwenden kann.

    Auf jedenfall schoneinmal Danke

    Martin

  • Hallo Martin,

    eine Möglichkeit besteht darin eine Pipe zu öffnen, die Dir mittels Befehl dir den Inhalt des Verzeichnisses ausgibt, in dem die auszuwertenden Sensor-Dateien liegen.

    Falls Du nicht weißt, was eine Pipe ist, dann hilft Dir die Suchmaschine Deines Vertrauens weiter.

    Die Pipe musst Du dann auslesen, wie eine normale Datei. Jede Zeile der Pipe enthält den Dateinamen, der mit Deinem Programm ausgelesen wird.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Hallo,

    hier der Code den ich zusammengebastelt habe. Teile hier aus dem Forum und andere Teile irgendwo aus dem Netz.

    Im Moment habe ich zwei Sensoren an dem RPI dran. Wenn ich im betreffenden Ordner die Ordnernamen auslese erhalte ich folgendes.

    w1_bus_master1
    28-000003c06b4e
    28-000003aa64a7

    Ich muss also in einer Schleife

    datei.open("/sys/bus/w1/devices/28-000003aa64a7/w1_slave", ios::in);

    den jeweiligen Ordner öffnen.
    Wie mache ich das wenn ich nicht weiß ob es 2, 3 oder vielleicht 10 1wire sind die Temperatren lBeginnen die Dateien immer mit 28- . Lege ich den Namen dann in ein Array oder eine Liste. Wie legt man eine Liste an? Ist mein Code zum auslesen soweit ok?

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <stdlib.h>
    #include <cstdio>
    #include <dirent.h>

    using namespace std;


    /* Entry Point */
    int main (int argc, char **argv)
    {
    ifstream datei;
    int temperatur;
    int gefunden;
    float variable1;
    string teilstring;
    string text;

    int abort = 0;

    while ((abort != 1))
    {
    datei.open("/sys/bus/w1/devices/28-000003aa64a7/w1_slave", ios::in);
    if ((datei.fail()))
    {
    cout << "Konnte datei nicht öffnen!";

    /* Man könnte hier auch break nehmen um die schleife abzubrechen. */
    /* break; */
    return 0;
    }

    /* Zeiger Position immer auf 0, wir haben nur eine Zeile zum lesen ... */
    datei.seekg (0, datei.beg);
    while(!datei.eof())
    {
    getline(datei, text);
    gefunden = text.find("YES",0);
    if (gefunden >0)
    {
    getline(datei,text);
    gefunden = text.find("t=",0);
    teilstring = text.substr(gefunden+2);
    temperatur = atoi(teilstring.c_str());
    variable1 = ((float)temperatur) / 1000.0f;
    cout << variable1 << "\n";
    }
    }
    datei.close();
    sleep(1);
    char pfad[] = "/sys/bus/w1/devices/";
    DIR *verzeichnis;
    struct dirent *dateien;
    verzeichnis = opendir(pfad);
    while(dateien = readdir(verzeichnis))
    {
    cout << dateien->d_name << endl;
    }

    }
    //::getchar();

    return 0;
    }

  • Hallo Martin,

    mit Pipe zum Auslesen eines Verzeichnisses meinte ich eigentlich sowas hier:

    Code
    #Icon-Code
    procedure main()
    	pfad := "/sys/bus/w1/devices/"
    	sensoren := []
    	if pipe := open("ls " || pfad, "p") then
    	{	while put(sensoren, read(pipe))
    		close(pipe)
    	}
    	every write(sensoren[1 to *sensoren])
    end

    In der Liste [font="Courier"]sensoren[/font] befinden sich dann die Namen der Sensoren, die erkannt wurden. In den dort erhaltenen Verzeichnissen kannst Du dann in [font="Courier"]w1_slave[/font] nach Messwerten schauen.

    Dann ist es vollkommen egal, wie die Sensoren sich im System anmelden - oder wie viele es jetzt sind.

    Denn sowas wie

    Code
    datei.open("/sys/bus/w1/devices/28-000003aa64a7/w1_slave", ios::in);


    ist kein guter Programmierstil. Für kleine Übungen ist das ganz ok. Aber wenn Du in einem halben Jahr einen Sensor austauschst, dann geht das Gesuche und Gefrage wieder los.

    Mein Beispielcode oben liest die Dateien aus, die sich im Verzeichnis [font="Courier"]pfad[/font] befinden. Jeder gefundene Eintrag (Verzeichnis mit der ID des Sensors) wird in der Liste [font="Courier"]sensoren[/font] abgelegt. Anschließend wird die Liste ausgegeben.

    Du brauchst jetzt lediglich Pfad und jeden Listen-Eintrag aneinander zu hängen, um den Dateinamen zu erhalten, in dem sich die Messwerte des betreffenden Sensors befinden.

    Beste Grüße

    Andreas

    Hallo Martin,

    mit Pipe zum Auslesen eines Verzeichnisses meinte ich eigentlich sowas hier:

    Code
    procedure main()
    	pfad := "/sys/bus/w1/devices/"
    	sensoren := []
    	if pipe := open("ls " || pfad, "p") then
    	{	while put(sensoren, read(pipe))
    		close(pipe)
    	}
    	every write(sensoren[1 to *sensoren])
    end

    In der Liste [font="Courier"]sensoren[/font] befinden sich dann die Namen der Sensoren, die erkannt wurden. In den dort erhaltenen Verzeichnissen kannst Du dann in [font="Courier"]w1_slave[/font] nach Messwerten schauen.

    Dann ist es vollkommen egal, wie die Sensoren sich im System anmelden - oder wie viele es jetzt sind.

    Denn sowas wie

    Code
    datei.open("/sys/bus/w1/devices/28-000003aa64a7/w1_slave", ios::in);


    ist kein guter Programmierstil. Für kleine Übungen ist das ganz ok. Aber wenn Du in einem halben Jahr einen Sensor austauschst, dann geht das Gesuche und Gefrage wieder los.

    Mein Beispielcode oben liest die Dateien aus, die sich im Verzeichnis [font="Courier"]pfad[/font] befinden. Jeder gefundene Eintrag (Verzeichnis mit der ID des Sensors) wird in der Liste [font="Courier"]sensoren[/font] abgelegt. Anschließend wird die Liste ausgegeben.

    Du brauchst jetzt lediglich Pfad und jeden Listen-Eintrag aneinander zu hängen, um den Dateinamen zu erhalten, in dem sich die Messwerte des betreffenden Sensors befinden.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (31. Mai 2015 um 18:08)

  • Hi,

    ich bin auch gerade dabei mir da was zu basteln. Die Fühler IDs lese ich mir im moment so aus


    Weiter bin ich auch noch nicht. Als nächtes wollte ich die Printausgabe in eine Variable speichern und damit die Datei öffnen.

    Einmal editiert, zuletzt von mr-brain (31. Mai 2015 um 18:18)

  • Hallo mal wieder, hallo mr-brain,

    zu deinem Code habe ich mal eine Frage!

    In der Zeile

    dirHandle = opendir("/sys/bus/w1/devices");

    möchte ich gerne "/sys/bus/w1/devices"

    durch eine Variable ersetzen.
    Wenn ich nun



    //Edit by trek_star: Hab die Schrift mal Minimal verkleinert ;)

    Einmal editiert, zuletzt von Alex (5. Juni 2015 um 10:41)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!