initial commit: copied code from arduino-esp project
This commit is contained in:
commit
77cae4847c
14 changed files with 1373 additions and 0 deletions
5
main/component.mk
Normal file
5
main/component.mk
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
294
main/esp32-sensornode_main.cpp
Normal file
294
main/esp32-sensornode_main.cpp
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* ESP32 Environmental Sensor Node with SI7021s (Temp + Hum)
|
||||
*
|
||||
* copyright: Jannik Beyerstedt | https://jannikbeyerstedt.de | code@jannikbeyerstedt.de
|
||||
* license: http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 License
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "si7021.hpp"
|
||||
#include <WiFi.h>
|
||||
#include <driver/adc.h>
|
||||
|
||||
#define BOARD_HUZZAH 1 /* Adafruit Feather HUZZAH */
|
||||
#define BOARD_LOLIN 2 /* LoLin NodeMCU */
|
||||
#define BOARD_ESP07S 3 /* standalone ESP07S */
|
||||
#define BOARD_ESP32 4 /* standalone ESP32 */
|
||||
|
||||
/* DEBUG SETTINGS */
|
||||
#define TEST /* use test config and database */
|
||||
#define PRINT_INFO /* enable Serial output */
|
||||
#define PRINT_DEBUG /* enable additional debug output */
|
||||
|
||||
/* CONFIGURATION OPTIONS */
|
||||
#ifndef NODENAME
|
||||
#define NODENAME "env-esp32-01" /* IMPORTANT: CHANGE FOR EACH DEVICE */
|
||||
#endif
|
||||
|
||||
#ifndef BOARD
|
||||
#define BOARD 4 /* IMPORTANT: select one of the BOARD_* types */
|
||||
#endif
|
||||
|
||||
#define DB_HOSTNAME "ursaminor.fra80"
|
||||
#define DB_PASSWD "c2Vuc29yczpTZW5zb3JzLXcuaW5mbHV4QGhvbWU" // BasicAuth String
|
||||
|
||||
#if BOARD == BOARD_ESP32
|
||||
#define BATT_FULL 2812 // TODO: get actual value
|
||||
#define BATT_CUTOFF 2280 // TODO: get actual value
|
||||
#else
|
||||
#error "unsupported board chosen"
|
||||
#endif
|
||||
|
||||
/* SETTINGS */
|
||||
float tempOffset = +0.0;
|
||||
float humiOffset = +0.0;
|
||||
|
||||
const char* host = DB_HOSTNAME;
|
||||
const int httpPort = 8086;
|
||||
|
||||
const char* wlan_ssid = "WLAN-Bey-IoT";
|
||||
const char* wlan_passwd = "IoT-Fra80";
|
||||
|
||||
#ifndef TEST
|
||||
String loggerName = NODENAME;
|
||||
const uint16_t sendInterval_sec = 1800; /* 1800 sec (30 min) */
|
||||
const uint8_t sampleAvgNum = 6; /* 6 (every 5 minutes) */
|
||||
const uint16_t sampleInterval_sec = sendInterval_sec / sampleAvgNum;
|
||||
String serviceUri = "/write?db=sensors";
|
||||
#else
|
||||
String loggerName = "esp-test";
|
||||
const uint16_t sendInterval_sec = 180; /* 180 sec (3 min) */
|
||||
const uint8_t sampleAvgNum = 6; /* 3 (every 1 minute) */
|
||||
const uint16_t sampleInterval_sec = sendInterval_sec / sampleAvgNum;
|
||||
String serviceUri = "/write?db=test";
|
||||
#endif
|
||||
|
||||
/* GLOBAL VARIABLES */
|
||||
const unsigned int wifiConnectTimeout = 30; /* num of 500ms intervals */
|
||||
|
||||
Si7021 si7021 = Si7021();
|
||||
float temp = 0.0;
|
||||
float humi = 0.0;
|
||||
|
||||
uint16_t battLevel = 0;
|
||||
float battPerc = 0.0;
|
||||
|
||||
RTC_DATA_ATTR uint8_t sampleCnt = 0;
|
||||
RTC_DATA_ATTR float tempAccu = 0.0; // for average value
|
||||
RTC_DATA_ATTR float humiAccu = 0.0; // for average value
|
||||
|
||||
#ifdef PRINT_INFO
|
||||
#define INFO_PRINT(x) Serial.print(x)
|
||||
#define INFO_PRINTLN(x) Serial.println(x)
|
||||
#else
|
||||
#define INFO_PRINT(x)
|
||||
#define INFO_PRINTLN(x)
|
||||
#endif
|
||||
|
||||
#if defined(PRINT_INFO) && defined(PRINT_DEBUG)
|
||||
#define DEBUG_PRINT(x) Serial.print(x)
|
||||
#define DEBUG_PRINTLN(x) Serial.println(x)
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#define DEBUG_PRINTLN(x)
|
||||
#endif
|
||||
|
||||
/* GLOBAL FUNCTIONS */
|
||||
bool wlanConnect(void) {
|
||||
unsigned int cycles = 0;
|
||||
|
||||
INFO_PRINT("[INFO ] Connecting to WiFi");
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(wlan_ssid, wlan_passwd);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
INFO_PRINT(".");
|
||||
|
||||
cycles++;
|
||||
if (cycles > wifiConnectTimeout) {
|
||||
INFO_PRINTLN(" FAILED");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
INFO_PRINT(" ok, IP: ");
|
||||
INFO_PRINTLN(WiFi.localIP());
|
||||
return true;
|
||||
}
|
||||
|
||||
void doDeepSleep(uint16_t durationSec) {
|
||||
esp_sleep_enable_timer_wakeup(durationSec * 1000000);
|
||||
// esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); // TODO more fine grained settings
|
||||
#ifdef PRINT_DEBUG
|
||||
Serial.printf("[DEBUG] Going to deep sleep for %d seconds\n", durationSec);
|
||||
#endif
|
||||
#ifdef PRINT_INFO
|
||||
delay(100); // time to send the messages via Serial
|
||||
#endif
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
void printWakeupReason() {
|
||||
esp_sleep_wakeup_cause_t wakeup_reason;
|
||||
wakeup_reason = esp_sleep_get_wakeup_cause();
|
||||
switch (wakeup_reason) {
|
||||
case 1:
|
||||
DEBUG_PRINTLN("[DEBUG] Wakeup caused by external signal using RTC_IO");
|
||||
break;
|
||||
case 2:
|
||||
DEBUG_PRINTLN("[DEBUG] Wakeup caused by external signal using RTC_CNTL");
|
||||
break;
|
||||
case 3:
|
||||
DEBUG_PRINTLN("[DEBUG] Wakeup caused by timer");
|
||||
break;
|
||||
case 4:
|
||||
DEBUG_PRINTLN("[DEBUG] Wakeup caused by touchpad");
|
||||
break;
|
||||
case 5:
|
||||
DEBUG_PRINTLN("[DEBUG] Wakeup caused by ULP program");
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINTLN("[DEBUG] Wakeup was not caused by deep sleep");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void app_main() {
|
||||
initArduino();
|
||||
pinMode(4, OUTPUT);
|
||||
digitalWrite(4, HIGH);
|
||||
//do your own thing
|
||||
|
||||
#ifdef PRINT_INFO
|
||||
Serial.begin(115200);
|
||||
delay(100);
|
||||
Serial.println("");
|
||||
|
||||
Serial.print("[INFO ] Node ");
|
||||
Serial.print(loggerName);
|
||||
Serial.print(", BoardType: ");
|
||||
Serial.println(BOARD);
|
||||
#endif
|
||||
#ifdef PRINT_DEBUG
|
||||
printWakeupReason();
|
||||
#endif
|
||||
|
||||
// switch WiFi off for the moment
|
||||
DEBUG_PRINTLN("[DEBUG] Turning wifi off for now");
|
||||
WiFi.mode(WIFI_OFF);
|
||||
|
||||
// setup the si7021 sensor
|
||||
if (false == si7021.begin()) {
|
||||
INFO_PRINTLN("[ERROR] SI7021 not set up properly");
|
||||
}
|
||||
|
||||
// setup the adc for VCC measurement
|
||||
// TODO!
|
||||
adc1_config_width(ADC_WIDTH_12Bit);
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_11db); // 11dB ~ max 3.14V = 4069
|
||||
|
||||
/* GET VALUE SAMPLES */
|
||||
// measure environmental data from si7021
|
||||
if (false == si7021.measure()) {
|
||||
INFO_PRINT("[ERROR] SI7021 measurement failed");
|
||||
}
|
||||
humi = si7021.humidity + humiOffset;
|
||||
temp = si7021.temperature + tempOffset;
|
||||
|
||||
// measure battery level
|
||||
battLevel = adc1_get_raw(ADC1_CHANNEL_0); // ADC0 = GPIO36 = VP = pin 4 (after en)
|
||||
battPerc = (0 == battLevel) ? 0 : 100.0 * (battLevel - BATT_CUTOFF) / (BATT_FULL - BATT_CUTOFF);
|
||||
|
||||
#ifdef PRINT_INFO
|
||||
Serial.printf("[INFO ] > Humidity: %5.2f Temperature: %5.2f", humi, temp);
|
||||
Serial.printf(" Battery Bat: %5.1f /100 (raw: %4d)\n", battPerc, battLevel);
|
||||
#endif
|
||||
|
||||
/* ---------- MAIN LOGIC START ---------- */
|
||||
// accumulate and average $sampleAvgNum samples before sending data
|
||||
if (sampleCnt < sampleAvgNum) {
|
||||
sampleCnt++;
|
||||
tempAccu += temp;
|
||||
humiAccu += humi;
|
||||
}
|
||||
|
||||
// calculate average and send data, if $sampleAvgNum are reached
|
||||
if (sampleCnt >= sampleAvgNum) {
|
||||
|
||||
INFO_PRINTLN("[INFO ] Enough samples collected -> send average to database");
|
||||
temp = tempAccu / (float)sampleCnt;
|
||||
humi = humiAccu / (float)sampleCnt;
|
||||
sampleCnt = 0;
|
||||
tempAccu = 0;
|
||||
humiAccu = 0;
|
||||
#ifdef PRINT_INFO
|
||||
Serial.printf("[INFO ] < Humidity: %5.2f Temperature: %5.2f\n", humi, temp);
|
||||
#endif
|
||||
|
||||
// turn wifi on again
|
||||
DEBUG_PRINTLN("[DEBUG] Turning wifi on again and connecting");
|
||||
if (wlanConnect()) {
|
||||
|
||||
// send data to influxdb
|
||||
String influxDataLine = "weather,sensor=" + loggerName + " temp=" + String(temp, 2);
|
||||
influxDataLine += ",hum=" + String(humi, 2);
|
||||
influxDataLine += ",batRaw=" + String(battLevel);
|
||||
influxDataLine += ",bat=" + String(battPerc);
|
||||
|
||||
INFO_PRINT("[INFO ] Connecting to ");
|
||||
INFO_PRINT(host);
|
||||
WiFiClient client;
|
||||
if (client.connect(host, httpPort)) {
|
||||
INFO_PRINTLN(" > success");
|
||||
|
||||
String httpRequest = "POST " + serviceUri + " HTTP/1.1\r\n" + "Host: " + host + ":" + httpPort +
|
||||
"\r\n" + "Content-Length: " + influxDataLine.length() + "\r\n" +
|
||||
"Authorization: Basic " + DB_PASSWD + "=\r\n" + "Connection: close\r\n" +
|
||||
"\r\n" + influxDataLine + "\r\n";
|
||||
client.print(httpRequest);
|
||||
delay(100);
|
||||
|
||||
while (client.available()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line.indexOf("HTTP") != -1) {
|
||||
if (line.indexOf("204") == -1) { // expect a HTTP 204 status code
|
||||
INFO_PRINTLN("[ERROR]: invalid http status code");
|
||||
INFO_PRINTLN(line);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
INFO_PRINTLN(" > FAILED");
|
||||
}
|
||||
client.stop();
|
||||
WiFi.disconnect(true);
|
||||
// continue with deep sleep at end of main function
|
||||
|
||||
} else { // ELSE: !wifiConnect
|
||||
|
||||
/* WIFI CONNECT FAILED, WAIT MAX 5 MINUTES IN DEEP SLEEP */
|
||||
INFO_PRINTLN("[INFO ] WiFi connect failed -> wait a bit and try again");
|
||||
if (sendInterval_sec > (5 * 60)) {
|
||||
doDeepSleep(5 * 60);
|
||||
} else {
|
||||
doDeepSleep(sendInterval_sec);
|
||||
}
|
||||
} // ENDIF: wifiConnect
|
||||
|
||||
} else { // ELSE: sampleCnt < sampleAvgNum
|
||||
|
||||
#ifdef PRINT_INFO
|
||||
Serial.printf("[INFO ] %d of %d samples collected -> sleep\n", sampleCnt, sampleAvgNum);
|
||||
// continue with deep sleep at end of main function
|
||||
#endif
|
||||
|
||||
} // ENDIF: sampleCnt
|
||||
/* ---------- MAIN LOGIC END ---------- */
|
||||
|
||||
/* SAVE ENERGY BY WAITING IN DEEP SLEEP */
|
||||
doDeepSleep(sampleInterval_sec);
|
||||
}
|
121
main/si7021.cpp
Normal file
121
main/si7021.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* si7021 library
|
||||
* SI7021 Temperature and Humidity Sensor @ ESP32 i2c
|
||||
*
|
||||
* copyright: Jannik Beyerstedt | http://jannikbeyerstedt.de | code@jannikbeyerstedt.de
|
||||
* license: http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 License
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#include "si7021.hpp"
|
||||
|
||||
/**
|
||||
* Constuctor of the SI7021 sensor wrapper
|
||||
*/
|
||||
Si7021::Si7021(void) {
|
||||
_i2caddr = SI7021_DEFAULT_ADDRESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the I2C interface
|
||||
* Attention: leave at least 25 ms power up time before the first measurement
|
||||
*/
|
||||
bool Si7021::begin(void) {
|
||||
Wire.begin();
|
||||
Wire.setClock(200000);
|
||||
|
||||
reset();
|
||||
|
||||
if (readRegister8(SI7021_READRHT_REG_CMD) != 0x3A) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a reset command to the sensor
|
||||
*/
|
||||
void Si7021::reset(void) {
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write((uint8_t)SI7021_RESET_CMD);
|
||||
Wire.endTransmission(true);
|
||||
delay(10); // SI7021 reset time
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a humidity and temperature measurement
|
||||
* Get the values from the public variables temperature and humudity
|
||||
*
|
||||
* @return true, if successful measurement
|
||||
*/
|
||||
bool Si7021::measure(void) {
|
||||
uint8_t chxsum;
|
||||
uint8_t cnt;
|
||||
|
||||
// TRIGGER HUMIDITY MEASUREMENT AND GET VALUE
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write((uint8_t)SI7021_MEASRH_NOHOLD_CMD);
|
||||
Wire.endTransmission(true); // true, otherwise the read will not work
|
||||
|
||||
delay(23); // wait for the Conversion Time of the Sensor
|
||||
cnt = Wire.requestFrom(_i2caddr, 3);
|
||||
if (cnt < 3) {
|
||||
// Serial.printf("[ERROR] SI7021 humi, only %d bytes received\n", cnt);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t hum_raw = Wire.read();
|
||||
hum_raw <<= 8;
|
||||
hum_raw |= Wire.read();
|
||||
chxsum = Wire.read();
|
||||
|
||||
this->humidity = hum_raw;
|
||||
this->humidity *= 125;
|
||||
this->humidity /= 65536;
|
||||
this->humidity -= 6;
|
||||
|
||||
// GET TEMPERATURE VALUE OF PREVIOUS HUMIDITY MEASUREMENT
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write((uint8_t)SI7021_READPREVTEMP_CMD);
|
||||
Wire.endTransmission(true); // true, otherwise the read will not work
|
||||
|
||||
cnt = Wire.requestFrom(_i2caddr, 3);
|
||||
if (cnt < 3) {
|
||||
// Serial.printf("[ERROR] SI7021 temp, only %d bytes received\n", cnt);
|
||||
return false;
|
||||
}
|
||||
uint16_t temp_raw = Wire.read();
|
||||
temp_raw <<= 8;
|
||||
temp_raw |= Wire.read();
|
||||
chxsum = Wire.read();
|
||||
|
||||
this->temperature = temp_raw;
|
||||
this->temperature *= 175.72;
|
||||
this->temperature /= 65536;
|
||||
this->temperature -= 46.85;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// void Si7021::writeRegister8(uint8_t reg, uint8_t value) {
|
||||
// // TODO: Test
|
||||
// Wire.beginTransmission(_i2caddr);
|
||||
// Wire.write((uint8_t)reg);
|
||||
// Wire.write((uint8_t)value);
|
||||
// Wire.endTransmission();
|
||||
// }
|
||||
|
||||
uint8_t Si7021::readRegister8(uint8_t reg) {
|
||||
uint8_t value;
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.endTransmission(true); // true, otherwise the value does not get read
|
||||
|
||||
Wire.requestFrom(_i2caddr, 1);
|
||||
value = Wire.read();
|
||||
|
||||
return value;
|
||||
}
|
47
main/si7021.hpp
Normal file
47
main/si7021.hpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* si7021 library
|
||||
* SI7021 Temperature and Humidity Sensor @ ESP32 i2c
|
||||
*
|
||||
* copyright: Jannik Beyerstedt | http://jannikbeyerstedt.de | code@jannikbeyerstedt.de
|
||||
* license: http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 License
|
||||
*/
|
||||
|
||||
#ifndef SI7021_H
|
||||
#define SI7021_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define SI7021_DEFAULT_ADDRESS (0x40)
|
||||
|
||||
#define SI7021_MEASRH_HOLD_CMD 0xE5
|
||||
#define SI7021_MEASTEMP_HOLD_CMD 0xE3
|
||||
#define SI7021_MEASRH_NOHOLD_CMD 0xF5
|
||||
#define SI7021_MEASTEMP_NOHOLD_CMD 0xF3
|
||||
#define SI7021_READPREVTEMP_CMD 0xE0
|
||||
#define SI7021_RESET_CMD 0xFE
|
||||
#define SI7021_READRHT_REG_CMD 0xE7
|
||||
// #define SI7021_WRITERHT_REG_CMD 0xE6
|
||||
// #define SI7021_READHEATER_REG_CMD 0x11
|
||||
// #define SI7021_WRITEHEATER_REG_CMD 0x51
|
||||
// #define SI7021_ID1_CMD 0xFA0F
|
||||
// #define SI7021_ID2_CMD 0xFCC9
|
||||
// #define SI7021_FIRMVERS_CMD 0x84B8
|
||||
|
||||
class Si7021 {
|
||||
public:
|
||||
Si7021(void);
|
||||
bool begin(void);
|
||||
void reset(void);
|
||||
|
||||
bool measure(void);
|
||||
float temperature;
|
||||
float humidity;
|
||||
|
||||
private:
|
||||
// void writeRegister8(uint8_t reg, uint8_t value);
|
||||
uint8_t readRegister8(uint8_t reg);
|
||||
|
||||
int8_t _i2caddr;
|
||||
};
|
||||
|
||||
#endif // SI7021_H
|
Loading…
Add table
Add a link
Reference in a new issue