summaryrefslogtreecommitdiffstats
path: root/HvacStation/HvacStation.ino
diff options
context:
space:
mode:
Diffstat (limited to 'HvacStation/HvacStation.ino')
-rw-r--r--HvacStation/HvacStation.ino122
1 files changed, 83 insertions, 39 deletions
diff --git a/HvacStation/HvacStation.ino b/HvacStation/HvacStation.ino
index 7d687ac..eb6e131 100644
--- a/HvacStation/HvacStation.ino
+++ b/HvacStation/HvacStation.ino
@@ -1,20 +1,31 @@
#include <WiFi.h>
#include <HTTPClient.h>
#include <PID_v1.h>
+#include <Wire.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
#define nelem(arr) (sizeof(arr) / sizeof(arr[0]))
-enum {
+enum times {
SECOND = 1000,
- PERIOD = 30*SECOND,
+ SERVER_PERIOD = 10*SECOND,
+ DISPLAY_PERIOD = 1*SECOND,
+ SOLENOID_WINDOW = 2*SECOND,
};
-enum pins { SOLENOID_PIN = 21 };
+enum pins { SOLENOID_PIN = 23 };
enum tunings {
P = 2,
I = 5,
D = 1,
};
-enum { SOLENOID_WINDOW = 5000 };
+enum screen {
+ SCREEN_WIDTH = 128,
+ SCREEN_HEIGHT = 64,
+ SCREEN_I2C_ADDR = 0x3C,
+ TEXT_SIZE = 1,
+ TEXT_COLOR = WHITE,
+};
const char ssid[] = "Pixel_6504";
const char password[] = "zj3av9sjev7ed8j";
@@ -24,6 +35,7 @@ const char dutyCycleUrl[] = "http://hvac.samanthony.xyz/duty_cycle";
double pidInput, pidOutput, pidSetpoint;
PID pid(&pidInput, &pidOutput, &pidSetpoint, P, I, D, DIRECT);
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void
setup(void) {
@@ -32,6 +44,17 @@ setup(void) {
Serial.begin(9600);
while (!Serial) {}
+ Serial.println("Initializing display...");
+ if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_I2C_ADDR)) {
+ Serial.println("Failed to initialize display.");
+ for (;;) {}
+ }
+ delay(1000);
+ display.clearDisplay();
+ display.setTextSize(TEXT_SIZE);
+ display.setTextColor(TEXT_COLOR);
+ display.display();
+
pid.SetOutputLimits(0, SOLENOID_WINDOW);
pid.SetMode(AUTOMATIC);
@@ -50,31 +73,70 @@ void
loop(void) {
static float humidity = 0.0; // Measured humidity of the building.
static float target = 0.0; // Target humidity.
- static unsigned long lastUpdate = 0; // Last time the server was contacted.
+ static unsigned long lastServerUpdate = 0; // Last time the server was contacted.
+ static unsigned long lastDisplayUpdate = 0; // Last time the display was refreshed.
- pidInput = humidity;
- pidSetpoint = target;
- pid.Compute();
+ computePidOutput(target, humidity);
writeSolenoidPin(pidOutput);
unsigned long now = millis();
- if (now - lastUpdate > PERIOD) {
- lastUpdate = now;
+ if (now - lastServerUpdate > SERVER_PERIOD) {
+ lastServerUpdate = now;
+ float dutycycle = pidOutput / SOLENOID_WINDOW * 100.0;
+ contactServer(&target, &humidity, dutycycle);
+ }
+ if (now - lastDisplayUpdate > DISPLAY_PERIOD) {
+ lastDisplayUpdate = now;
+ float dutycycle = pidOutput / SOLENOID_WINDOW * 100.0;
+ refreshDisplay(target, humidity, dutycycle);
+ }
+}
- if (get(humidityUrl, &humidity) != 0)
- Serial.println("Failed to get humidity from server.");
+void
+computePidOutput(float target, float humidity) {
+ pidSetpoint = target;
+ pidInput = humidity;
+ pid.Compute();
+}
- if (get(targetUrl, &target) != 0)
- Serial.println("Failed to get target from server.");
+void
+writeSolenoidPin(double pidOutput) {
+ static unsigned long windowStartTime = 0;
- float dc = pidOutput / SOLENOID_WINDOW * 100.0;
- if (postDuty(dc) != 0)
- Serial.println("Failed to post duty cycle to server.");
+ unsigned long now = millis();
+ if (now - windowStartTime > SOLENOID_WINDOW)
+ windowStartTime = now; // Start new window.
- Serial.printf("Measured humidity: %.2f%%\n", humidity);
- Serial.printf("Target humidity: %.2f%%\n", target);
- Serial.printf("Duty cycle: %.0f%%\n", dc);
- }
+ if (now - windowStartTime < pidOutput)
+ digitalWrite(SOLENOID_PIN, HIGH);
+ else
+ digitalWrite(SOLENOID_PIN, LOW);
+}
+
+// Get the target and measured humidities from the server, and post the duty cycle.
+void
+contactServer(float *target, float *humidity, float dutycycle) {
+ if (get(targetUrl, target) != 0)
+ Serial.println("Failed to get target from server.");
+ if (get(humidityUrl, humidity) != 0)
+ Serial.println("Failed to get humidity from server.");
+ if (postDuty(dutycycle) != 0)
+ Serial.println("Failed to post duty cycle to server.");
+}
+
+// Print the duty cycle and measured and target humidities to the OLED screen.
+void
+refreshDisplay(float target, float humidity, float dutycycle) {
+ Serial.printf("Target humidity: %.2f%%\n", target);
+ Serial.printf("Measured humidity: %.2f%%\n", humidity);
+ Serial.printf("Duty cycle: %.0f%%\n", dutycycle);
+
+ display.clearDisplay();
+ display.setCursor(0, 10);
+ display.printf("Target: %.0f%%\n", target);
+ display.printf("Measured: %.0f%%\n", humidity);
+ display.printf("Duty cycle: %.0f%%\n", dutycycle);
+ display.display();
}
// Make a GET request to the server and set *x to the float value that it responds with.
@@ -145,21 +207,3 @@ parseFloat(const char *str, float *x) {
}
return 0;
}
-
-void
-writeSolenoidPin(double pidOutput) {
- static unsigned long windowStartTime = 0;
-
- unsigned long now = millis();
- if (now - windowStartTime > SOLENOID_WINDOW) {
- // Start new window.
- windowStartTime = now;
- float dc = pidOutput / SOLENOID_WINDOW * 100.0;
- Serial.printf("Duty cycle: %.0f%%\n", dc);
- }
-
- if (pidOutput > now - windowStartTime)
- digitalWrite(SOLENOID_PIN, HIGH);
- else
- digitalWrite(SOLENOID_PIN, LOW);
-}