Temperature / humidity node with OLED display



  • I've just built this temperature / humidity node, with a 1.3" OLED display:

    TempHumDisp_1.jpg
    TempHumDisp_2.jpg

    The OLED is a 128x64 I2C version, driven by an SSD1306 chip, and will display 8 lines of text - but as I'm short-sighted :smile: , I've used double-height text, showing time (from Domoticz), temperature, humidity and battery voltage.

    The node uses a Ceech board, and is powered by a Samsung phone battery with a micro-USB connector (top left) to charge it. There is an HTU21D temperature / humidity sensor bottom left. Connectors have been judiciously bent (!), so that the base will fit on the box.

    The sketch is based on Ceech's example sketch for the board, with the inclusion of a cut-down, text-only library for the SSD1306 (to save space).



  • @MikeF Is the display on all the time?



  • @Dwalt Currently, yes. I haven't done any measurements yet on current / discharge rate, but I can power it from USB and charge the battery at the same time. I may add a push button to turn on the display.



  • Great project
    what script and stuff have you used?
    i am very interested to make a temprature switch for my living room with that kind of display
    great work :)



  • I've used the following:

    • Ceech ATmega328p board w/ ESP8266 and NRF24l01+ socket LTC4067 lithium battery charger - here

    • HTU21D temperature and humidity sensor

    • SSD1306 1.3" I2C 128x64 display - here

    • micro USB breakout board

    The sketch is included below (I've referenced the source of this in the comments at the beginning):

    // Temp + humidity sensor
    // Using Ceech board
    // and SSD1306 128 x 64 OLED display.
    // This example is designed to fit Arduino Nano/Pro Mini
    //
    // SSD1306 text-only library taken from this thread:
    //		https://forum.arduino.cc/index.php?topic=274880.0
    
    #include <MySensor.h>
    #include <SPI.h>
    #include <Wire.h> 				// I2C
    #include <HTU21D.h>            	// temperature / humidity (i2c, HTU21D, SHT21)
    #include <SSD1306_text.h>		// SSD1306 OLED display
    #include <Time.h>
    
    #define SKETCH_NAME "Temp + hum w. display"
    #define SKETCH_MAJOR_VER "1"
    #define SKETCH_MINOR_VER "1"
    
    #define TEMP_CHILD_ID 5
    #define HUM_CHILD_ID 6
    #define BATT_CHILD_ID 10
    
    #define batteryVoltage_PIN	A0		//analog input A0 on ATmega328 is battery voltage ( /2)
    #define LTC4067_CHRG_PIN	A1		//analog input A1 on ATmega 328 is /CHRG signal from LTC4067
    
    #define OLED_RST 4
    SSD1306_text oled(OLED_RST);
    
    const float VccMin        = 1.0*3.5;  // Minimum expected Vcc level, in Volts. Example for 1 rechargeable lithium-ion.
    const float VccMax        = 1.0*4.2;  // Maximum expected Vcc level, in Volts. 
    
    HTU21D SHT21;						  // Hum/Temp (SHT12)
    
    MySensor sensor_node(7,8);
    
    float lastTempSHT;					// SHT temp/hum
    float lastHumSHT;
    float lastBattVoltage;
    int lastBattPct = 0;
    float VccReference = 3.3;
    
    boolean charge = false;
    boolean timeReceived = false;
    unsigned long lastUpdate=0, lastRequest=0; 
    
    unsigned long SLEEP_TIME = 60000;  	//  60 sec sleep time between reads (seconds * 1000 milliseconds)
    
    MyMessage temperatureMsg(TEMP_CHILD_ID, V_TEMP);			// SHT temp (deg C)
    MyMessage humidityMsg(HUM_CHILD_ID, V_HUM);					// SHT hum (% rh)
    MyMessage batteryVoltageMsg(BATT_CHILD_ID, V_VOLTAGE);
    
    void setup()  
    {  
    	analogReference(DEFAULT);							// default external reference = 3.3v for Ceech board
    	VccReference = 3.323 ;								// measured Vcc input (on board LDO)
    	sensor_node.begin(NULL, 21);						// fixed node 21
    	Wire.begin();										// init I2C
    	SHT21.begin();										// initialize temp/hum				
      
    // Send the sketch version information to the gateway and Controller
    	sensor_node.sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER);
    
    	sensor_node.present(TEMP_CHILD_ID, S_TEMP);			// SHT temp
    	sensor_node.present(HUM_CHILD_ID, S_HUM);			// SHT humidity
    	sensor_node.present(BATT_CHILD_ID, S_POWER);		// Battery parameters
      
    	sensor_node.requestTime(receiveTime);
    
    // Initialize, optionally clear the screen
        oled.init();
        oled.clear();                 // clear screen
        
        oled.setTextSize(1,1);
        oled.setCursor(0);
        oled.print("NODE_2");
    
    }
    
    void receiveTime(unsigned long controllerTime) {
    	setTime(controllerTime);
    	timeReceived = true;
    }
    
    void loop() 
    {
      
    	unsigned long now = millis();
    	sensor_node.process();
      
    	sensor_node.requestTime(receiveTime);  
    	lastRequest = now;
      
    	Serial.print(hour());
    	printDigits(minute());
    	printDigits(second());
    	Serial.println(); 
    
    	oled.setTextSize(2,1);
    	oled.setCursor(0,66);
    	//oled.print("      ");
    	if (hour() < 10) {
    		oled.print("0");
    	}
    	oled.print(hour());
    	oled.print(":");
    	if (minute() < 10) {
    		oled.print("0");
    	}
    	oled.print(minute());
    
    	sendTempHum();
    	Serial.println();
    	sendVoltage();
      
    	// Sleep until something happens with the sensor
    	sensor_node.sleep(SLEEP_TIME);
    } 
    
    void sendTempHum(void)
    {
    	// SHT2x sensor
    	// Temperature and Humidity
    	float humidity = SHT21.readHumidity();
    	// send to MySensor network / only if change
    	if (humidity != lastHumSHT && humidity != 0.00) {
    		lastHumSHT = humidity;
    		sensor_node.send(humidityMsg.set(humidity, 2));  // Send
    	}
    	 
    	float temperatureSHT = SHT21.readTemperature();
    	// send to MySensor network / only if change
    	if (temperatureSHT != lastTempSHT && temperatureSHT != 0.00) {
    		lastTempSHT = temperatureSHT;
    	 	sensor_node.send(temperatureMsg.set(temperatureSHT, 2));  // Send
    	}
    	
    	Serial.print("SHT21 temp: ");
    	Serial.print(temperatureSHT);
    	Serial.print(" SHT21 hum: ");
    	Serial.print(humidity);
    	
    	oled.setCursor(2);
    	oled.print("Temp: ");
    	oled.print(temperatureSHT,1);
    	oled.print("C");
    	oled.setCursor(4);
    	oled.print("Hum : ");
    	oled.print(humidity,0);
    	oled.print("%");
      
    }
    
    void sendVoltage(void)
    // battery values
    {
    	// get Battery Voltage
    	float batteryVoltage = ((float)analogRead(batteryVoltage_PIN)* VccReference/1024) * 2;	// actual voltage is double
    	Serial.print("Batt: ");
    	Serial.print(batteryVoltage);
    	Serial.print("V ; ");
    	
    	// send battery percentage for node
    	int battPct = 1 ;
    	if (batteryVoltage > VccMin){
    		battPct = 100.0*(batteryVoltage - VccMin)/(VccMax - VccMin);
    	}
    	
    	charge = digitalRead(LTC4067_CHRG_PIN);
    	
    	sensor_node.send(batteryVoltageMsg.set(batteryVoltage, 3));  		// Send (V)
    	sensor_node.sendBatteryLevel(battPct);
    	
    	Serial.print("BattPct: ");
    	Serial.print(battPct);
    	Serial.println("% ");
    
    	oled.setCursor(6);
    	oled.print("Batt: ");
    	oled.print(batteryVoltage,1);
    	oled.print("V");
    	if (charge)
    		oled.print("*");
    	else
    		oled.print(" ");
    
    }
    
    void printDigits(int digits){
      // utility function for digital clock display: prints preceding colon and leading 0
      Serial.print(":");
      if(digits < 10)
        Serial.print('0');
      Serial.print(digits);
    }
    
    

    It requires the attached libraries.

    SSD1306_text.zip

    WRT the display: I've found that there are different drivers for different size displays, which require corresponding different libraries. There is a 0.96" version, which I originally used, which used the SSD1306 driver and library, whereas many of the 1.3" versions use the SH1106. All I know is that the 1.3" display I use worked straight away, with the original library - YMMV.



  • @MikeF Maybe an idea about turning on the display.. how about adding a PIR, and turn on the display if movement is detected..? My guess is that it'll lower the power consumption, and still show info when someone is nearby.


  • Mod

    Very nice! And I love @Stric's idea to use a PIR. The display only uses 5-13mA (source) but a pir uses even less.



  • I've since added a simple on/off switch, connected to D2, and changed the sketch to read the state of this pin and send a sleep/wake command to the SSD1306.



  • I experienced some burn in effect on this SSD1306 displays after a few months of running, so turning the display off is a good idea!


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.