Bladeren bron

Working weather station, POSTing to RTDB

- Everything works overall
- Loading LEDs when connecting to wifi, or uploading data
- Sleeps for 30 seconds between reads
Jason Tarka 4 jaren geleden
commit
0f0a3be3b2
8 gewijzigde bestanden met toevoegingen van 392 en 0 verwijderingen
  1. 30 0
      01_humidity.ino
  2. 77 0
      01_leds.ino
  3. 54 0
      01_pressure.ino
  4. 8 0
      02_sleep.ino
  5. 33 0
      02_wifi.ino
  6. 103 0
      03_log_data.ino
  7. 54 0
      99_main.ino
  8. 33 0
      outdoor-weather-station.ino

+ 30 - 0
01_humidity.ino

@@ -0,0 +1,30 @@
+#include <Adafruit_AHTX0.h>
+
+Adafruit_AHTX0 aht;
+
+struct {
+public:
+	float temperature;
+	float humidity;
+} HumTemp;
+
+void initHumidity() {
+	debugln("Initializing humidity sensor");
+	
+	if (!aht.begin()) {
+		Serial.println("Could not initialize humidity sensor");
+		// TODO: Turn on the LED or screen or something
+		ERR;
+	}
+	debugln("Initialized humidity sensor");
+}
+
+void updateHumidity() {
+	sensors_event_t hum,
+		temp;
+
+	aht.getEvent(&hum, &temp);
+
+	HumTemp.temperature = temp.temperature;
+	HumTemp.humidity = hum.relative_humidity;
+}

+ 77 - 0
01_leds.ino

@@ -0,0 +1,77 @@
+#include <Adafruit_DotStar.h>
+
+#define NUM_DOTSTAR 5
+#define PROGRESS_NUM_STATES 10
+
+Adafruit_DotStar pixels(
+	NUM_DOTSTAR,
+	PIN_DOTSTAR_DATA,
+	PIN_DOTSTAR_CLOCK,
+	DOTSTAR_BRG
+);
+
+boolean ledsShowingProgress = false;
+int ledProgress = 0;
+
+const uint32_t PROGRESS_BLUE = pixels.Color(0, 0, 255),
+			   PROGRESS_GREEN = pixels.Color(255, 0, 0),
+			   PROGRESS_RED = pixels.Color(0, 255, 0);
+
+// Which LEDs should be lit up for a given position in the progress.
+// This could be calculated, but I have memory to spare, and this is
+// easier at the moment.
+uint16_t ledProgressMap[PROGRESS_NUM_STATES] = {
+	0b00000,
+	0b00001,
+	0b00011,
+	0b00111,
+	0b01111,
+	0b11111,
+	0b11110,
+	0b11100,
+	0b11000,
+	0b10000
+};
+
+void initLeds() {
+	pixels.begin();
+	pixels.show();
+	pixels.setBrightness(2);
+
+	hideProgress();
+}
+
+// Update LEDs to show loading, such as connecting to wifi
+void showProgress(uint32_t colour) {
+	if(!ledsShowingProgress) {
+		// Reset the progress display
+		ledProgress = 0;
+		ledsShowingProgress = true;
+	}
+
+	ledProgress = (ledProgress + 1) % PROGRESS_NUM_STATES;
+
+	for(byte i = 0; i < NUM_DOTSTAR; i++) {
+		boolean on = ((1 << i) & ledProgressMap[ledProgress]) > 0;
+		pixels.setPixelColor(
+				i,
+				on ? colour : 0
+			);
+	}
+
+	pixels.show();
+}
+
+// Turn off the LEDs
+void hideProgress() {
+	ledsShowingProgress = false;
+	for(byte i = 0; i < NUM_DOTSTAR; i++) {
+		pixels.setPixelColor(i, 0); 
+	}
+	pixels.show();
+}
+
+void showError() {
+	pixels.fill(PROGRESS_RED);
+	pixels.show();
+}

+ 54 - 0
01_pressure.ino

@@ -0,0 +1,54 @@
+#include <Adafruit_DPS310.h>
+
+Adafruit_DPS310 dps;
+Adafruit_Sensor *dps_temp = dps.getTemperatureSensor();
+Adafruit_Sensor *dps_pressure = dps.getPressureSensor();
+
+struct {
+	float pressure;
+	float temperature;
+} PressTemp;
+
+void initPressure() {
+	debugln("Initializing pressure sensor");
+
+	if (!dps.begin_I2C()) {
+		Serial.println("Failed to initialize pressure sensor!");
+		ERR;
+	}
+
+	// Set high precision
+	dps.configurePressure(DPS310_64HZ, DPS310_64SAMPLES);
+	dps.configureTemperature(DPS310_64HZ, DPS310_64SAMPLES);
+
+//	dps_temp->printSensorDetails();
+//	dps_pressure->printSensorDetails();
+
+	debugln("Initialized pressure sensor");
+}
+
+void updatePressure() {
+	sensors_event_t temp,
+		pressure;
+
+	debugln("Reading pressure & temperature");
+
+	// Wait until both are available, as reading temperature
+	// resets pressure availability, but both are still OK
+	// to read.
+	while (!dps.temperatureAvailable() || !dps.pressureAvailable()) {
+		debugln("Waiting...");
+		delay(1);
+	}
+	
+
+	// Docs say I need to read temperature first,
+	// though testing seems to show it doesn't matter.
+	dps_temp->getEvent(&temp);
+	PressTemp.temperature = temp.temperature;
+	
+	dps_pressure->getEvent(&pressure);
+	PressTemp.pressure = pressure.pressure;
+
+	debugln("Got temperature & pressure");
+}

+ 8 - 0
02_sleep.ino

@@ -0,0 +1,8 @@
+void deepSleep() {
+	hideProgress(); // Make sure the LEDs are turned off
+	
+	debuglog("Going to sleep for: ", SLEEP_TIME_US);
+	esp_sleep_enable_timer_wakeup(SLEEP_TIME_US);
+	Serial.flush();
+	esp_deep_sleep_start();
+}

+ 33 - 0
02_wifi.ino

@@ -0,0 +1,33 @@
+#include <WiFi.h>
+
+#define NETWORK "Guest WiFi Signal"
+#define PASSWORD "something easy"
+#define HOSTNAME "outdoor-weather-station"
+
+void connectWifi() {
+	WiFi.begin(NETWORK, PASSWORD);
+
+	debug("Connecting to wifi ..");
+	while (WiFi.status() != WL_CONNECTED) {
+		debug('.');
+		showProgress(PROGRESS_BLUE);
+		delay(500);
+	}
+
+	debugln();
+	debugln("Connected!");
+	debuglog("IP: 		", WiFi.localIP());
+	debuglog("Strength: ", WiFi.RSSI());
+	debuglog("DNS:		", WiFi.dnsIP());
+	debuglog("Gateway:	", WiFi.gatewayIP());
+}
+
+
+void initWifi() {
+	WiFi.mode(WIFI_STA);
+
+	// Set the hostname
+	WiFi.setHostname(HOSTNAME);
+
+	connectWifi();
+}

+ 103 - 0
03_log_data.ino

@@ -0,0 +1,103 @@
+#include <WiFi.h>
+#include <WiFiClientSecure.h>
+
+#define PROJECT "weather-station-58080"
+#define AUTH_TOKEN "aud8LdW1IeTWqcv77Ka1LJn5xSqambsJ9jYx5OEh"
+#define DATABASE_URL "https://weather-station-58080-default-rtdb.firebaseio.com"
+#define DATABASE_PATH "outdoor.json"
+
+#define PORT 443
+#define HOST "weather-station-58080-default-rtdb.firebaseio.com"
+const String WRITE_URL = String("https://") + HOST + "/" + DATABASE_PATH + "?auth=" + AUTH_TOKEN;
+
+void getSomething() {
+	showProgress(PROGRESS_GREEN);
+	String content = String("GET / HTTP/1.1\r\n")
+				+ "Host: example.com\r\n"
+				+ "User-Agent: ESP32/FunHouse/tarka-outdoor-weather-station" + "\r\n"
+				+ "Connection: close" + "\r\n";
+
+	WiFiClientSecure client;
+	client.setInsecure();
+	debugln("Connectiong to: example.com");
+	showProgress(PROGRESS_GREEN);
+
+	if(!client.connect("example.com", 443)) {
+		debugln("Connection failed!");
+		ERR;
+	}
+
+	debugln("Connection established. Sending headers & body.");
+	showProgress(PROGRESS_GREEN);
+	client.print(content);
+
+	// Wait for things to happen
+	showProgress(PROGRESS_GREEN);
+	delay(500);
+
+	while(client.available()) {
+		showProgress(PROGRESS_GREEN);
+		String line = client.readStringUntil('\n');
+		debuglog("Read line: ", line);
+	}
+	hideProgress();
+	debugln("===== Done =====");
+}
+
+boolean uploadData(
+	float temperature,
+	float pressure,
+	float humidity,
+	float light
+) {
+	showProgress(PROGRESS_GREEN);
+	String data = String("{")
+				+ "\t\"temperature\": " + temperature + ",\n"
+				+ "\t\"pressure\": " + pressure + ",\n"
+				+ "\t\"humidity\": " + humidity + ",\n"
+				+ "\t\"light\": " + light + ",\n"
+				+ "\t\"time\": { \".sv\": \"timestamp\" }\n"
+				+ "}";
+	debuglog("Content body: ", data);
+
+	String content = String("POST ") + RTDB_URL + " HTTP/1.1\r\n"
+				+ "Host: " + RTDB_HOST + "\r\n"
+				+ "User-Agent: ESP32/FunHouse/tarka-outdoor-weather-station" + "\r\n"
+				+ "Content-Type: application/x-www-form-urlencoded" + "\r\n"
+				+ "Accept: */*" + "\r\n"
+				+ "Content-Length: " + data.length() + "\r\n"
+				+ "Connection: close" + "\r\n"
+				+ "\r\n"
+				+ data;
+
+	debuglog("HTTP request: ", content);
+
+	WiFiClientSecure client;
+	client.setInsecure();
+	showProgress(PROGRESS_GREEN);
+	debuglog("Connectiong to: ", RTDB_HOST);
+
+	if(!client.connect(RTDB_HOST, PORT)) {
+		debugln("Connection failed!");
+		showError();
+		return false;
+	}
+
+	debugln("Connection established. Sending headers & body.");
+	showProgress(PROGRESS_GREEN);
+	client.print(content);
+
+	// Wait for things to happen
+	showProgress(PROGRESS_GREEN);
+	delay(500);
+
+	while(client.available()) {
+		showProgress(PROGRESS_GREEN);
+		String line = client.readStringUntil('\n');
+		debuglog("Read line: ", line);
+	}
+	debugln("===== Done =====");
+
+	hideProgress();
+	return true;
+}

+ 54 - 0
99_main.ino

@@ -0,0 +1,54 @@
+void setup() {
+	Serial.begin(115200);
+	while(!Serial) delay(10);
+
+	initLeds(); // Shows errors, so needs to be first
+	initHumidity();
+	initPressure();
+}
+
+void loop() {
+	debugln("----------------------");
+	updateHumidity();
+	updatePressure();
+	
+	uint16_t light = analogRead(LIGHT_PIN);
+
+	debugln();
+
+	debuglog("Light value:            ", light);
+	debuglog("Humidity - Humidity:    ", HumTemp.humidity);
+	debuglog("Humidity - Temperature: ", HumTemp.temperature);
+	debuglog("Pressure - Temperature: ", PressTemp.temperature);
+	debuglog("Pressure - Pressure:    ", PressTemp.pressure);
+
+	float averageTemperature = (HumTemp.temperature + PressTemp.temperature) / 2;
+	debuglog("Average - Temperature:  ", averageTemperature);
+
+	debugln();
+	
+	initWifi();
+
+#ifdef TEST_MODE
+	getSomething();
+	hideProgress();
+	delay(5000);
+#else
+	boolean complete = false;
+	while(!complete) {
+		delay(500);
+		debugln("Uploading data");
+		complete = uploadData(
+				averageTemperature,
+				PressTemp.pressure,
+				HumTemp.humidity,
+				light
+			);
+	}
+
+	hideProgress();
+
+	delay(1000);
+	deepSleep();
+#endif
+}

+ 33 - 0
outdoor-weather-station.ino

@@ -0,0 +1,33 @@
+//#define TEST_MODE
+
+#define LIGHT_PIN A3
+
+#define ERR reboot()
+
+#define SLEEP_TIME_S 30
+#define SLEEP_TIME_MS SLEEP_TIME_S * 1000
+#define SLEEP_TIME_US SLEEP_TIME_MS * 1000
+
+#define debug(X) Serial.print(X)
+#define debugln(...) Serial.println(__VA_ARGS__)
+#define debuglog(A, B) debug(A); debugln(B)
+
+char log_buff[200];
+#define dout(...) sprintf(log_buff, __VA_ARGS__); Serial.println(log_buff); 
+
+#define RTDB_AUTH_TOKEN "abc123"
+#define RTDB_PROJECT "weather-station-xxxxx"
+#define RTDB_PATH "outdoor"
+
+#define RTDB_HOST RTDB_PROJECT "-default-rtdb.firebaseio.com"
+#define RTDB_URL "https://" RTDB_HOST "/" RTDB_PATH ".json?auth=" RTDB_AUTH_TOKEN
+
+// Reboot on error
+void reboot() {
+	showError();
+	const int64_t reboot_sleep_time = 5 * 1000 * 1000;
+	debuglog("Rebooting by going to sleep for: ", reboot_sleep_time);
+	esp_sleep_enable_timer_wakeup(reboot_sleep_time);
+	Serial.flush();
+	esp_deep_sleep_start();
+}