Thermometer mit OLED Display

Dieser Beitrag beschreibt den Bau eines einfachen Thermometers mit einem DS18B20 Sensor. Wir verenden ein Board mit ESP8266-E12 und integriertem OLED Display und einen Sensor DS18B20 ohne Board. Die Schaltung ist sehr einfach und der Sensor kann direkt mit dem Board verlötet werden.

Schaltung:

Ansicht:

Da der ESP8266 WiFi unterstützt habe ich im Sketch bereits die Unterstützung eines zweiten entfernten Sensors eingebaut. Dieser zweite Sensor wird mit dem Thermometer mit ESP-Now kommunizieren, ein Protokoll mit dem sehr energiesparende Lösungen geschaffen werden können. Die Messergebnisse werden dann abwechselnd am Display angezeigt. Wenn kein entfernter Sensor angeschlossen ist, wird nur der Wert des internen Sensors angezeigt.

Der Sketch ist ausführlich kommentiert.

Sketch:

/* Esp8266 mit OLED Display als Thermometer 
 */

//Bibliotheken für WiFi 
#include <ESP8266WiFi.h>
//Bibliothek für OLED Display
#include <U8g2lib.h>
//Bibliotheken für DS18B20 Temperatur Sensor
#include <OneWire.h>
#include <DallasTemperature.h>

//Bibliothek für ESP-Now
extern "C"{
#include <espnow.h>
}

//Pins für Temperatursensor
const byte bus = 0;//pin GPIO0

//Protokoll zum Auslesen  des Sensors
OneWire oneWire(bus);

//Sensor Instanz
DallasTemperature sensoren(&oneWire);

//Array um Sensoradressen zu speichern
DeviceAddress adressen;

//Display initialisieren
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 5, /* data=*/ 4, /* reset=*/ 16);

//Offset zur Kalibrierung der Temperatur
const uint8_t offset = 15;

//Werte der Temperatursensoren -127 = der Wert, 
//den man erhält wenn kein Sensor angeschlossen ist 
  float aussen = -127;
  float innen = -127;

// Nach einem Reset ist die SSID sichtbar damit ein entfernter Sensor sich 
// verbinden kann. Nach ca. 2 Minuten sollte die SSID versteckt werden 
// Zähler zum Abschalten der sichtbaren SSID  
int cnt = 24;

//Logos als Bitmap für Display
#define haus_width 16
#define haus_height 16
static unsigned char haus_bits[] = {
   0x80, 0x0c, 0xc0, 0x0d, 0x60, 0x0f, 0x30, 0x0e, 0x18, 0x0c, 0xcc, 0x19,
   0x46, 0x31, 0x47, 0x71, 0xc5, 0x51, 0x04, 0x10, 0xf4, 0x16, 0x94, 0x16,
   0x94, 0x16, 0x94, 0x10, 0x94, 0x10, 0xff, 0xff };

#define baum_width 16
#define baum_height 16
static unsigned char baum_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x10, 0x05, 0x08, 0x0a, 0x34, 0x13,
   0x04, 0x10, 0x02, 0x10, 0x02, 0x08, 0x04, 0x16, 0x18, 0x10, 0xd0, 0x17,
   0xa0, 0x09, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff };


//Datenstruktur für den Datenaustausch über ESP Now
struct DATEN_STRUKTUR {
    float temp = 0;
};

//Netzwerk Name
char* SSID = "Thermometer";


//Callback funktion wenn Daten empfangen wurden 
void on_receive_data(uint8_t *mac, uint8_t *r_data, uint8_t len) {
 
    DATEN_STRUKTUR data;
    //wir kopieren die empfangenen Daten auf die Datenstruktur
    //um über die Datenstruktur zugreifen zu können
    memcpy(&data, r_data, sizeof(data));
    aussen = data.temp;
  };
 
// function um eine Sensoradressen zu drucken
void printAddress(DeviceAddress adressen)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (adressen[i] < 16) Serial.print("0");
    Serial.print(adressen[i], HEX);
  }
}

void setup() {
  Serial.begin(115200); 
  
  WiFi.begin();
  //Konfiguration des Access Points
  WiFi.mode(WIFI_AP);
  
  WiFi.softAP(SSID); 
  //ESOP-Now initialisieren  
  if (esp_now_init()!=0) {
    ESP.restart();
    delay(1);
  }
 
 
  // ESP Rolle festlegen 1=Master, 2 = Slave 3 = Master + Slave
  esp_now_set_self_role(2); 
  //und callback funktion registrieren
  esp_now_register_recv_cb(on_receive_data);  

  //Display vorbereiten
  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.setFontMode(0);

  //Temperatursensor initialisieren
  sensoren.begin();
  Serial.print(sensoren.getDeviceCount(), DEC);
  Serial.println(" Sensoren gefunden.");
  //Nun prüfen wir ob der Bus im parasitären Modus ist
  Serial.print("Parasitärer Modus ist ");
  if (sensoren.isParasitePowerMode()) {
    Serial.println("EIN");
  } else {
    Serial.println("AUS");
  }
  //Nun prüfen wir ob einer der Sensoren am Bus ein Temperatur Sensor ist
  if (!sensoren.getAddress(adressen,0)) {
    Serial.println("Kein Temperatursensor vorhanden!");
  }
  //adressen anzeigen
  Serial.print("Adresse: ");
  printAddress(adressen);
  Serial.println();
  sensoren.setResolution(adressen,12);
  Serial.print("Auflösung = ");
  Serial.print(sensoren.getResolution(adressen), DEC);
  Serial.println();
  //Pullup Widerstand für Temperatursensor
  pinMode(0,INPUT_PULLUP);
}

void loop() {
  char text[50] = {0}; //Textbuffer für Display
  int tmp; //Temporär für Temperaturen
  sensoren.requestTemperatures(); // Sensor  Messung starten
  delay(800);//Zeit um die Temperatur zu messen
  innen = sensoren.getTempC(adressen); //Temperatur vom Sensor lesen
  //Wir wandeln die Temperatur nach integer mit einer Dezimalstelle
  tmp = round(innen * 10);
  //Ausgabetext generieren
  sprintf(text,"%2d.%01d°C", tmp/10-offset, abs(tmp%10));
  //und an Display senden
  u8g2.firstPage(); do {
    //zuerst das Logo
    u8g2.drawXBM( 0, 8, haus_width, haus_height, haus_bits);
    //dann den Text
    u8g2.setFont(u8g2_font_osb26_tf);
    u8g2.setFontDirection(0);
    u8g2.drawUTF8(20, 30, text);
  } while ( u8g2.nextPage() );  
  delay(5000); //5 Sekunden warten
  //Zähler vermindern
  if (cnt > 0) cnt--;
  //Haben wir einen Wert von einem entfernten Sensor
  //Dann zeigen wir den an
  if (aussen !=  -127) {
    //Wir wandeln die Temperatur nach integer mit einer Dezimalstelle
    tmp = round(aussen * 10);
    //Ausgabetext generieren
    sprintf(text,"%2d.%01d°C", tmp/10, abs(tmp%10));
    //und an Display senden
    u8g2.firstPage(); do {
      //zuerst das Logo
      u8g2.drawXBM( 0, 8, baum_width, baum_height, baum_bits);
      //dann den Text
      u8g2.setFont(u8g2_font_osb26_tf);
      u8g2.setFontDirection(0);
      u8g2.drawUTF8(20, 30, text);
    } while ( u8g2.nextPage() );
    delay(5000); //5 Sekunden warten
    //Zähler vermindern
    if (cnt>0) cnt--;
  }
  //Wenn Zähler auf 0 die SSID verstecken
  if (cnt <= 0) WiFi.softAP(SSID,NULL,1,1);
}  


Mit einem geeigneten LiPo-Akku mit 3.7 V kann das Thermometer mit Batterie betrieben werden. Laderegler und Batteriebuchse sind am Board vorhanden.

 

Letzter Artikel Uno R3 als Webserver mit Ethernet Shield

Kommentar

Gerald - August 23, 2018

Ein 1200mAh Akku hält ohne Aufladung ca. 1 Tag.
Der 4.7 kOhm Widerstand ist nicht nötig wenn man den Datenpin mit pinMode auf INPUT_PULLUP setze.
Für einen Temperatursensor der dei Daten mit WiFi und mit Batterie betrieben werden kann, möchte ich auf den nächsten Beitrag in diesem Blog verweisen.

Sören - August 21, 2018

Meines Erachtens fehlt zwischen Plus-Pol und Daten-Pin ein 4,7kOhm Widerstand – oder ist der bei 3.3V nicht nötig?
Ich arbeite grundsätzlich mit 5V.

Passende Widerstände sollte az-delivery auch anbieten…

Stephan - August 21, 2018

Hallo Manuel,

du könntest die Temperaturen mit MQTT versenden. Für OpenHab gibt es da dann entsprechende Unterstützung.
Nutze ich auch für diverse Sensoren. Z.B.: https://github.com/stritti/smart-swimming-pool

Ralph - August 21, 2018

Das mit der Batterie würde mich auch interessieren.

Zu. Kühlschrank, der ist ein relativ guter Farradayscher Käfig mit Wifi innen ist da nicht viel. Funfakt deswegen hatte Snowden als die Journalisten ihn in HongKong aufsuchten, deren Smartphones in den Kühlschrank gesteckt.

Manuel - August 20, 2018

Hi,

interessante Sache. Wie lange würde die Batterie in etwa halten? Und wäre das WiFi geeignet, um den Sensor im SmartHome (openHAB) zu integrieren? Suche noch eine Lösung um die Kühlschranktemperatur zu überwachen.

Danke für Kommentar.

Grüße

Manuel

Hinterlasse einen Kommentar

Kommentare müssen vor der Veröffentlichung überprüft werden

Erforderliche Angabe