Temperatursensor DS18B20 an ESP 8266

Hallöchen,

Ich habe mir ein TTGO 8266 bestellt, und zwar dieses hier mit Display:

https://de.aliexpress.com/item/Ttgo-Zu-Esp8266-Oled-Sh1106-1-3-Zoll-Wetter-Station-Wifi-Meteo-Modul/32991627632.html?spm=a2g0s.9042311.0.0.63524c4dJmCHH7

Daran wollte ich einen Temperatursensor DS18B20 anschließen:

Ich habe in diesem Projekt vor, mir die Temperatur auf dem Display mit einer kleinen Grafik anzeigen zu lassen.
Ich habe mich an dieses Einsteigertutorial gehalten und im Anschluss wollte ich den Code dann nach meinem Belieben ändern:

Den Code habe ich an einer Stelle geändert, und zwar habe ich

OneWire  ds(2);  // on pin 2 (a 4.7K pullup is necessary)

geändert auf

OneWire  ds(15);  // on pin 2 (a 4.7K pullup is necessary)

da ich den mittleren Pin des Sensors auf den Anschluss GPIO15 gesteckt habe. Mit diesem Code wollte ich dann die Adresse des Sensors über den seriellen Monitor auslesen.
Jetzt frage ich mich als erstes, ob das so vom Anschluss (ds(15) her richtig ist.

Hier ist der Code dazu:

/*
 * ESP8266-01 with multiple DS10B20 temperature sensors
 * reads sensors asyncronsly for less blocking time
 * 
 * Use GPIO2 for the sensors, a single 4.7K pullup resisor is needed.
 * 
 */
#include <OneWire.h>

const int nsensors = 2;
byte sensors[][8] = {
   { 0x28, 0xC1, 0x02, 0x64, 0x04, 0x00, 0x00, 0x35 },
   { 0x28, 0xE7, 0x0B, 0x63, 0x04, 0x00, 0x00, 0x44 }
};
int16_t tempraw[nsensors];
unsigned long nextprint = 0;

OneWire  ds(15);  // on pin 2 (a 4.7K pullup is necessary)

void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println();
  Serial.println();
}

void loop() 
{
  ds18process(); //call this every loop itteration, the more calls the better.

  if(millis() > nextprint) {
    Serial.print("Temp F: ");
    for(byte j=0; j<nsensors; j++){
      Serial.print(j); Serial.print("=");
      Serial.print(ds18temp(1, tempraw[j])); Serial.print("  ");
    }
    Serial.println();
    nextprint = millis() + 1000; //print once a second
  }
}

/* Process the sensor data in stages.
 * each stage will run quickly. the conversion 
 * delay is done via a millis() based delay.
 * a 5 second wait between reads reduces self
 * heating of the sensors.
 */
void ds18process() {
  static byte stage = 0;
  static unsigned long timeNextStage = 0;
  static byte sensorindex = 100;
  byte i, j;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];

  if(stage == 0 && millis() > timeNextStage) {
    if (!ds.search(addr)) {
      //no more, reset search and pause
      ds.reset_search();
      timeNextStage = millis() + 5000; //5 seconds until next read
      return;
    } else {
      if (OneWire::crc8(addr, 7) != addr[7]) {
        Serial.println("CRC is not valid!");
        return;
      }
      //got one, start stage 1
      stage = 1;
    }
  }
  if(stage==1) {
    Serial.print("ROM =");
    for ( i = 0; i < 8; i++) {
      Serial.write(' ');
      Serial.print(addr[i], HEX);
    }
    //find sensor
    for(j=0; j<nsensors; j++){
      sensorindex = j;
      for(i=0; i<8; i++){
        if(sensors[j][i] != addr[i]) {
          sensorindex = 100;
          break; // stop the i loop
        }
      }
      if (sensorindex < 100) { 
        break; //found it, stop the j loop
      }
    }
    if(sensorindex == 100) {
      Serial.println("  Sensor not found in array");
      stage = 0;
      return;
    }
    Serial.print("  index="); Serial.println(sensorindex);
  
    ds.reset();
    ds.select(sensors[sensorindex]);
    ds.write(0x44, 0);        // start conversion, with parasite power off at the end
    stage = 2; //now wait for stage 2
    timeNextStage = millis() + 1000; //wait 1 seconds for the read
  }
  
  if (stage == 2 && millis() > timeNextStage) {
    // the first ROM byte indicates which chip
    switch (sensors[sensorindex][0]) {
      case 0x10:
        Serial.print("  Chip = DS18S20");  // or old DS1820
        Serial.print("  index="); Serial.println(sensorindex);
        type_s = 1;
        break;
      case 0x28:
        Serial.print("  Chip = DS18B20");
        Serial.print("  index="); Serial.println(sensorindex);
        type_s = 0;
        break;
      case 0x22:
        Serial.print("  Chip = DS1822");
        Serial.print("  index="); Serial.println(sensorindex);
        type_s = 0;
        break;
      default:
        Serial.println("Device is not a DS18x20 family device.");
        stage=0;
        return;
    }
  
    present = ds.reset();
    ds.select(sensors[sensorindex]);
    ds.write(0xBE);         // Read Scratchpad
  
    Serial.print("  Data = ");
    Serial.print(present, HEX);
    Serial.print(" ");
    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
      Serial.print(data[i], HEX);
      Serial.print(" ");
    }
    Serial.print(" CRC=");
    Serial.print(OneWire::crc8(data, 8), HEX);
    Serial.print(" index="); Serial.print(sensorindex);
    Serial.println();
  
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } else {
      byte cfg = (data[4] & 0x60);
      // at lower res, the low bits are undefined, so let's zero them
      if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
      //// default is 12 bit resolution, 750 ms conversion time
    }
    tempraw[sensorindex] = raw;
    stage=0;
  }
}

/* Converts raw temp to Celsius or Fahrenheit
 * scale: 0=celsius, 1=fahrenheit
 * raw: raw temp from sensor
 * 
 * Call at any time to get the last save temperature
 */
float ds18temp(byte scale, int16_t raw) 
{
  switch(scale) {
    case 0: //Celsius
      return (float)raw / 16.0;
      break;
    case 1: //Fahrenheit
      return (float)raw / 16.0 * 1.8 + 32.0;
      break;
    default: //er, wut
      return -255;
  }
}

Hi

Der Kommentar ist somit schon Mal falsch - Nichts ist schlimmer, als ein irreführender Kommentar!

Heißt der Pin GPIO15 in der IDE auch 15?
Gleiches für Nummer 2, also dem Original - hat der dortige Bastler den DS18B20 an dem Pin '2'?

Selber kenne ich den ESP8266 nicht, habe nur hier und da aufgeschnappt, daß die GPIO-Nummern, ähnlich wie bei den AVRs des Arduino, herzlich wenig mit den Arduino-Pin-Nummern zu tun haben.
Suche dazu Mal nach 'Pinout ESP 8266' - vll. hilft Dir Das schon weiter.

MfG

Der Tutorial-Ersteller nannte seinen Pin GPIO2 und im Code hat er die Zeile wie folgt geschrieben:

OneWire  ds(2);  // on pin 2 (a 4.7K pullup is necessary)

Zu meinem Board wurde dieses hier mitgeliefert (Bild):

Hallo,

pass mit GPIO15 auf, der muß zur Bootzeit Low-Pegel haben (hat bei den fertigen Boards dazu einen PullDown-Widerstand drauf. Nimm GPIO 12 oder 13 für Deinen DS.

Gruß aus Berlin
Michael

Mist, das wusste ich nicht. Ich hatte den GPIO15 getestet. Nun kann ich keinen neuen Code mehr hochladen. Grrr sehr ärgerlich. Hast du einen Tipp für mich, das wieder glattzubügeln?
LG und vielen Dank schonmal bis hierher.

Klemme die Beschaltung an dem Pin ab.

Gruß Tommy

Bringt leider keinen Erfolg, sehr ärgerlich. Auch die kleine Bootleuchte auf der Rückseite blinkt nicht mehr beim Hochladen, so wie das zweite Ersatzdisplay es tut, dass sich bei gleichen Einstellungen hochladen lässt.

Wie ist GPIO15 jetzt beschaltet?

Gruß Tommy

Ich hatte alle Kabel vom Board gezogen und nur über USB angeschlossen. Ich hatte den Reset Knopf nun während des Hochladens komplett gedrückt gehalten und es hat funktioniert. Puh, Schwein gehabt 8-).

Meine Schaltung habe ich nun überprüft mit einem Arduino Nano, einem OLED Display und dem DS18B20.
Hier wird die Temperatur schön angezeigt.
Komisch ist nur, dass sie nur richtig angezeigt wird, wenn ich den Sensor an 5v angeschlossen habe. Am 3v3V Pin schwankt sie immer wieder zwischen dem korrektem Wert und -127. Der Sensor ist jedoch im Datenblatt mit mindestens 3V angegeben.

Versuch mal statt des 4,7k einen 3,9k Pullup Widerstand

Es hat funktioniert! Ich habe nochmal den 3,3v Anschluss getestet, GPIO12 benutzt und auch im Code:

#define ONE_WIRE_BUS 12 // GPIO des ESP

benutzt.

Im Monitor wird mir nun der korrekte Wert ausgegeben. Das reicht mir für heute, morgen gehts weiter.
Vielen Dank an alle Helfer.
Ich bin mir sicher, die Tage kommen eventuell noch ein paar klitzekleine weitere Fragen dazu.

LG und gute Nacht!

Hi

-127 ist der Fehler-Rückgabewert der Lib - hat also nur indirekt was mit Dem zu tun, was der Sensor wirklich geschwätzt hat.

MfG

Hallo,

so allgemein: die fertigen Boards sind normalerweise immer so beschaltet, daß sie sich vernünftig benehmen, also GPIO16 mit PullDown, Reset und GPIO0 an der Logik für die "automatische" Umschaltung aus der IDE.
Wen die klemmen: alles extern abtrennen. Wenn kein PORG-Taster an GPIO0 auf dem Board ist (wie bei diesem z.B.) eine Brücke zwischen GPIO0 und GND stecken. Reset festhalten und das Programmieren starten.
Reset loslassen, wenn die IDE mit dem Programmieren beginnt. Dann solte das Flashen starten.
Wenn das komplett fertig ist die Brücke entfernen und Reset kurz drücken, dann sollte das geflashte Programm sich melden.
Hier
https://www.arduinoforum.de/arduino-Thread-ESR8266-Bootmodi-und-Pin-Nutzung
hatte ich dazu mal was geschrieben.

Gruß aus Berlin
Michael

Danke Michael,

Ich bin jetzt einen kleinen Schritt weiter. Ich wollte das Display gerne mit der Adafruit library benutzen. Ich nutze dazu den unten stehenden Code, wobei mir das mit dem “Reset” noch nicht so ganz geheuer ist (bzw. weiß ich nicht, was dieser genau tut). Lösche ich die Zeilen mit “Reset”, funktioniert der Code nicht mehr. Gebe ich eine willkürliche Zahl ein funktioniert der Code, jedoch würde ich diesen Punkt gerne verstehen.

Das Display springt auf jeden Fall schonmal an und im seriellen Monitor wird mit die korrekte Temperatur angezeigt.
Die Displayanzeige auf dem Board springt jedoch wild hin und her, ist nicht auf der richtigen Position und es sind teilweise alte Schriften vom vorher aufgespielten Code zu sehen.

Das Bild verdeutlicht dies ganz gut (Unten rechts in der Ecke des Displays ist ein Teil meines Codes, die Mitte zeigt Texte des vorher aufgespielten Codes). Die Grafiken ändern zusätzlich nach dem delay auch noch ihre Position in der X-Achse.

Hat dafür wer eine Erklärung?

LG

(Das Bild lässt sich trotz erfüllter Anforderungen nicht hochladen, hier ein externer Link: )

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




#define OLED_RESET 10
Adafruit_SSD1306 display(OLED_RESET);

#define OLED_SDA  5
#define OLED_SCL 4
#define OLED_RST  10


#define ONE_WIRE_BUS 12 // GPIO des ESP
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.

//ADC_MODE(ADC_VCC); // ADC an zur Auslesung der Spannung



    
#if (SSD1306_LCDHEIGHT != 64) //LSD Display Auflösung 128x64
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif




void setup()
{
   
Wire.begin( OLED_SDA, OLED_SCL); 

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

delay(1000);

Serial.begin(115200);
Serial.println("Starte Temperatur Messprogramm");

delay(1000);

sensors.begin(); /* Inizialisieren der Dallas Temperature library */

// Abfrage Temperatur
double temperatur;

sensors.requestTemperatures(); 

temperatur = sensors.getTempCByIndex(0);

Serial.println();
Serial.print(temperatur);
Serial.print(" Grad Celsius");

}

void loop()
{

double temperatur;

sensors.requestTemperatures(); 

temperatur = sensors.getTempCByIndex(0);

display.clearDisplay();

display.drawLine(76, 52, 76, 64, WHITE);
display.setFont();
display.setTextSize(0);
display.setCursor(80, 80); //11, 5
display.println(temperatur);
display.drawRoundRect( 0, 0, 64, 16, 3, WHITE);
display.setCursor(74, 5);
display.println("EXTRUDER");
display.drawRoundRect( 68, 0, 60, 16, 3, WHITE);

display.drawRoundRect( 24, 17, 80, 30, 3, WHITE);
display.setTextSize(0);
display.setTextColor(WHITE);
display.setCursor(80, 39);  //38, 39
display.println("TEST");
display.setCursor(72, 39);
display.println( "C");
display.display();

delay(1000);
    
}

Hallo,

woher hast Du die Erkenntnis, daß Reset vom Display an GPIO10 hängt?
Ich habe zu Deinem Board außer dem Bild nichts gefunden und da ist Reset vom OLED nicht erwähnt, nur SDA und SCK. Verkutlich haben sie Reset mit auf den ESP8266 Reset gelegt um ein Pin zu sparen, das kann man machen.

Der Adafruit Constructor dazu sagt ja:
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Gruß aus Berlin
Michael

Danke. Ich habe gelesen, dass dieses Display nur mit dem SH1106 Treiber funktioniert. Den angehängten Code habe ich hochgeladen und er funktioniert einwandfrei ohne Fehler. Nun wollte ich gerne die u8glib verwenden, könntest du mir eine kleine Anleitung geben, wie ich das am besten umsetze?
LG

Nimm lieber die U8g2lib. Die andere wird nicht weiterentwickelt.

Zu dieser Lib gibt es ein sehr ausführliches Wiki.

Gruß Tommy

Vielen Dank. Diese habe ich bereits getestet mit dem Beispiel "GraphicsTest". Die Zeile 74 habe ich wie folgt geändert:

//U8G2_SH1106_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 4, /* dc=*/ 5, /* reset=*/ 8);

Leider bleibt damit das Display aus.

Nutze ich die Zeile 67:

//U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 4, /* data=*/ 5, /* reset=*/ U8X8_PIN_NONE);

Springt das Display zwar an, ist jedoch um 2 Pixel versetzt, da der Displaytreiber den SH1106 braucht.

Hast du dafür einen Vorschlag?

Kannst Du die 2 Pixel mit -2 für x ausgleichen?

Gruß Tommy

Klasse, das funktioniert. Danke. Ist zwar etwas komisch, aber Hauptsache es geht so. Ich würde mich gerne etwas durch die ganzen Grafikfunktionen wühlen und rumprobieren. Hast du eine Quelle, wo man diese Grafiken mit Beschreibung findet?
LG und danke schonmal bis hierher.

Habs gefunden: