OneWire Sensoren Dynamisch abfragen und Temperatur zuordnen

Hallo Gemeinde,
In der suche bin ich nicht Fündig geworden was die Abfrage der OneWire (DS18B20) Sensoren angeht. Daher wende ich mich hier an die Forum Mittglieder die sicherlich mehr erfahrung haben in diesem Tehma.

Ich scanne die Sensoren ein was auch funktioniert

 OneWire oneWire(oneWireBus);
 DallasTemperature sensors(&oneWire);
 DeviceAddress tempDeviceAddress; // Variable für die Sensor-ID

void scanOneWireSensors() {
 int deviceCount = sensors.getDeviceCount();
  Serial.printf("Gefundene OneWire-Sensoren: %d\n", deviceCount);
  
  // Begrenze die Anzahl auf maximal 5 Sensoren
  int sensorLimit = (deviceCount < 5) ? deviceCount : 5;
  
  // Falls du nur einen Sensor anzeigen willst (oder mehrere, dann ggf. zusammenfügen):
  for (int i = 0; i < sensorLimit; i++){
    DeviceAddress deviceAddress;
    String sensorID = "";
    
    if (sensors.getAddress(deviceAddress, i)){
      for (uint8_t j = 0; j < 8; j++){
        if (deviceAddress[j] < 0x10) sensorID += "0";
        sensorID += String(deviceAddress[j], HEX);
      }
      sensorID.toUpperCase();
    }
    else {
      sensorID = "NotFound";
    }
    
    // Setze das .txt-Feld auf einen festen Text, z.B. "Sensor ID"
    sendToNextion("cb_owID", "Sensor ID");
    
    // Aktualisiere das .path-Feld direkt – analog zum WLAN-Beispiel:
    String cmd = "cb_owID.path=\"" + sensorID + "\"" + END_CHAR;
    Serial1.print(cmd);
    Serial.println("Gesendete Sensor-ID: " + sensorID);
 }
 }
 // Konvertiert die Sensoradresse in eine lesbare ID
  String getSensorID(DeviceAddress deviceAddress) {
    String id = "";
    for (uint8_t i = 0; i < 8; i++) {
        if (deviceAddress[i] < 16) id += "0";
        id += String(deviceAddress[i], HEX);
    }
    return id;
 }

danach frage ich am Nextion nach die ID der Sensoren, was auch soweit klappt

Aber da scheitert es dann an der zuordnung der Temp. zu dem jeweiligen Sensor. Da er immer nur den ersten Sensor abfragt.

void getTemperatureForID(String sensorID) {
    Serial.println("Starte Temperaturabfrage...");

    // Temperaturabfrage durch die neue Funktion
    float tempC = getTemperature(0);  // Temperatur des ersten Sensors holen

    // Debug-Ausgabe vor der Bedingung
    Serial.println("Abfrage abgeschlossen, Wert erhalten: ");
    Serial.println(tempC);  // Ausgabe des gemessenen Temperaturwerts

    if (tempC != DEVICE_DISCONNECTED_C) {
        // Wenn der Sensor verbunden ist, den Wert ausgeben und ans Nextion senden  "When the sensor is connected, output the value and send it to the Nextion"
        Serial.print("Sensor ID: ");
        Serial.print(sensorID);
        Serial.print(" - Temperatur: ");
        Serial.println(tempC);

        sendToNextion("t_temp", tempC);  // Temperatur an Nextion senden
    } else {
        // Fehlerbehandlung, falls der Sensor nicht verbunden ist  "Error handling if the sensor is not connected"
        Serial.println("Fehler: Sensor nicht verbunden oder Temperaturabfrage fehlgeschlagen");
    }
}

nun meine Frage wie kann ich das ganze Dynamisch machen, das er zu den gefundenen Sensoren auch die Temperatur abfragt.

21:40:43.571 -> Gefundene OneWire-Sensoren: 2
21:40:43.571 -> Gesendete Sensor-ID: 28EEBE5D2716017A
21:40:43.619 -> Gesendete Sensor-ID: 2869C87B0000006B

21:41:09.353 -> Empfangen: p2869C87B0000006B
21:41:09.353 -> Sensor ID: 2869C87B0000006B
21:41:09.353 -> Starte Temperaturabfrage...
21:41:09.432 -> Abfrage abgeschlossen, Wert erhalten: 
21:41:09.432 -> -1.50
21:41:09.432 -> Sensor ID: 2869C87B0000006B - Temperatur: -1.50

weil das ist die 2 te ID die er ausgibt, aber die Temperatur von Sensor 1. Richtig wäre Sensor-ID: 28EEBE5D2716017A - Temp: -1.50

kann mir da jemand vieleicht weiterhelfen das ich die Zuordnung hinbekomme?

Vielen Dank schon einmal

P.S.

Die zuornung soll dann so erfolgen und die werte an das ensprechende Feld auf dem Nextion gesendet werden

void temperatur() {
    // Beispiel: Temperaturabfragen für die Sensoren "Example: Temperature queries for the sensors"
    tempID1 = getTemperature(0);  // Temperatur des ersten Sensors
    tempID2 = getTemperature(1);  // Temperatur des zweiten Sensors
    tempID3 = getTemperature(2);  // Temperatur des dritten Sensors
    tempID4 = getTemperature(3); // Temperatur des vierten Sensors
    tempID5 = getTemperature(4);  // Temperatur des fünften Sensors

    // Umwandlung der Temperaturen in Strings
    String tempAStr = String(tempID1, 1);  // 1 Dezimalstelle
    String tempBStr = String(tempID2, 1);
    String tempSStr = String(tempID3, 1);
    String tempWTStr = String(tempID4, 1);
    String tempPStr = String(tempID5, 1);

    // Vergleichen, ob sich die Temperaturen geändert haben
    if (tempAStr != lastTempID1) {
        sendToNextion("t_atemp", tempAStr);  // Sendet als String
        lastTempID1 = tempAStr;  // Speichern der aktuellen Temperatur
    }
    if (tempBStr != lastTempID2) {
        sendToNextion("t_btemp", tempBStr);
        lastTempID2 = tempBStr;
    }
    if (tempSStr != lastTempID3) {
        sendToNextion("t_stemp", tempSStr);
        lastTempID3 = tempSStr;
    }
    if (tempWTStr != lastTempID4) {
        sendToNextion("t_wtemp", tempWTStr);
        lastTempID4 = tempWTStr;
    }
    if (tempPStr != lastTempID5) {
        sendToNextion("t_ptemp", tempPStr);
        lastTempID5 = tempPStr;
    }
}

Ich versteh Dein Problem nicht.
Was hindert Dich daran:

die sensorID zu benutzen?
Allerdings ist der ganze String-Kram komplett überflüssig und macht eher Probleme.

Hast Du das multiple-Example aus der dallas-temperatureLib mal angesehen?

hi my_x_y.

ich verstehe nicht ganz was du meinst, mit was hindert mich daran die id zu benutzen.

meinst du ich soll die ids fest vergeben und dann die temperatur dazu auslesen?

aber was ist wenn diese nicht bekannt sind. ich muss sie von aussen scannen können und dann zuordnen.
der gedanke ist also so, ich scanne die sensoren, suche mir den ersten aus der liste aus und bekomme dann die temperatur dazu angeigt, dann den 2ten bis hin zum 5ten. anhand der temperatur kann ich dann sagen welcher sensor wo verbaut ist. sind ja nicht alle temperaturen gleich, also sollte das machbar sein. oder es wird jeder nach und nach angesteckt und dann ausgelesen.

bezüglich der strings
das ist nicht so einfach, da die sensoren in eine combobox angezeigt werden als liste, geht das leider nur im txt format. daher das ganze als string. sorry ich hätte es auch lieber anderst, aber es ist nun mal das problem und du kannst es nicht einfach so mit covx ändern. ich wüsste nicht wie.

Ok dann kann ich es nicht abändern und muss so klarkommen ohne temperatur.

Aber danke für die Antwort

Ich glaub, Du machst Dir das alles viel zu schwer.

Es ist egal, was Du wie nachher auf dem Nextion darstellst. Die Texte in Strings zu wandeln ist nicht nötig.
Und schon gar nicht sind Strings bei der Verarbeitung der DS-Daten notwendig.

Mit Deinen Codefragmenten komme ich nicht weiter. Hast Du mal einen kompletten Sketch, aus dem ich was entwickeln kann?

glaube ich auch, aber ich lerne etwas dabei, wie es nicht geht oder gehen sollte. die umstellung von einer normalen sps auf den esp32 mit nextion ist schon eine herrausvorderung. bei der sps war es einfacher.*gg

Aber Danke noch einmal

Verstehe nicht so ganz was Du mit dynamisch abfragen meinst, aber im Beispiel oben übergibst Du zwar eine Sensor-ID

void getTemperatureForID(String sensorID)

fragst aber immer nur Sensor-ID 0 -> Sensor 1 ab.

float tempC = getTemperature(0)

Damit kommt nun mal immer die Temperatur von Sensor 1, egal was auch immer Du übergibst.

Also entweder Du ordnest Deine ermittelten ID 0 bis ... zu oder fragst eben direkt über die Adresse ab.

Was ist den einfacher als mit einem normalen Text Werte an das Display zu übergeben?
:astonished:
cu

Ich hab das mal zerlegt, was ich aus dem Code lese.
Du versendest die Adresse des Sensors / der Sensoren.
Warum machst Du das?
Und warum immer wieder?
Wenn Du die Zuordnung einer Temperatur zu einem Sensor haben willst, dann kannst Du die gesamte Handlung auf dem Controller machen und dann nur passend die zugehörige Temperatur zum Sensor übermitteln.
Dafür gibt es dann zwei Möglichkeiten:
a) Die eindeutige Kennung des Sensors benutzen
b) Das Th/TL-Byte des Sensors beschreiben und auswerten

Ersteres hat den Nachteil dass die Sensorkennung doch etwas länger ist.
Und die Kennung ändert sich, wenn der Sensor getauscht wird.
Mit b) vergibst Du dem Sensor eine eindeutige ID - fertig.
Ich hatte dazu mal eine Abhandlung.

Und wie dort schon beschrieben, werden Arrays genutzt und nicht durchgezählte Variablen.

Wenn ich nachher Zeit finde, schreib ich Dir das komplett um

ja wie gesagt ich steccke da nicht so tief drinne in der materie, hier nutze ich von esera den onwiere hup der auf tcp/ip geht. da macht das teil alles. aber da ich nun weg von dem system woll musste ich halt sehen wie ich es gebacken bekomme. es ist so wie ein klickibunti user ein linux bedienen will und doch scheitert bei den kleinen dingen. so geht es mir im moment. das mit der eigenen zuordnung wusste ich nicht. ich bin immer davon ausgegangen das jeder sensor seine eigene feste id hat und aus die maus.

ja das mit der abfrage ses ersten sensors das war ja die frage gewesen, wie ich es schaffe nicht nur die erste id abzufragen. ich schicke vom display bis zu 5 ids 123|234|567|845|438| diese sind durch | getrennt, der nano ordnet diese variablen id1-5 zu. wenn ich also den ersten sensor anklicke der ja id1 hat soll mir dazu die temperatur ausgegeben werden. dann kann ich diesen sensor auf dem display einer bezeichnung zu ordnen temp1 z.b oder temp2. das mache ich dann mit allen sensoren so. wenn das ganze fertig ist sage ich save und schicke diese liste wieder an den nano und er hat den richtigen sensor mit der richtige id an der richtigen stelle wo diese dann gebraucht wird, so war meine vorstellung.

Kannst Du mir mal diesen Sketch aufspielen, alle Sensoren anhängen und mal schauen, ob der Serielle monitor was ausgibt?

#include <OneWire.h>
#include <DallasTemperature.h>

constexpr byte oneWireBus {2};
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);

struct TempSensors
{
  DeviceAddress adress;
  uint8_t id;
  float value;
};
TempSensors tempSensors[]
{
  {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0.0},
  {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0.0},
  {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0.0},
  {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0.0},
  {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0.0},
};

const uint8_t tempDeviceCount = sizeof(tempSensors) / sizeof(tempSensors[0]);

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  initTempSensors();
}

void loop()
{}

void initTempSensors()
{
  sensors.begin();
  sensors.setWaitForConversion(true);
  sensors.requestTemperatures();
  uint8_t count = sensors.getDeviceCount();
  Serial.print(F("Gefundene Sensoren: "));
  Serial.print(count);
  if (count != tempDeviceCount)
  {
    Serial.println(F("count stimmt nicht!"));
    Serial.println();
    if (count > tempDeviceCount)
    { count = tempDeviceCount; }
  }
  sensors.setWaitForConversion(true);
  sensors.requestTemperatures();
  delay(1000); // Wait for once temperaturecall
  for (byte b = 0; b < count; b++)
  {
    sensors.getAddress(tempSensors[b].adress, b);
    tempSensors[b].id = sensors.getUserData(tempSensors[b].adress);
    tempSensors[b].value = sensors.getTempC(tempSensors[b].adress);
  }
  printSensorData();
}

void printSensorData()
{
  Serial.println(F("SensorDaten: "));
  for (byte b = 0; b < tempDeviceCount; b++)
  {
    Serial.print(F("Count: "));
    Serial.print(b);
    Serial.print(F(" ADR: "));
    for (byte c = 0; c < 8; c++)
    {
      Serial.print("0x");
      if (tempSensors[b].adress[c] < 0xF)
      { Serial.print(0); }
      Serial.print(tempSensors[b].adress[c], HEX);
    }
    Serial.print(F(" ID: "));
    Serial.print(tempSensors[b].id);
    Serial.print(F(" Temp: "));
    Serial.println(tempSensors[b].value);
  }
  Serial.println();
}

PIN 2 musst Du evtl. anpassen!

14:24:13.308 -> SensorDaten:

14:24:13.308 -> Count: 0 ADR: 0x280xEE0xBE0x5D0x270x160x010x7A ID: 70 Temp: 2.00

14:24:13.308 -> Count: 1 ADR: 0x280x690xC80x7B0x000x000x000x6B ID: 128 Temp: 25.00

14:24:13.308 -> Count: 2 ADR: 0x000x000x000x000x000x000x000x00 ID: 0 Temp: 0.00

14:24:13.308 -> Count: 3 ADR: 0x000x000x000x000x000x000x000x00 ID: 0 Temp: 0.00

14:24:13.308 -> Count: 4 ADR: 0x000x000x000x000x000x000x000x00 ID: 0 Temp: 0.00

14:24:13.308 ->

1 Like

Ok, 2 Sensoren :slight_smile:
Aussen und Innentemperatur?

der eine ist die aussen temperatur Nr.1 und der zweite ist fest verbaut auf der Platine, das die umgebungstemp. von der mcu.

Ok. Dann ist das richtig. Wieviele Sensoren schiebst Du zur Anzeige aufs Nextion?

ich habe die anzahl auf 5 begrenzt da nicht mehr sensoren gebraucht werden im normalfall.
Aussentemp, Beckentemp, Wärmetauscher, optional. Motortemp, und solarspeicher. das reicht eigendlich aus.

Kannst Du mal die Funktion tauschen und nochmal die Ausgabe zeigen?

void initTempSensors()
{
  sensors.begin();
  sensors.setWaitForConversion(true);
  sensors.requestTemperatures();
  uint8_t count = sensors.getDeviceCount();
  Serial.print(F("Gefundene Sensoren: "));
  Serial.print(count);
  if (count != tempDeviceCount)
  {
    Serial.println(F("count stimmt nicht!"));
    Serial.println();
    if (count > tempDeviceCount)
    { count = tempDeviceCount; }
  }
  sensors.setWaitForConversion(true);
  sensors.requestTemperatures();
  delay(1000); // Wait for once temperaturecall
  for (byte b = 0; b < count; b++)
  {
    sensors.setUserDataByIndex(b, b + 1);
    sensors.getAddress(tempSensors[b].adress, b);
    tempSensors[b].id = sensors.getUserData(tempSensors[b].adress);
    tempSensors[b].value = sensors.getTempC(tempSensors[b].adress);
  }
  printSensorData();
}

14:54:52.379 -> SensorDaten:

14:54:52.379 -> Count: 0 ADR: 0x280xEE0xBE0x5D0x270x160x010x7A ID: 1 Temp: 2.00

14:54:52.379 -> Count: 1 ADR: 0x280x690xC80x7B0x000x000x000x6B ID: 2 Temp: 24.00

14:54:52.379 -> Count: 2 ADR: 0x000x000x000x000x000x000x000x00 ID: 0 Temp: 0.00

14:54:52.379 -> Count: 3 ADR: 0x000x000x000x000x000x000x000x00 ID: 0 Temp: 0.00

14:54:52.379 -> Count: 4 ADR: 0x000x000x000x000x000x000x000x00 ID: 0 Temp: 0.00

14:54:52.379 ->

Jetzt siehst Du, was ich gemacht habe :slight_smile: Die ID ist jetzt IM Sensor gespeichert.
Jeder weitere Sensor könnte jetzt eine neue ID bekommen.
Mit dieser ID kannst Du dann weiter arbeiten. Nix mehr mit Adressen merken oder sonst was.
Denn wenn Du einen Sensor dazu baust, kann es Dir passieren, dass der INDEX für vorhandene Sensoren ein anderer wird. Die ID bleibt aber gleich.

Tauscht Du einen Sensor, sagst Du dem neuen nur, welcher er vorher war - und Du brauchst NIX am Code ändern.

Ok, dann bau ich nachher weiter.

ahh, also brauche ich dann wenn einmal ein sensor getauscht wird ihm nur sagen du hast jetzt diese nummer und er ist gleich an der richtigen stelle. verstehe ich das gerade richtig?

GENAU!
Ich hab doch gesagt, ich mach Dir das ganz einfach. :wink:

1 Like

Bei mir sieht das jetzt so aus:

#include <OneWire.h>
#include <DallasTemperature.h>
OneWire oneWire(4);  //GPIO Pin 1-Wire Bus
DallasTemperature sensors(&oneWire);

float tempDallas[10];
uint8_t sensorID[10][8] = {
{ 0x28, 0x61, 0x64, 0x35, 0xFA, 0x61, 0x80, 0xD8  },
{ 0x28, 0x61, 0x64, 0x35, 0xFB, 0xFD, 0x5B, 0x8A  },
{ 0x28, 0x61, 0x64, 0x35, 0xFA, 0x67, 0x60, 0x9B  },
{ 0x28, 0x61, 0x64, 0x35, 0xFA, 0x5D, 0xD0, 0x63  } };

void setup() {
Serial.begin(115200);
sensors.begin(); }

void loop() {
 sensors.requestTemperatures();
  for (int i=0; i<4; i++){
  tempDallas[i] = sensors.getTempC(sensorID[i]);
  Serial.print("S");   Serial.print(i+1);   Serial.print(":");
  Serial.print(tempDallas[i]);  Serial.print("ºC   ");
  }
  Serial.println("");
  delay(1000);
}

Und funktioniert. Im Moment habe ich 4 Sensoren angeschlossen. Die Adressen muss man natürlich vorher einzeln abfragen und irgendwo speichern.
P.S. Nein, stimmt nicht. Ich hab mir die Skripte von my_xy_projekt angesehen und da gibt es elegantere Methoden.


Hier noch ein Foto von meinen Sensoren. Die haben jetzt alle ein Nümmerchen eingraviert bekommen, damit ich sie den Adressen zuordnen kann.