Created
May 2, 2020 16:53
-
-
Save dadosch/71253c0f5f52be0457114451374d28f6 to your computer and use it in GitHub Desktop.
esp8266 with CCS811 and deep sleep
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const int FW_VERSION = 01; | |
const char* fwUrlBase = "http://someurl.tld/esp_update/"; | |
#include "main.h" | |
#include <Arduino.h> | |
#include <ESP8266WiFi.h> | |
#include <PubSubClient.h> | |
//needed for WifiManager | |
#include <DNSServer.h> | |
#include <ESP8266WebServer.h> | |
#include <WiFiManager.h> | |
// for firmware update | |
#include <ESP8266HTTPClient.h> | |
#include <ESP8266httpUpdate.h> | |
#ifdef USE_BMP180 | |
// I2C: 0x77 | |
#include <Wire.h> | |
#include <Adafruit_BMP085.h> | |
Adafruit_BMP085 bmp; | |
boolean bmp180_available=true; | |
#endif | |
#ifdef USE_BME280 | |
// I2C: 0x76 | |
#include <BME280I2C.h> | |
#include <Wire.h> | |
BME280I2C::Settings bme280Settings( | |
BME280::OSR_X1, | |
BME280::OSR_X1, | |
BME280::OSR_X1, | |
BME280::Mode_Forced, | |
BME280::StandbyTime_1000ms, | |
BME280::Filter_Off, | |
BME280::SpiEnable_False, | |
BME280I2C::I2CAddr_0x76 // I2C address. I2C specific. | |
); | |
BME280I2C bme280(bme280Settings); | |
boolean bme280_available=true; | |
#endif | |
#ifdef USE_BH1750 | |
// I2C: 0x23 | |
#include <Wire.h> | |
#include <BH1750.h> | |
BH1750 bh1750(0x23); | |
boolean bh1750_available=true; | |
#endif | |
#ifdef USE_CCS811 | |
#include <Wire.h> // I2C library | |
// I2C: 0x5A | |
#include <ccs811.h> | |
CCS811 ccs811; | |
boolean ccs811_available=true; | |
#endif | |
WiFiClient wifiClient; | |
PubSubClient mqttClient(wifiClient); | |
const String MQTT_USERNAME = "user"; | |
const String MQTT_PASSWORD = "pass"; | |
ADC_MODE(ADC_VCC); | |
String macToStr(const uint8_t* mac){ | |
String result; | |
for (int i = 0; i < 6; ++i) { | |
result += String(mac[i], 16); | |
} | |
return result; | |
} | |
String getMAC(){ | |
String clientMac = ""; | |
unsigned char mac[6]; | |
WiFi.macAddress(mac); | |
clientMac += macToStr(mac); | |
return String( clientMac ); | |
} | |
void checkForUpdates() { | |
String mac = getMAC(); | |
String fwURL = String( fwUrlBase ); | |
fwURL.concat( mac ); | |
String fwVersionURL = fwURL; | |
fwVersionURL.concat( ".version" ); | |
Serial.println( "Checking for firmware updates." ); | |
Serial.print( "MAC address: " ); | |
Serial.println( mac ); | |
Serial.print( "Firmware version URL: " ); | |
Serial.println( fwVersionURL ); | |
HTTPClient httpClient; | |
httpClient.begin(wifiClient, fwVersionURL ); | |
int httpCode = httpClient.GET(); | |
if( httpCode == 200 ) { | |
String newFWVersion = httpClient.getString(); | |
Serial.print( "Current firmware version: " ); | |
Serial.println( FW_VERSION ); | |
Serial.print( "Available firmware version: " ); | |
Serial.println( newFWVersion ); | |
int newVersion = newFWVersion.toInt(); | |
if( newVersion > FW_VERSION ) { | |
Serial.println( "Preparing to update" ); | |
String fwImageURL = fwURL; | |
fwImageURL.concat( ".bin" ); | |
t_httpUpdate_return ret = ESPhttpUpdate.update(wifiClient, fwImageURL ); | |
switch(ret) { | |
case HTTP_UPDATE_FAILED: | |
Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); | |
break; | |
case HTTP_UPDATE_NO_UPDATES: | |
Serial.println("HTTP_UPDATE_NO_UPDATES"); | |
break; | |
case HTTP_UPDATE_OK: | |
break; | |
} | |
} | |
else { | |
Serial.println( "Already on latest version" ); | |
} | |
} | |
else { | |
Serial.print( "Firmware version check failed, got HTTP response code " ); | |
Serial.println( httpCode ); | |
} | |
httpClient.end(); | |
} | |
void connectWiFiAndMqtt(){ | |
Serial.println("now starting WiFiManager…"); | |
WiFiManager wifiManager; | |
wifiManager.autoConnect(); | |
Serial.println("WiFiManager started and connected."); | |
checkForUpdates(); | |
Serial.println("now starting MQTT…"); | |
mqttClient.setServer("host", 1883); | |
while(! mqttClient.connected()){ | |
Serial.print("connecting..."); | |
String clientId = "sensorhub-"; | |
clientId += String(ESP.getChipId()); | |
mqttClient.connect(clientId.c_str(),MQTT_USERNAME.c_str(),MQTT_PASSWORD.c_str()); | |
} | |
Serial.println("mqtt connected."); | |
} | |
void initializeSensors(){ | |
Serial.println("now starting sensors…"); | |
#ifdef USE_BH1750 | |
// Wire is not started by BH1750, but by Adafruit library. | |
Wire.begin(); | |
if(!bh1750.begin(BH1750::ONE_TIME_HIGH_RES_MODE)){ | |
Serial.println("Could not find a valid BH1750 sensor, check wiring!"); | |
bh1750_available=false; | |
} | |
#endif | |
#ifdef USE_BMP180 | |
if (!bmp.begin()) { | |
Serial.println("Could not find a valid BMP180 sensor, check wiring!"); | |
bmp180_available=false; | |
} | |
#endif | |
#ifdef USE_BME280 | |
Wire.begin(); | |
if(!bme280.begin()){ | |
Serial.println("Could not find a valid BME280 sensor, check wiring!"); | |
bme280_available=false; | |
} | |
#endif | |
#ifdef USE_CCS811 | |
Wire.begin(); | |
ccs811.set_i2cdelay(50); // Needed for ESP8266 because it doesn't handle I2C clock stretch correctly | |
rst_info * rstinfo = ESP.getResetInfoPtr(); | |
// when NOT coming out of deepsleep: | |
if (rstinfo->reason != REASON_DEEP_SLEEP_AWAKE){ | |
// setup ccs811 into correct mode | |
Serial.println("CCS811: setup begins."); | |
bool ok= ccs811.begin(); | |
if( !ok ) Serial.println("setup: CCS811 begin FAILED"); | |
ok= ccs811.start(CCS811_MODE_60SEC); | |
if( !ok ){ | |
// start failed! | |
Serial.println("setup: CCS811 start FAILED"); | |
} | |
}else{ | |
// we come out of deep sleep and ccs811 is in known state. | |
Serial.println("CCS811: setup already done."); | |
} | |
#endif | |
} | |
void submitSensorData(String sensorName, String whatIsMeasured,float value){ | |
Serial.println(sensorName+" Sensor data: "+whatIsMeasured + " " +String(value)); | |
String mqttId = String(ESP.getChipId()); | |
String topic = "sensors/"+mqttId; | |
String mqttValue = "{\""+whatIsMeasured+"\":"+String(value)+"}"; | |
mqttClient.publish(topic.c_str(), mqttValue.c_str()); | |
} | |
void runSensors(){ | |
#ifdef USE_BMP180 | |
if(bmp180_available){ | |
float bmp180_temp = bmp.readTemperature(); | |
float bmp180_press = bmp.readPressure(); | |
submitSensorData("bmp180","temp",bmp180_temp); | |
submitSensorData("bmp180","press",bmp180_press); | |
} | |
#endif | |
#ifdef USE_BME280 | |
if(bme280_available){ | |
float bme280_press, bme280_temp, bme280_hum; | |
bme280.read(bme280_press, bme280_temp, bme280_hum); | |
submitSensorData("bme280","press",bme280_press); | |
submitSensorData("bme280","temp",bme280_temp); | |
submitSensorData("bme280","hum",bme280_hum); | |
} | |
#endif | |
#ifdef USE_BH1750 | |
float bh1750_lightlevel = bh1750.readLightLevel(); | |
submitSensorData("bh1750","lightlevel",bh1750_lightlevel); | |
#endif | |
#ifdef USE_CCS811 | |
uint16_t eco2, etvoc, errstat, raw; | |
ccs811.read(&eco2,&etvoc,&errstat,&raw); | |
// Print measurement results based on status | |
if( errstat==CCS811_ERRSTAT_OK ) { | |
// everything is fine, we have new data | |
submitSensorData("ccs811","eco2",eco2); | |
submitSensorData("ccs811","etvoc",etvoc); | |
} else if( errstat==CCS811_ERRSTAT_OK_NODATA ) { | |
// everything is fine, but there is no new data yet.) | |
Serial.println("CCS811: waiting for (new) data"); | |
} else if( errstat & CCS811_ERRSTAT_I2CFAIL ) { | |
// I2C Connection failed | |
Serial.println("CCS811: I2C error"); | |
} else { | |
// other error | |
Serial.print("CCS811: errstat="); Serial.print(errstat,HEX); | |
Serial.print("="); Serial.println( ccs811.errstat_str(errstat) ); | |
} | |
#endif | |
// submit power supply (battery voltage) | |
float esp_vcc = ESP.getVcc(); | |
submitSensorData("esp8266","vcc",esp_vcc); | |
} | |
void setup() { | |
Serial.begin(115200); | |
Serial.println("sensor station started."); | |
connectWiFiAndMqtt(); | |
initializeSensors(); | |
runSensors(); | |
mqttClient.disconnect(); | |
Serial.println("going to sleep now!"); | |
//sleep 60 seconds, with 2 extra seconds, because ccs811's clock might be not too accurate. | |
ESP.deepSleep(62e6); | |
} | |
void loop() { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment