Dallas bremst loop stark aus ?

Hallo,

gibt es eine andere Möglichkeit die Temperaturen der Dallassensoren auszulesen? Also schneller.
In der ersten Funktion nach loop ist ein delay(1000) drin. Das stört bestimmt.
Das Programm reagiert dennoch gefühlt verzögert länger als die eine Sekunde auf Tastendruck.
Ohne die Dallas Geschichte gibts aus meiner Sicht keine Verzögerung auf Tastendruck. Es wird sofort auf die SD geschrieben.

Sketch ist zu lang für hier, deshalb als Datei.

SDcard_Write_Taster_LcdSPI_DS1820_002.ino (9.04 KB)

Das Programm reagiert dennoch gefühlt verzögert länger als die eine Sekunde auf Tastendruck.

Neuere Versionen von DallasTemperature kannst Du asynchron abfragen lassen, damit ist der Arduino nicht mehr blockiert (er kann also noch andere Dinge tun), aber der Sensor braucht 0.75s für die Erfassung der Temperatur (der Arduino muss solange warten, bis er den Wert kriegt), wenn Du also auf Knopfdruck die Temperatur einlesen willst und es Dir zu langsam geht, dann musst Du auf andere Sensoren ausweichen.

Edit: Du kannst auch die Auflösung runterschrauben, dann geht's deutlich schneller, z.B. 9bit = ca 100ms.

Nimm die neueste Lib:
http://milesburton.com/Dallas_Temperature_Control_Library

Ich mache es so:

const int ONE_WIRE_BUS = 14;
const unsigned long POLLING_INTERVAL = 500;

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress sensorList[] = {	{ 0x28,0x68,0x2A,0xA4,0x05,0x00,0x00,0xAB },
                            { 0x28,0x82,0x38,0xA5,0x05,0x00,0x00,0x3D } };
float temperatures[2];

void setup()
{	
  sensors.begin();
  sensors.setWaitForConversion(false);
  sensors.setResolution(sensorList[0], 9);
  sensors.setResolution(sensorList[1], 9);
}

void loop()
{
  readTemperatureSensors();
}

void readTemperatureSensors()
{
  static unsigned long previousPollingMillis;
  static unsigned long previousRequestMillis;
  static bool dataRequested;

  if(dataRequested == true && millis() - previousRequestMillis > 100)
  {
    temperatures[0] = sensors.getTempC(sensorList[0]);
    temperatures[1] = sensors.getTempC(sensorList[1]);
    dataRequested = false;
    return;
  }
	
  if(dataRequested == false && millis() - previousPollingMillis > POLLING_INTERVAL)
  {
    previousPollingMillis = millis();

    sensors.requestTemperatures();
    dataRequested = true;
    previousRequestMillis = millis();
  }
}

Bei 9 Bit (0,5°) Auflösung dauert die Konvertierung wie gesagt etwa 100ms.

Der Schlüssel ist hier setWaitForConversion(false). Das macht die Aufrufe von requestTemperatures() nicht-blockierend.

Ich habe dabei ein TFT mit SD Slot laufen. Das läuft wunderbar nebeneinander ohne etwas zu blockieren. :slight_smile:
Eine Ausgabe ist an dieser Stelle nicht drin. Das schreibt nur die aktuelle Temperaturen in ein float Array

Doc_Arduino:
Das Programm reagiert dennoch gefühlt verzögert länger als die eine Sekunde auf Tastendruck.

Ja. Aber nur bei falscher Ansteuerung und wenn zwischen "Anforderung einer Messung" und "Abholen des Messwertes" nicht die erforderliche Messzeit liegt. Dann macht die Dallas-Library eine Zwangspause im Sketch und würgt Deine Loop gnadenlos runter.

Die einfachste Logik, falls Du nicht mehr als 30 Messungen pro Minute brauchst, geht so: Immer wenn die Sekunde wechselt, machst Du EINE Aktion:

  • bei Anbruch einer geraden Sekunde: Messung anfordern
  • bei Anbruch einer ungeraden Sekunde: Temperatur abholen
    u.s.w.
    Dann liegt selbst in der höchsten Messauflösung mindestens die notwendige Messzeit dazwischen, und die Temperatur kann stets ohne eine zusätzliche Zwangspause abgeholt werden.

Hallo,

aha, dann werde ich mal versuchen das umzubauen. Danke für die netten Hinweise.

Hallo,
die Anwendung, wo man 30 Temperaturmesswerte pro Minute benötigt würde mich wirklich mal interessieren. Wie träge ist denn eigentlich der Sensor an sich ?

Im Moment ist das eher zum Test gedacht. Deshalb die 500ms. Das Display reagiert so sofort wenn sich die Temperatur ändert (Finger hinhalten reicht) und man sieht dass alles funktioniert. Ist übertrieben, aber es stört sonst nichts. Später reicht das natürlich viel langsamer :slight_smile:

Die Geschwindigkeit hängt wie gesagt von der Auflösung ab. Bei 0,5° dauert eine Wandlung etwa 100ms. Laut Datenblatt glaube ich 93ms. Dadurch dass das nicht blockierend ist kann man dann zwischen der Anforderung und dem Auslesen andere Dinge machen.

Trägheit ist aber immer noch da. Vielleicht durch das Gehäuse. Ich habe ein Thermometer mit Thermoelement. Das reagiert viel schneller. Es hält sich aber in Grenzen. Man kann damit leben.

Hallo,

hab nochmal in das Datenblatt geschaut zu meinen DS18S20. Der hat nur 9Bit Auflösung und benötigt max. 750ms zum messen. Kann es sein das nur der DS18B20 in 9Bit schneller messen kann?

Und dann fällt mir auf, dass in der neuen Dallas Library kein Bsp. mehr drin ist zum erstmaligen auslesen der Sensoren überhaupt. Damit man zum Bsp. die Adressen erstmal angezeigt bekommt. Ich hätte wetten können das war in der alten dabei. Oder ich habe den Sketch woanders her. ?

Ja, ich habe DS18B20 :s Der braucht 750ms für 12 Bit

Das Beispiel für die Adressen nennt sich "Tester"

Du kannst das aber auch per Hand programmieren:

DeviceAddress tempDeviceAddress;
numberOfDevices = sensors.getDeviceCount();

for(int i=0; i<numberOfDevices; i++)
{
    if(sensors.getAddress(tempDeviceAddress, i))
    {
       for (int i=0; i < 8; i++)
       {
            if (tempDeviceAddress[i] < 16) Serial.print("0");
            Serial.print(tempDeviceAddress[i], HEX);
       }
       Serial.println();
    }
}

Nicht getestet. Nur den relevanten Teil rauskopiert und etwas angepasst

Hallo,

okay, alles klar. :slight_smile:

Hallo,

okay, dann gibt es diesen alten Testsketch nicht mehr. Die Ausgabe gefiel mir bisher am Besten, weil man auch gleich den Sensortyp mit angezeigt bekam. Hängt unten dran, damit es nicht abhanden kommt.

Jetzt habe ich das neue Bsp. Single für mich angepaßt, alles unnötige Serial usw. rausgewurfen, scheint auch zu funktionieren. Kommt mir dennoch irgendwie sehr kurz vor.
Nur frage ich mich, was macht diese Funktion?
sensors.requestTemperatures(); // Send the command to get temperatures
Der wird keine Sensoradresse übergeben. Woher weis die welche(n) Sensor die auslesen soll? Hexerei?

#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);

// Device Adressen der einzelnen ds1820 Temperatursensoren angeben (loop anpassen)
DeviceAddress sensor1 = { 0x10, 0x40, 0xDD, 0xC3, 0x2, 0x8, 0x0, 0xB4 };
DeviceAddress sensor2 = { 0x10, 0x8A, 0xB, 0xAC, 0x2, 0x8, 0x0, 0x2C };
char sensor1Name[] = "Sensor 1: ";
char sensor2Name[] = "Sensor 2: ";


void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");
  
 
  // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(sensor1, 9);
  sensors.setResolution(sensor2, 9);
 
}



void loop(void)
{ 

  sensors.requestTemperatures();     // Send the command to get temperatures
  
  // It responds almost immediately. Let's print out the data
  printTemperature(sensor1); // Use a simple function to print out the data
  printTemperature(sensor2); // Use a simple function to print out the data
  Serial.println();
  
delay(750);    // vorläufig, wird durch millis ersetzt 

}  // Ende loop


// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
}

Das sendet ein Kommando an alle Sensoren eine Wandlung durchzuführen. Die Sensor Adresse spielt erst bei getTempC() eine Rolle, wo man dann die Temperatur ausliest. Technisch läuft dass so ähnlich wie ein Broadcast im Netzwerk. Das Kommando wird einfach von allen Sensoren am Bus ausgewertet.

Das ist ja der springende Punkt mit dem Delay. Das ist ein A/D Wandler drin und die Wandlung dauert eine bestimme Zeit. Deshalb muss man zwischen Anforderung und Auslesen warten. In der neueren Lib kann man da eben waitForConversion() auf false setzen, damit die Anforderung nicht-blockierend ist. Dann ist man selbst dafür verantwortlich das Delay zu setzen. Siehe die zwei das WaitForConversion Beispiele.

Wenn waitForConversion() auf true ist, dann wird das Delay durch die Lib gemacht:

void DallasTemperature::requestTemperatures()
{
  _wire->reset();
  _wire->skip();
  _wire->write(STARTCONVO, parasite);

  // ASYNC mode?
  if (false == waitForConversion) return; 
  
  switch (bitResolution)
  {
    case 9:
      delay(94);
      break;
    case 10:
      delay(188);
      break;
    case 11:
      delay(375);
      break;
    case 12:
    default:
      delay(750);
      break;
  }
  return;
}

Was standardmäßig der Fall ist. Siehe der Konstruktor:

DallasTemperature::DallasTemperature(OneWire* _oneWire)
{
  ....

  waitForConversion = true;
}

Da sieht man auch, dass die Lib nicht 100%ig für den DS18S20 geeignet ist, da das automatische Delay für 9 Bit zu kurz ist. Jedenfalls wenn man die Auflösung per Hand setzt. Wenn man nichts macht vergehen durch den default case 750ms und es passt :slight_smile:
Den Teil würde ich daher bei dir entfernen

Du kannst aber auch die Anforderung nach Adresse machen:

 // sends command for one device to perform a temperature conversion by address
  bool requestTemperaturesByAddress(uint8_t*);

und

  // sends command for one device to perform a temperature conversion by index
  bool requestTemperaturesByIndex(uint8_t);

Es bringt nur nichts wenn man sowieso alle Sensoren zur gleichen Zeit ausliest. Das wäre nur was wenn man die Sensoren zu unterschiedlichen Zeiten auslesen würde. Also z.B. Sensor1 alle Minute und Sensor2 alle 5 Minuten

Bei sowas lohnt es sich in den Header zu schauen. Da sieht man was es an Methoden gibt.

Hallo,

gut, dann werde ich mir das nochmal anschauen.
Wegen dem "Tester" Wie gesagt, der alte Testsketch gefiel mir besser. :wink:
Hängt nun hier nochmal dran. Hatte ich vorhin vergessen.

Dallas_DS18S20_001.ino (3.06 KB)

Hallo,

habs nun hinbekommen mit den Änderungen im Code. Funktioniert einwandfrei. Auf Tastendruck wird zackig reagiert und im Display laufen die 1/10 Sekunden von millis flüssig durch. Was will man mehr. :slight_smile:

Danke an Euch für die Unterstützung und Erklärungen.

SDcard_Write_Taster_LcdSPI_DS1820_003.ino (8.8 KB)