Skip to content

Commit

Permalink
Merge pull request #1 from brushknight/v2.0
Browse files Browse the repository at this point in the history
wip: v2.0
  • Loading branch information
brushknight authored Sep 24, 2021
2 parents 6197e53 + b930337 commit 5201ddd
Show file tree
Hide file tree
Showing 19 changed files with 616 additions and 109 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Terrarium Controller

It consists of 2 parts, IoT esp32 based controller and server that works as a proxy for other data storages.

4 changes: 4 additions & 0 deletions esp32/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
platform = espressif32
board = nodemcu-32s
framework = arduino
monitor_speed = 115200
lib_deps =
adafruit/DHT sensor library @ ^1.4.2
adafruit/Adafruit NeoPixel @ ^1.8.0
bblanchon/ArduinoJson@^6.18.0
marcoschwartz/LiquidCrystal_I2C @ ^1.1.4
adafruit/RTClib @ ^1.14.1
alexgyver/EncButton @ ^1.7
60 changes: 42 additions & 18 deletions esp32/src/climate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,28 @@ namespace Climate

/* schedule
08 - 20 hot max 29.5
20 - 8 hot max 25
TODO: add 2 hour difference for UTC timezone
// temp tolerance ~ 1.5C - to be measured and tuned
time in UTC
06 - 18 hot max 29.5
18 - 6 hot max 25
*/

#define DAY_START_HOUR 8
#define DAY_START_HOUR 6
#define DAY_START_MINUTE 0

#define NIGHT_START_HOUR 20
#define NIGHT_START_HOUR 18
#define NIGHT_START_MINUTE 0

#define DHTTYPE DHT22
#define HEATER_RELAY_PIN 4

#define DHT_HOT_SIDE_PIN 16 // #1
#define DHT_HOT_CENTER_PIN 17 // #2
#define DHT_COLD_CENTER_PIN 5 // #3
#define DHT_COLD_SIDE_PIN 18 // #4
#define DHT_HOT_SIDE_PIN 16 // #1
#define DHT_HOT_CENTER_PIN 17 // #2
#define DHT_COLD_CENTER_PIN 18 // #3
#define DHT_COLD_SIDE_PIN 19 // #4

#define DAY_MAX_TEMP 28.5
#define DAY_TEMP_TOLERANCE_WARM 0.5
Expand All @@ -34,14 +35,17 @@ namespace Climate
#define NIGHT_TEMP_TOLERANCE_WARM 0.5
#define NIGHT_TEMP_TOLERANCE_COLD 0.6

#define MAX_NULL_READINGS_SEC 30

int lastNotNullReadings = 0;

DHT_Unified dhtHotSide(DHT_HOT_SIDE_PIN, DHTTYPE);
DHT_Unified dhtHotCenter(DHT_HOT_CENTER_PIN, DHTTYPE);
DHT_Unified dhtColdCenter(DHT_COLD_CENTER_PIN, DHTTYPE);
DHT_Unified dhtColdSide(DHT_COLD_SIDE_PIN, DHTTYPE);

volatile byte relayState = LOW;


HeaterPhase heaterPhase;

ClimateData readTempHumid(DHT_Unified dht)
Expand Down Expand Up @@ -80,18 +84,18 @@ namespace Climate

void turnRelayOn()
{
relayState = LOW;
relayState = HIGH;
heaterPhase = heating;
digitalWrite(HEATER_RELAY_PIN, relayState);
Serial.println("turn relay on");
//Serial.println("turn relay on");
}

void turnRelayOff()
{
relayState = HIGH;
relayState = LOW;
heaterPhase = cooling;
digitalWrite(HEATER_RELAY_PIN, relayState);
Serial.println("turn relay off");
//Serial.println("turn relay off");
}

void climateSetup()
Expand All @@ -104,7 +108,7 @@ namespace Climate
dhtColdSide.begin();
}

Telemetry::TelemteryData climateControl(int hour, int minute)
Telemetry::TelemteryData climateControl(int hour, int minute, uint32_t now)
{

bool isDay = hour >= DAY_START_HOUR && hour < NIGHT_START_HOUR && minute >= DAY_START_MINUTE;
Expand All @@ -121,6 +125,16 @@ namespace Climate
// Serial.println("4: cold side");
ClimateData coldSide = readTempHumid(dhtColdSide);

if (hotSide.t > 0 || hotCenter.t > 0)
{
lastNotNullReadings = now;
}

if (lastNotNullReadings != 0 && now - lastNotNullReadings > MAX_NULL_READINGS_SEC)
{
ESP.restart();
}

Telemetry::TelemteryData telemetryData = Telemetry::TelemteryData();

float maxTemp = DAY_MAX_TEMP - DAY_TEMP_TOLERANCE_WARM;
Expand Down Expand Up @@ -160,8 +174,18 @@ namespace Climate
}

telemetryData.hotSide = hotSide;
telemetryData.hotCenter = hotCenter;
telemetryData.coldCenter = coldCenter;

if (SENSORS_COUNT == 2)
{
telemetryData.hotCenter = hotSide;
telemetryData.coldCenter = coldSide;
}
else if (SENSORS_COUNT == 4)
{
telemetryData.hotCenter = hotCenter;
telemetryData.coldCenter = coldCenter;
}

telemetryData.coldSide = coldSide;
telemetryData.heaterPhase = heaterPhase;

Expand Down
3 changes: 2 additions & 1 deletion esp32/src/climate.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <DHT_U.h>
#include "telemetry.h"
#include "climate_data.h"
#include "config.h"

namespace Climate
{
Expand All @@ -14,7 +15,7 @@ namespace Climate
ClimateData readTempHumid(DHT_Unified dht);
void turnRelayOn();
void turnRelayOff();
Telemetry::TelemteryData climateControl(int hour, int minute);
Telemetry::TelemteryData climateControl(int hour, int minute, uint32_t now);
}

#endif
7 changes: 7 additions & 0 deletions esp32/src/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef CONFIG
#define CONFIG

#define SENSORS_COUNT 2
#define TERRARIUM_ID 3

#endif
198 changes: 198 additions & 0 deletions esp32/src/display.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#include "display.h"

namespace Display
{

int lcdColumns = 20;
int lcdRows = 4;

LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);

void render(DisplayData displayData)
{
// just do clear?
// clearRow(0);
// clearRow(1);
// clearRow(2);
// clearRow(3);

renderHarvestInfo(displayData.nextHarvestInSec);
renderClimate(displayData);
renderTime(displayData.hour, displayData.minute, displayData.second);
renderInfo(displayData.terrId);
renderSubmissionInfo(displayData.submission);
}

void renderSubmissionInfo(bool submission)
{
lcd.setCursor(9, 2);
lcd.print(" ");
lcd.print(" ");
if (submission){
lcd.setCursor(9, 2);
lcd.print("S");
}
}

void renderHarvestInfo(int secondsToNextHarvest)
{
lcd.setCursor(9, 3);
lcd.print(" ");
lcd.print(" ");
lcd.print(" ");
lcd.setCursor(9, 3);
lcd.print(secondsToNextHarvest);
}

void renderInfo(int id)
{
lcd.setCursor(4, 3);
lcd.print(" ");
lcd.print(" ");
lcd.print(" ");
lcd.print(" ");
lcd.setCursor(4, 3);
lcd.print("ID");
lcd.setCursor(6, 3);
lcd.print(id);
}

void clearRow(int row)
{
lcd.setCursor(0, row);
for (int i = 0; i < 20; i++)
{
lcd.print(" ");
}
}

void renderClimate(DisplayData displayData)
{
clearRow(0);
clearRow(1);
lcd.setCursor(0, 0);
lcd.print(floatToString(displayData.hotSide.t));

if (SENSORS_COUNT == 4)
{
lcd.print("|");
lcd.setCursor(5, 0);
lcd.print(floatToString(displayData.hotCenter.t));
lcd.setCursor(11, 0);
lcd.print(floatToString(displayData.coldCenter.t));
lcd.print("|");
}

lcd.setCursor(16, 0);
lcd.print(floatToString(displayData.coldSide.t));

lcd.setCursor(0, 1);
lcd.print(floatToString(displayData.hotSide.h));

if (SENSORS_COUNT == 4)
{
lcd.print("|");
lcd.setCursor(5, 1);
lcd.print(floatToString(displayData.hotCenter.h));
lcd.setCursor(11, 1);
lcd.print(floatToString(displayData.coldCenter.h));
lcd.print("|");
}

lcd.setCursor(16, 1);
lcd.print(floatToString(displayData.coldSide.h));

lcd.setCursor(0, 2);
lcd.print("heater");
lcd.setCursor(0, 3);
lcd.print(" ");
lcd.print(" ");
lcd.print(" ");
lcd.setCursor(0, 3);
if (displayData.heater)
{
lcd.print("ON");
}
else
{
lcd.print("OFF");
}
lcd.setCursor(13, 2);
if (displayData.heaterPhase == Climate::HeaterPhase::cooling)
{
lcd.print("cooling");
}
else
{
lcd.print("heating");
}
}

char *floatToString(double value)
{
static char buffer[5];
sprintf(buffer, "%.1f", value);
//Serial.println(buffer);
return buffer;
}

void renderTime(int hour, int minute, int second)
{
char buffer[20];
sprintf(buffer, "%02d:%02d:%02d", hour, minute, second);

lcd.setCursor(12, 3);
lcd.print(buffer);
}

void renderConnectingToWifi(char *ssid, int attempts)
{
lcd.clear();
// set cursor to first column, first row
lcd.setCursor(0, 0);
lcd.print("Connecting to WiFi");

lcd.setCursor(0, 1);
lcd.print(ssid);

lcd.setCursor(0, 2);
for (int i = 0; i < attempts; i++)
{
lcd.print("*");
}
}

void renderNtp(int attempts)
{
lcd.clear();
// set cursor to first column, first row
lcd.setCursor(0, 0);
lcd.print("Fetching time from NTP");

lcd.setCursor(0, 1);
for (int i = 0; i < attempts; i++)
{
lcd.print("*");
}
}

void renderConnectedToWifi(char *ssid)
{
lcd.clear();
// set cursor to first column, first row
lcd.setCursor(0, 0);
lcd.print("Connected to WiFi");

lcd.setCursor(0, 1);
lcd.print(ssid);
}

void displaySetup()
{
// initialize LCD
lcd.init();
// turn on LCD backlight
lcd.backlight();
Serial.println("displaySetup: ok");
}
}
Loading

0 comments on commit 5201ddd

Please sign in to comment.