Temperatursensor, Delay zu hoch.

Hallo, ich habe folgendes Problem, ich habe einen Temperatursensor in meinem Programm integriert und seit dem ist der delay zwischen 2 Abschnitte zu groß, wobei ich nicht mal z.b."delay(ms);" irgendwo stehen habe, deswegen gehe ich davon aus, dass es an der Library liegt. Ich würde jetzt gerne wissen, ob man die irgendwie abändern kann, wenn meine Vermutungen richtig sind. Vorab noch, wenn ich den Temperatur Part als einzige Funktion abspielen lasse, dann besteht der Delay auch. Hierzu mein verwendeter Part.

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
OneWire oneWire(9);
DallasTemperature sensors (&oneWire);
void setup() {
  sensors.begin();
  Serial.begin(9600);
  lcd.begin(20, 4);
}

void loop() {  
    sensors.requestTemperatures();
  float currentTemp0;
  currentTemp0 = sensors.getTempCByIndex(0);

Serial.print("Temp0 = ");
Serial.print("\t");
Serial.print(currentTemp0);
lcd.setCursor(0, 0);
lcd.print(currentTemp0);
}

diesen Teil habe ich nur implementiert, und seit dem gibts dieses delay Problem.

und seit dem gibts dieses delay Problem.

Das glaub ich dir nicht.

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
OneWire oneWire(9);
DallasTemperature sensors (&oneWire);

Ich seh da kein #include also gibts auch kein delay, denn so funktionierts garnicht.

Da du die Dallas Lib nutzt, vermute ich mal, das es sich um den DS18B20 oder S20 handelt. Im parasitären Betrieb braucht der mindestens 750ms Pause, bis der interne Kondensator für einen Messvorgang geladen ist. Wie diese Pause vorhanden ist, ist völlig egal. Du mußt als nicht zwingend per delay Pause machen, sondern nach dem Prinzip blink without delay mit millis eine Schleife laufen lassen, wo frühestens nach 750ms die Messung ausgelöst wird

Sorry mein Fehler, beim ganzen hin und her Ausschneiden und Einfügen, habe ich diese Zeile wohl im Eifer des erstellen dieses Beitrags übersprungen. Richtig würde es natürlich so aussehen:::

#include <DallasTemperature.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
OneWire oneWire(9);
DallasTemperature sensors (&oneWire);
void setup() {
  sensors.begin();
  Serial.begin(9600);
  lcd.begin(20, 4);
}

void loop() {  
    sensors.requestTemperatures();
  float currentTemp0;
  currentTemp0 = sensors.getTempCByIndex(0);

Serial.print("Temp0 = ");
Serial.print("\t");
Serial.print(currentTemp0);
lcd.setCursor(0, 0);
lcd.print(currentTemp0);

}

nix_mehr_frei

Im endgültigen Programm, würde ich aufm LCD in einer Art "Menü" hin und her wechseln, und bei diesem Vorgang stört die Verzögerung, aber wenn sich die immer auf der Tatsache beruht, dass der Kondensator vom Temperatursensor zu langsam aufläd, dann werde ich wohl mit der Verzögerung leben müssen. ._. Außer euch würde noch was einfallen, womit man die Verzögerung wenigstens fürs wechsel zu einem anderen Menüpunkt "überspringen" kann. Das wechseln zu den einzelnen Punkten habe ich über viele If schleifen gelöst, welche dann immer zu bedingen Werten erfüllt werden. Ich wechsel im Menü über das drehen eines verstellbaren Widerstand. Hier dann noch ein paar Auszüge dazu.

#include <DallasTemperature.h>
#include <LiquidCrystal.h>
#include <OneWire.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
OneWire oneWire(9);
DallasTemperature sensors (&oneWire);
void setup() {
  sensors.begin();
  Serial.begin(9600);
  
pinMode(13, OUTPUT);
pinMode(10, INPUT);
pinMode(9, INPUT);
pinMode(8, INPUT);
pinMode(7, INPUT);
pinMode(6, INPUT);

lcd.begin(20, 4);

}

void loop() {
  
// Vierter Punkt Links ------------------------------------------
if(analogRead(A0) < 1023 && analogRead(A0) > 850 ){


    lcd.setCursor(0, 0);
    lcd.print("Vierter Punkt Rechts");
      lcd.setCursor(0, 1);
      lcd.print("                    ");
          lcd.setCursor(0, 3);
          lcd.print("LINKS Drehen!       ");
}

// Dritter Punkt Recht ------------------------------------------
if(analogRead(A0) < 850 && analogRead(A0) > 750){


    lcd.setCursor(0, 0);
    lcd.print("Dritter Punkt Rechts");
      lcd.setCursor(0, 1);
      lcd.print("                    ");
          lcd.setCursor(0, 3);
          lcd.print("LINKS Drehen! RECHTS");
}

// Zweiter Punkt Rechts -----------------------------------------
if(analogRead(A0) < 750 && analogRead(A0) > 650){


    lcd.setCursor(0, 0);
    lcd.print("Zweiter Punkt Rechts");
      lcd.setCursor(0, 1);
      lcd.print("                    ");
          lcd.setCursor(0, 3);
          lcd.print("LINKS Drehen! RECHTS");
}
***************************************************
***************************************************
***************************************************
// Erster Punkt Rechts ------------------------------------------
if(analogRead(A0) < 650 && analogRead(A0) > 550){
  
  sensors.requestTemperatures();
  float currentTemp0;
  currentTemp0 = sensors.getTempCByIndex(0);
  Serial.print("Temp0 = ");
  Serial.print("\t");
  Serial.print(currentTemp0);
    lcd.setCursor(0, 0);
    lcd.print("Temperatur -A1 - -A3"); 
      lcd.setCursor(0, 1);
      lcd.print(currentTemp0);
         lcd.setCursor(5, 1);
         lcd.print("               ");
            lcd.setCursor(0, 2);
            lcd.print(" ");
                lcd.setCursor(0, 3);
                lcd.print("LINKS Drehen! RECHTS");
              
}
***************************************************
***************************************************
***************************************************

// Mitte des Menüs ----------------------------------------------
if(analogRead(A0) < 550 && analogRead(A0) > 450){


    lcd.setCursor(0, 0);
    lcd.print("    Erster Test!    ");
      lcd.setCursor(0, 1);
      lcd.print("Display Einstellung.");
          lcd.setCursor(0, 3);
          lcd.print("LINKS Drehen! RECHTS");              
}

// Erster Punkt Links -------------------------------------------
if(analogRead(A0) < 450 && analogRead(A0) > 350){
if(analogRead(A0) < 450 && analogRead(A0) > 350 && digitalRead(10) == 1){
digitalWrite(13, HIGH);

}
else
{ 
digitalWrite(13, LOW); 
}

    lcd.setCursor(0, 0);
    lcd.print(".Erster Punkt Links.");
      lcd.setCursor(0, 1);
      lcd.print(" Press -S1 to Laser ");      
          lcd.setCursor(0, 3);
          lcd.print("LINKS Drehen! RECHTS");
}

// Zweiter Punkt Links ------------------------------------------
if(analogRead(A0) < 350 && analogRead(A0) > 250){


    lcd.setCursor(0, 0);
    lcd.print("Zweiter Punkt Links.");
      lcd.setCursor(0, 1);
      lcd.print("                    ");     
          lcd.setCursor(0, 3);
          lcd.print("LINKS Drehen! RECHTS");
}

// Dritter Punkt Links ------------------------------------------
if(analogRead(A0) < 250 && analogRead(A0) > 150){


    lcd.setCursor(0, 0);
    lcd.print("Dritter Punkt Links.");
      lcd.setCursor(0, 1);
      lcd.print("                    ");      
          lcd.setCursor(0, 3);
          lcd.print("LINKS Drehen! RECHTS");
}

// Vierter Punkt Links ------------------------------------------
if(analogRead(A0) < 150 && analogRead(A0) > 0){


    lcd.setCursor(0, 0);
    lcd.print("Vierter Punkt Links.");
      lcd.setCursor(0, 1);
      lcd.print("                    ");      
          lcd.setCursor(0, 3);
          lcd.print("      Drehen! RECHTS");
}
}

Hier mal doch lieber das ganze bisherige Programm,
störender Teil durch Sternchen makiert.

Du musst den Temperatur-Sensor asynchron (nicht blockierend) abfragen.
Dann wird die Loop-Funktion weiterhin durchlaufen und man kann mit millis() auf das Ende der Konvertierungszeit warten.
Hier mal ein Beispiel:

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

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

uint32_t requestMillis = 0;
bool requestStarted = false;
const uint8_t bitResolution = 12;
const uint16_t ConvWait = 750;

void setup() {
  Serial.begin(115200);
  sensors.begin();
  sensors.setResolution(bitResolution); // die Aufloesung festlegen
  sensors.setWaitForConversion(false);  // den Sensor asynchron (nicht blockierend) abfragen
}

void loop() {
  if (!requestStarted) {                      // wenn noch kein Request ausgeloest wurde, dann...
    sensors.requestTemperatures();            // Request ausloesen
    requestStarted = true;                    // Variable zum merken, dass der Request ausgeloest wurde
    requestMillis = millis();                 // die Millisekunden merken
  }
  if (millis() - requestMillis >= ConvWait) { // wenn die Konvertierungszeit erreicht ist, dann...
    float temp = sensors.getTempCByIndex(0);  // die Temperatur auslesen
    Serial.print("Temperature: ");            // und anzeigen
    Serial.println(temp);
    requestStarted = false;                   // die Variable zuruecksetzen, damit der naechste Request ausgeloest werden kann
  }
}

slartibartfast, ich danke dir. :slight_smile: Genau das hat mein Problem behoben! Von der Funktion "millis" in dem Sinne hatte ich noch nie was gehört, aber das liegt wahrscheinlich daran, dass ich so ziemlich neu bin und sowieso nichts weiß.

Hallo,

du hättest auch das Bsp. der Lib nehmen können. "WaitforConversion2". :slight_smile:

Nur eins muß ich hier unbedingt korrigieren. Wegen dem 750ms.
Das hat nichts mit parasitärer Spannungsversorgung zu tun.
Der Sensor benötigt einfach die Zeit zum internen wandeln.
Je höher die Auflösung umso länger dauerts.
Man gibt dem Sensor den Befehl, "mache jetzt eine Messung",
dann muß man die notwendigen ms warten und dann erst kann man sich den Meßwert abholen.
Während dieser Pause kann man andere Dinge erledigen.

Das mit der Zeit zum umwandeln stimmt nicht!
Man liest im Netz dazu die unterschiedlichsten Aussagen, also habe ich ein Test-Sketch geschrieben, um das mal konkret zu ermitteln. So nebenbei zeigt es auch noch weitere Daten zu den Temperatur-Sensoren an.
Zum testen habe ich zwei DS18B20 parallel am Port 2 eines Nano angeschlossen (4.7 kOhm zwischen Datenleitung und +5V).
Hier der Sketch:

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

#define ONE_WIRE_BUS 2 // das Datenkabel des Temperatursensors (auch mehrere Sensoren parallel) ist an Digitalport 2 angeschlossen

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress dsAddress[8];
uint8_t dsCount = 0;
float temp = 0.0;
uint32_t startMillis = 0;
uint32_t stopMillis = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("*** Testprogramm fuer Dallas Temperatur Sensoren ***"));
  Serial.println();
  
  sensors.begin();

  dsCount = sensors.getDeviceCount();
  Serial.print(F("Anzahl der Sensoren: "));
  Serial.println(dsCount);
  
  //sensors.setWaitForConversion(true);
  Serial.print(F("Konvertierungs-Modus: "));
  if (sensors.getWaitForConversion()) {
    Serial.println(F("warten (Programm wird angehalten)"));
  } else {
    Serial.println(F("nicht warten (Programm laeuft weiter)"));
  }

  Serial.print(F("Strom ueber das Datenkabel: "));
  if (sensors.isParasitePowerMode()) {
    Serial.println(F("Ja"));
  } else {
    Serial.println(F("Nein"));
  }
  for (uint8_t i = 0; i < dsCount; i++) {
    Serial.println("");
    Serial.print(F("Temperatursensor Nr. "));
    Serial.print(i + 1);
    Serial.println(F(": "));
    Serial.print(F("Adresse:    "));
    if (sensors.getAddress(dsAddress[i], i)) {
      printAddress(dsAddress[i]);
      //sensors.setResolution(dsAddress[i], 12);
      Serial.print(F("Sensor-Typ: "));
      switch (dsAddress[i][0]) {
        case 0x10:
          Serial.println(F("DS18S20"));
          break;
        case 0x28:
          Serial.println(F("DS18B20"));
          break;
        default:
          Serial.println(F("unbekannt"));
          break;
      }
      Serial.print(F("Aufloesung: "));
      Serial.print(sensors.getResolution(dsAddress[i]));
      Serial.println(F(" Bit"));
      Serial.print(F("Temperatur: "));
      startMillis = millis();
      sensors.requestTemperaturesByIndex(i);
      if (!sensors.getWaitForConversion()) delay(750);
      temp = sensors.getTempCByIndex(i);
      stopMillis = millis();
      Serial.print(temp);
      Serial.println(F(" Grad C"));
      Serial.print(F("Konvertierungs-Zeit: "));
      Serial.print(stopMillis - startMillis);
      Serial.println(F(" ms"));
    } else {
      Serial.println(F("FEHLER! Sensor falsch angeschlossen oder defekt!"));
    }
  }
}

void loop() {}

void printAddress(DeviceAddress deviceAddress) {
  Serial.print(F("{0x"));
  for (uint8_t i = 0; i < 8; i++) {
    if (deviceAddress[i] < 16) Serial.print(F("0"));
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(F(", 0x"));
  }
  Serial.println(F("}"));
}

Mit Stromversorgung der Sensoren über die 5V-Leitung sieht das Ergebnis so aus:

*** Testprogramm fuer Dallas Temperatur Sensoren ***

Anzahl der Sensoren: 2
Konvertierungs-Modus: warten (Programm wird angehalten)
Strom ueber das Datenkabel: Nein

Temperatursensor Nr. 1: 
Adresse:    {0x28, 0xFF, 0x4D, 0x2E, 0xC1, 0x15, 0x02, 0x7F}
Sensor-Typ: DS18B20
Aufloesung: 12 Bit
Temperatur: 26.62 Grad C
Konvertierungs-Zeit: 76 ms

Temperatursensor Nr. 2: 
Adresse:    {0x28, 0xFF, 0x93, 0x72, 0xC1, 0x15, 0x02, 0x49}
Sensor-Typ: DS18B20
Aufloesung: 12 Bit
Temperatur: 26.19 Grad C
Konvertierungs-Zeit: 107 ms

Ziehe ich die 5V-Leitungen ab (Parasite-Mode), dann sieht das Ergebnis so aus:

*** Testprogramm fuer Dallas Temperatur Sensoren ***

Anzahl der Sensoren: 2
Konvertierungs-Modus: warten (Programm wird angehalten)
Strom ueber das Datenkabel: Ja

Temperatursensor Nr. 1: 
Adresse:    {0x28, 0xFF, 0x4D, 0x2E, 0xC1, 0x15, 0x02, 0x7F}
Sensor-Typ: DS18B20
Aufloesung: 12 Bit
Temperatur: 26.62 Grad C
Konvertierungs-Zeit: 813 ms

Temperatursensor Nr. 2: 
Adresse:    {0x28, 0xFF, 0x93, 0x72, 0xC1, 0x15, 0x02, 0x49}
Sensor-Typ: DS18B20
Aufloesung: 12 Bit
Temperatur: 26.19 Grad C
Konvertierungs-Zeit: 844 ms

Hallo,

oooh doch, dass stimmt. Darüber könnten wir jetzt diskutieren bis wir schwarz werden. :wink:
Wenn du natürlich in deinen Code ein delay mit 750ms einbaust, kann ja die Messung nicht stimmen.

Ich werde auch nicht so richtig schlau aus der gesamten Zeitmessung.
Du mußt die loop vermessen wir lange ein Durchlauf dauert.
Im einfachsten Fall am Anfang Zeitnahme und am Ende und dann die Differenz bilden.
Diese wird konstant sein, eben weil du während der Meßwertwandlung andere Dinge machen könntest,
aber auf keinen Fall blockierst du die loop.

Doc_Arduino:
oooh doch, dass stimmt. Darüber könnten wir jetzt diskutieren bis wir schwarz werden. :wink:

Dann erkläre mir die extrem kurzen Zeiten, bei der direkten 5V Versorgung.

Doc_Arduino:
Wenn du natürlich in deinen Code ein delay mit 750ms einbaust, kann ja die Messung nicht stimmen.

Du hast den Code nur überflogen, oder?
Dieser delay wird nur in dem Fall ausgeführt, wenn getWaitForConversion auf FALSE gesetzt ist. Das habe ich aber hier für den Test auf TRUE gesetzt, weil ich ja gerade nicht den delay messen will.

Doc_Arduino:
Ich werde auch nicht so richtig schlau aus der gesamten Zeitmessung.

Die Zeitmessung erfolgt mit "startMillis = millis();" vor "requestTemperaturesByIndex" und mit "stopMillis = millis();" nach "getTempCByIndex". Die Differenz ist dann das Ergebnnis.

Und dass man mit getWaitForConversion auf FALSE den Ablauf nicht blockiert, weiß ich. Darum geht es hier aber nicht. Mich interessierte die tatsächliche Konvertierungszeit des Temperatursensors und dafür muss getWaitForConversion auf TRUE gesetzt sein. Das habe ich oben vergessen zu erwähnen.
Aber ich denke, dass die Messung ansonsten korrekt ist, oder?

Hallo,

die beste Doku ist das Datenblatt. Der einzige zeitliche Unterschied zwischen der 5V Versorgung sind paar µs.
Du kannst nicht einfach setWaitForConversion auskommentieren oder auf true setzen nach belieben.
Darum ist die Messung nicht korrekt. Du liest den alten Meßwert nur nochmal aus.
Wenn du 750ms später nochmal auslesen würdest, hättest du den neuen Meßwert.

Um wirklich den Unterschied zu messen, nämlich die paar µs, müßtest du einen Request schicken und ständig abfragen ob die Messung fertig ist. Wenn fertig, dann Endzeitnahme und Differenz bilden.

Ok, Du hast Recht! :slight_smile:

Bei der ganzen Testerei hatte ich mal "sensors.setCheckForConversion" auf "true" gesetzt und der DS18B20 merkt sich die Konfiguration (übrigens auch die Auflösung und setWaitForConversion).
Deshalb wurde die Funktion "requestTemperaturesByIndex" vorzeitig beendet (damit man halt selbst checken kann) und das führte dann zu meinen kurzen (falschen) Meßergebnissen.
Dein Hinweis auf den alten Meßwert brachte mich dazu, mal den Quellcode der Library durchzulesen und da entdeckte ich meinen Fehler.
Danke, dass Du mich auf den richtigen Weg geführt hast!

Hier dann mal eine korrigierte Version meines Testprogramms:

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

#define ONE_WIRE_BUS 2 // das Datenkabel des Temperatursensors (auch mehrere Sensoren parallel) ist an Digitalport 2 angeschlossen

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress dsAddress[8];
uint8_t dsCount = 0;
float temp = 0.0;
uint32_t startMillis = 0;
uint32_t stopMillis = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("*** Testprogramm fuer Dallas Temperatur Sensoren ***"));
  Serial.println();
  
  sensors.begin();

  dsCount = sensors.getDeviceCount();
  Serial.print(F("Anzahl der Sensoren: "));
  Serial.println(dsCount);
  
  sensors.setWaitForConversion(true);
  sensors.setCheckForConversion(false);

  Serial.print(F("Strom ueber das Datenkabel: "));
  if (sensors.isParasitePowerMode()) {
    Serial.println(F("Ja"));
  } else {
    Serial.println(F("Nein"));
  }
  for (uint8_t i = 0; i < dsCount; i++) {
    Serial.println("");
    Serial.print(F("Temperatursensor Nr. "));
    Serial.print(i + 1);
    Serial.println(F(": "));
    Serial.print(F("Adresse:    "));
    if (sensors.getAddress(dsAddress[i], i)) {
      printAddress(dsAddress[i]);
      sensors.setResolution(dsAddress[i], 12);
      Serial.print(F("Sensor-Typ: "));
      switch (dsAddress[i][0]) {
        case 0x10:
          Serial.println(F("DS18S20"));
          break;
        case 0x28:
          Serial.println(F("DS18B20"));
          break;
        default:
          Serial.println(F("unbekannt"));
          break;
      }
      Serial.print(F("Aufloesung: "));
      Serial.print(sensors.getResolution(dsAddress[i]));
      Serial.println(F(" Bit"));
      Serial.print(F("Temperatur: "));
      startMillis = millis();
      sensors.requestTemperaturesByAddress(dsAddress[i]);
      stopMillis = millis();
      temp = sensors.getTempCByIndex(i);
      Serial.print(temp);
      Serial.println(F(" Grad C"));
      Serial.print(F("Konvertierungs-Zeit: "));
      Serial.print(stopMillis - startMillis);
      Serial.println(F(" ms"));
    } else {
      Serial.println(F("FEHLER! Sensor falsch angeschlossen oder defekt!"));
    }
  }
}

void loop() {}

void printAddress(DeviceAddress deviceAddress) {
  Serial.print(F("{0x"));
  for (uint8_t i = 0; i < 8; i++) {
    if (deviceAddress[i] < 16) Serial.print(F("0"));
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(F(", 0x"));
  }
  Serial.println(F("}"));
}

Hallo,

sehr schön, freut mich das es nun klappt. Wir helfen uns hier alle gegenseitig so gut es geht.
Manchmal muß man hartnäckiger bleiben. :wink:

Wenn du bei deiner Zeitnahme micros statt millis nimmst, könntest du auf +/-4 Digits genau messen.
Mal sehen ob man wirklich einen Unterschied von ca. 10µs ermitteln kann.