ESP8266, DS18B20 Speichern von Adressen und Namen zur Wiederverwendung

Guten Morgen!
Mein erster Post hier im Forum und ich hoffe ich bin auch an der richtigen Stelle. Ich möchte das Rad nicht unbedingt neu erfinden und habe (erstmal) eine "Konzeptfrage". Wenn es dann an die Programmierung geht werde ich sicher weitere Nachfragen haben.

Ich möchte gerne eine Software schreiben, mit der ich an einem ESP8266 bis zu 10 DS18B20 Sensoren ansprechen kann. Ich habe schöne Beispiele gefunden, die ich auch soweit ans Laufen gebracht habe, aber ich habe ein Problem: Die Sensoren kann ich zwar über die Position am Bus ansprechen, wenn aber mal einer Kaputt geht, würde sich die Reihenfolge ändern und ich müsste umprogrammieren. Viel sicherer erscheint es mir, wenn ich die Sensoren über ihre Adresse anspreche. Die steht aber leider nicht an den Sensoren dran und jedesmal wenn ein Sensor getauscht wird gleich ein neues Sketch zu schreiben in das ich die Sensoradresse fix abspeicher ist irgendwie auch blöde.
Meine Idee war es also eine Datei im SPIFFS abzulegen, die die Adresse und einen "sprechenden Namen" dazu abspeichert, also etwas wie:

"0x28, 0xff, 0x07, 0x6f, 0x30, 0x17, 0x04, 0x0e" , "Temperatur Oben";
"0x28, 0xff, 0x07, 0x6f, 0x30, 0x17, 0x04, 0x1e" , "Temperatur Unten";

Diese Datei müsste ich dann öffnen, die Werte auslesen, in ein mehrdimensionales Array (oder zwei eindimensionale) packen und dann in der Anwendung weiterverarbeiten.

Ist dieser Ansatz prinzipiell sinnvoll, oder gibt es bessere Methoden so etwas zu "regeln".
Danke schön :slight_smile:
LG Thomas

Da es hier um einen ESP8266 wäre ne kleine Webpage mit den "allen" aktuellen Adressen anzeigen lassen und die entsprechende Zuordnung darunter. tauscht du jetzt einen der Sensoren hast du in der Übersicht eine Adresse die noch nicht zugeordnet ist. Diese kannst du dann in der Zuordnung speichern und schon ist alles gut.
Funktioniert aber nur solange du nur einen Sensor auf einmal tauscht bzw hinzufügst.

Das wäre meine herangehensweise.

Evtl. den Webserver nur über einen Hardware Pin aktivieren damit er nicht die ganze Zeit läuft

Gruß
DerDani

Tommylicious1980:
....und jedesmal wenn ein Sensor getauscht wird gleich ein neues Sketch zu schreiben in das ich die Sensoradresse fix abspeicher ist irgendwie auch blöde.
Meine Idee war es also eine Datei im SPIFFS abzulegen, die die Adresse und einen "sprechenden Namen" dazu abspeichert, also etwas wie:

Die Adressen im Spiffs abzulegen halte ich nicht für sinnvoll, die Dinger gehen nicht ständig kaputt. Ich habe 5 Stück am Pufferspeicher und Festbrennstoffkessel verteilt. Die liefern seit 2017 kontinuierlich Messwerte.

Die Ds18b20 über die Adressen anzusprechen, erachte ich bei mehr als 2 Stück im Sketch als sinnvoll.
Eine neue Adresse ist schnell mal in den Sketch geschrieben.

Tommylicious1980:
Diese Datei müsste ich dann öffnen, die Werte auslesen, in ein mehrdimensionales Array (oder zwei eindimensionale) packen und dann in der Anwendung weiterverarbeiten.

Im Heizungsraum habe ich es ohne Namenszuordnung gemacht.

const byte ONE_WIRE_PIN = D6;     // Pin für Ds18b20 einstellen
DeviceAddress sensor[] = { {0x28, 0xFF, 0xF6, 0x1E, 0x81, 0x16, 0x04, 0xB1} , {0x28, 0xFF, 0x2E, 0x17, 0x81, 0x16, 0x04, 0x42} ,
  {0x28, 0xFF, 0x29, 0x17, 0x81, 0x16, 0x04, 0x13} , {0x28, 0xFF, 0x03, 0x18, 0x81, 0x16, 0x04, 0xCC} , {0x28, 0xFF, 0xEA, 0x8C, 0x30, 0x17, 0x04, 0xD9}
};  //Speicher Rücklauf, Kessel, Warmwasser, Speicher Vorlauf, Haus Vorlauf

temp[i] = DS18B20.getTempC(sensor[i]);

Hier noch ein Beispiel mit Array für Adresse und Name.

const uint8_t ONE_WIRE_Bus = 12;
DeviceAddress sensor[] = { {0x28, 0xff, 0x33, 0x10, 0x81, 0x16, 0x04, 0x54},
  {0x28, 0xff, 0x07, 0x6f, 0x30, 0x17, 0x04, 0x2e},  {0x28, 0xff, 0x13, 0x6e, 0x30, 0x17, 0x04, 0x2e}
};
const char* dsname[] = {"IN", "OUT", "Solar", "Speicher", "Vorlauf", "Rücklauf"};

Gruß Fips

Mir sind tatsächlich schon Sensoren kaputt gegangen :smiley: Aber ich werde mir die Beispiele mal genauer ansehen. Danke schön :slight_smile:

Die Zuordnung über eine kleine Webseite habe ich mir genau so vorgestellt, nur eben dass die Adresse mit dem Namen zusammen abgespeichert wird.

Ich denk mal ein bisschen drauf rum :slight_smile:

Interessieren würde es mich aber schon wie ich Daten aus so einer Datei lesen könnte. Und die dann in einem Array zusammen mit den Namen speichern.. Datentypen mischen geht ja eher nicht so wie ich es mal gelebt habe.

Dann schau Dir mal struct an und Arrays davon.

struct myDS18B20 {  // beide zusammen sollten auf dem ESP8266 eine durch 4 teilbare Summe ergeben
  byte  adresse[8];  // die Adresse war nach meiner Erinnerung 8 Byte lang, sonst korrigieren
  char name[12]; // 11 Nutzzeichen + '\0'
};

myDS18B29 meineSensoren[8]; // für 8 Sensoren

Wie Du das initialiseren kannst, da gibt es viele Beispiele, sonst nochmal fragen.

Gruß Tommy

Tommy56:
byte adresse[8]; // die Adresse war nach meiner Erinnerung 8 Byte lang, sonst korrigieren

Die Lib bringt da schon was mit.

Nur nutzt es meist keiner.

Genau wie!

Gruß Fips

Und wo wird da die Verknüpfung mit dem Namen der Messtelle gespeichert? Darum ging es ja gerade in der Anfrage.

Gruß Tommy

Tommy56:
Und wo wird da die Verknüpfung mit dem Namen der Messtelle gespeichert? Darum ging es ja gerade in der Anfrage.

Gruß Tommy

struct myDS18B20 {
  DeviceAddress  adresse;  // so meinte ich das
  char name[12];

myDS18B29 meineSensoren[8]; // für 8 Sensoren

Gruß Fips

Dann schreibe das doch auch. :wink:
Vorm 2. Kaffee bin ich noch nicht so gut im Rätselraten.

Gruß Tommy

Guten Morgen :slight_smile:
Also ich habe mir die ganzen Beispiele und wirklich guten Anregungen durchgelesen. Ich bin mittlerweile so weit, dass ich immer besser verstehe wie das alles funktioniert und habe auch schon die ersten Ideen umgesetzt.
Danke für die großartige Unterstützung!

Im Moment bin ich an einem Problem, was weiterhin die Adressen betrifft. Die "DeviceAddress" ist ja nichts anderes als ein Byte Array mit 8 "Plätzen".

 byte array[8] = {0x28, 0x9D, 0x09, 0x52, 0x04, 0x00, 0x00, 0x57};
 
 //array[0] =  0x28; -> byte 1
 //array[1] = 0x9D; -> byte 2 usw.

Ich möchte jetzt diese Adresse in einer Variable vom Typ char speichern, weil ich diese Adresse dann im weiteren Programmverlauf verwenden möchte.

Ich weiß, dass ich mit einer kleinen Schleife, das Array auslesen kann um die Daten nach und nach zum Beispiel an der Seriellen Schnittstelle auszugeben.

for (uint8_t t = 0; t < 8; t++)
  { 
    Serial.print(tempDeviceAddress[t], HEX);           // Aus '0x28' wird '28'                  
 
  }

Um jetzt aber die Ausgabe in einem char adresse[17] zu speichern fehlt mir richtige Ansatz... (Ich habe char mit der größe 17 definiert, weil ich die 16 mit der Adresse füllen möchte, also ohne "0x" und Kommata. Wenn das die Sache unnötig kompliziert macht, dann kann ich den Wert ja auch entsprechend speichern, aber es geht mir erstmal um das Prinzip an sich.

Ich habe ein Beispiel gefunden, aber ich muss sagen, ich verstehe nicht was da passiert, und ich bin mir nicht so richtig sicher, ob es nicht einen einfacheren Weg gibt. Hier mal das was ich gefunden habe:

void array_to_string(byte array[], unsigned int len, char buffer[])
{
    for (unsigned int i = 0; i < len; i++)
    {
        byte nib1 = (array[i] >> 4) & 0x0F;
        byte nib2 = (array[i] >> 0) & 0x0F;
        buffer[i*2+0] = nib1  < 0xA ? '0' + nib1  : 'A' + nib1  - 0xA;
        buffer[i*2+1] = nib2  < 0xA ? '0' + nib2  : 'A' + nib2  - 0xA;
    }
    buffer[len*2] = '\0';
}

Mir ist klar: Ich übergebe ein Array, die Länge des Arrays ( was ja auch klar ist um die einzelnen Bytes auszulesen und den Puffer in den das ganze geschrieben wird.
str ist hier ein String, deswegen wird er am Ende auch mit \0 terminiert.

Soweit so klar und das ganze für char anzupassen, im schlimmsten Fall zu konvertieren ist sicher nicht das Problem.

So wie ich es interpretiere werden die Bytes des Arrays in diesem Beispiel als Binärcode behandelt (... also quasi die "Urform")
Ich definiere nib1 und nib2... und dann lese ich für mich total verwirrende Verschiebeoperationen und Zuweisungen :smiley:

Ich möchte die Adresse des Sensors in einer Protokollnachricht verschicken und benötige sie daher in einer gut lesbaren Form.

Ich überlege gerade, ob sowas nicht funktioniert:

char puffer[17];
sprintf(puffer,"%02X %02X %02X %02X %02X %02X %02X %02X",Temp1[0],Temp1[1],Temp1[2],Temp1[3],Temp1[4],Temp1[5],Temp1[6],Temp1[7]);

Das ist auch so ein Beispiel, das ich bei der Forumssuche gefunden habe, allerdings ist mir diese Formatangabe neu und ich habe auch noch keine Dokumentation dafür gefunden.

  DeviceAddress sensor[] = { {0x28, 0xFF, 0xF6, 0x1E, 0x81, 0x16, 0x04, 0xB1} , {0x28, 0xFF, 0x2E, 0x17, 0x81, 0x16, 0x04, 0x42} ,
    {0x28, 0xFF, 0x29, 0x17, 0x81, 0x16, 0x04, 0x13} , {0x28, 0xFF, 0x03, 0x18, 0x81, 0x16, 0x04, 0xCC} , {0x28, 0xFF, 0xEA, 0x8C, 0x30, 0x17, 0x04, 0xD9}
  };  //Rücklauf, Kessel, Warmwasser, Speicher Vorlauf, Haus Vorlauf

  char schick[47];
  for (auto h : sensor) {
    snprintf(schick, sizeof(schick), "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}\n", h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]);
    Serial.printf("%s\n", schick);
  }

Ausgabe:

0x28, 0xff, 0xf6, 0x1e, 0x81, 0x16, 0x04, 0xb1
0x28, 0xff, 0x2e, 0x17, 0x81, 0x16, 0x04, 0x42
0x28, 0xff, 0x29, 0x17, 0x81, 0x16, 0x04, 0x13
0x28, 0xff, 0x03, 0x18, 0x81, 0x16, 0x04, 0xcc
0x28, 0xff, 0xea, 0x8c, 0x30, 0x17, 0x04, 0xd9

printf, sprintf, snprintf

Gruß Fips

Das ist alles was ich wissen wollte glaube ich, gutes Beispiel um auch mit etwas komplexeren Sachen zurecht zu kommen, ohne gleich erschlagen zu werden. Danke