Created
June 4, 2022 09:31
-
-
Save hggh/6c33a130d9df5d71e38edde374a77777 to your computer and use it in GitHub Desktop.
ESP32-S2 deep sleep with bme280
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
#include <Arduino.h> | |
#include <Wire.h> | |
#include <WiFi.h> | |
#include <MQTT.h> | |
#include <SparkFunBME280.h> | |
#include <esp_wifi.h> | |
#include "esp_sleep.h" | |
#include <driver/adc_common.h> | |
#include "driver/adc.h" | |
#include "esp_adc_cal.h" | |
#include "esp_wifi.h" | |
#include <driver/adc_common.h> | |
#include "driver/gpio.h" | |
#include "driver/rtc_io.h" | |
BME280 bme; | |
WiFiClient wifi; | |
MQTTClient mqtt; | |
RTC_DATA_ATTR unsigned int status_boot_count = 0; | |
RTC_DATA_ATTR unsigned int status_wifi_errors = 0; | |
//#define DEBUG 1 | |
#define uS_TO_S_FACTOR 1000000 | |
#define DEFAULT_VREF 3300 | |
#define NO_OF_SAMPLES 10 | |
#define ADC_LIC_PIN GPIO_NUM_6 | |
#define ADC_SOLAR_PIN GPIO_NUM_4 | |
adc_channel_t adc_lic_pin_channel = ADC_CHANNEL_5; | |
adc_channel_t adc_solar_pin_channel = ADC_CHANNEL_3; | |
#define MQTT_SERVER "xx.xx.xx.xx" | |
#define MQTT_USERNAME "xx" | |
#define MQTT_PASSWORD "x" | |
const char* ssid = "xx-xx"; | |
const char* password = "xx"; | |
IPAddress ip_ip(x, xx, xx, xx); | |
IPAddress ip_gateway(x, x, x, 1); | |
IPAddress ip_dns(x, x, x, 1); | |
IPAddress ip_subnet(255, 255, 255, 0); | |
int get_wakeup_reason() { | |
esp_sleep_wakeup_cause_t wakeup_reason; | |
wakeup_reason = esp_sleep_get_wakeup_cause(); | |
#ifdef DEBUG | |
switch(wakeup_reason) | |
{ | |
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break; | |
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break; | |
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break; | |
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break; | |
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break; | |
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break; | |
} | |
#endif | |
return wakeup_reason; | |
} | |
float get_voltage(adc_channel_t channel, gpio_num_t pin) { | |
static float volt_r1 = 1000000.0; | |
static float volt_r2 = 1000000.0; | |
static esp_adc_cal_characteristics_t adc_chars; | |
static const adc_bits_width_t width = ADC_WIDTH_BIT_13; | |
static const adc_atten_t atten = ADC_ATTEN_DB_11; | |
adc_power_acquire(); | |
gpio_reset_pin(pin); | |
gpio_set_direction(pin, GPIO_MODE_INPUT); | |
adc1_config_width(width); | |
adc1_config_channel_atten((adc1_channel_t)channel, atten); | |
esp_adc_cal_characterize(ADC_UNIT_1, atten, width, DEFAULT_VREF, &adc_chars); | |
uint32_t adc_reading = 0; | |
for (int i = 0; i < NO_OF_SAMPLES; i++) { | |
adc_reading += adc1_get_raw((adc1_channel_t)channel); | |
} | |
adc_reading /= NO_OF_SAMPLES; | |
// get mV | |
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, &adc_chars); | |
float real_voltage = (voltage / 1000.0) / (volt_r2 / ( volt_r1 + volt_r2)); | |
adc_power_release(); | |
rtc_gpio_isolate(pin); | |
return real_voltage; | |
} | |
void goto_sleep() { | |
bme.setMode(MODE_SLEEP); | |
mqtt.disconnect(); | |
delay(1); | |
WiFi.disconnect(); | |
WiFi.mode(WIFI_OFF); | |
esp_wifi_stop(); | |
adc_power_off(); | |
esp_sleep_enable_timer_wakeup((uint64_t)15 * (uint64_t)60 * (uint64_t)uS_TO_S_FACTOR); | |
esp_deep_sleep_start(); | |
} | |
void setup() { | |
adc_power_on(); | |
++status_boot_count; | |
setCpuFrequencyMhz(80); | |
#ifdef DEBUG | |
Serial.begin(115200); | |
#endif | |
get_wakeup_reason(); | |
Wire.begin(); | |
bme.setI2CAddress(0x76); | |
bme.beginI2C(); | |
bme.setMode(MODE_SLEEP); | |
bme.setMode(MODE_FORCED); | |
WiFi.mode(WIFI_STA); | |
WiFi.persistent(false); | |
WiFi.setHostname("weatherstation"); | |
WiFi.config(ip_ip, ip_gateway, ip_subnet, ip_dns, ip_dns); | |
WiFi.begin(ssid, password); | |
bool wifi_ok = false; | |
for(int i=0; i < 2000; i++) { | |
if (WiFi.status() == WL_CONNECTED) { | |
wifi_ok = true; | |
break; | |
} | |
delay(1); | |
#ifdef DEBUG | |
Serial.print("."); | |
#endif | |
} | |
if (wifi_ok == false) { | |
status_wifi_errors++; | |
goto_sleep(); | |
} | |
float volt_solar = get_voltage(adc_solar_pin_channel, ADC_SOLAR_PIN); | |
float volt_lic = get_voltage(adc_lic_pin_channel, ADC_LIC_PIN); | |
mqtt.begin(MQTT_SERVER, wifi); | |
mqtt.setTimeout(5); | |
mqtt.connect("weatherstation", MQTT_USERNAME, MQTT_PASSWORD); | |
mqtt.loop(); | |
mqtt.publish("/weatherstation/bootcount/state", String(status_boot_count).c_str(), false, 1); | |
mqtt.publish("/weatherstation/wifierrors/state", String(status_wifi_errors).c_str()), false, 1; | |
mqtt.publish("/weatherstation/humidity/state", String(bme.readFloatHumidity()).c_str(), false, 1); | |
mqtt.publish("/weatherstation/temperature/state", String(bme.readTempC()).c_str(), false, 1); | |
mqtt.publish("/weatherstation/pressure/state", String(bme.readFloatPressure() / 100.0).c_str(), false, 1); | |
mqtt.publish("/weatherstation/volt_solar/state", String(volt_solar).c_str(), false, 1); | |
mqtt.publish("/weatherstation/volt_lic/state", String(volt_lic).c_str(), false, 1); | |
wifi.flush(); | |
mqtt.loop(); | |
#ifdef DEBUG | |
Serial.print("BootCount: "); | |
Serial.println(status_boot_count); | |
Serial.print("volt_solar: "); | |
Serial.println(volt_solar); | |
Serial.print("volt_lic: "); | |
Serial.println(volt_lic); | |
#endif | |
goto_sleep(); | |
} | |
void loop() { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment