Compare commits
5 Commits
develop
...
mseyfrie_d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb394523b5 | ||
|
|
a9e3628ad4 | ||
|
|
50f22fa759 | ||
|
|
9ca90ccc46 | ||
|
|
449dd0447c |
Binary file not shown.
@ -1,10 +1,2 @@
|
|||||||
# Smart_Garden
|
# Smart_Garden
|
||||||
|
|
||||||
## Requirements
|
|
||||||
VisualStudioCode with PlatformIO extension
|
|
||||||
|
|
||||||
## Build
|
|
||||||
Configuration is defined in `platformio.ini` file. If you have PlatformIO extension installed, just use built-in build-command.
|
|
||||||
|
|
||||||
## Flash to µC
|
|
||||||
Connect ESP32 to any desired USB-Port and use PlatformIOs upload-command.
|
|
||||||
|
|||||||
@ -18,8 +18,11 @@ monitor_speed = 115200
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
439 #ID of Lightsensor library BH1750
|
439 #ID of Lightsensor library BH1750
|
||||||
19 #DHT sensor library
|
19 #DHT sensor library
|
||||||
|
31 #Adafruit Unified Sensor
|
||||||
AutoConnect@^1.1.7
|
AutoConnect@^1.1.7
|
||||||
|
AsyncMqttClient@^0.8.2
|
||||||
ArduinoJson@^6.15.2
|
ArduinoJson@^6.15.2
|
||||||
|
; MQTT@^2.4.7
|
||||||
PubSubClient@^2.8
|
PubSubClient@^2.8
|
||||||
ArduinoNvs@^2.5
|
ArduinoNvs@^2.5
|
||||||
ESPRandom@^1.3.3
|
ESPRandom@^1.3.3
|
||||||
@ -5,22 +5,23 @@
|
|||||||
|
|
||||||
const int numReadings = 20;
|
const int numReadings = 20;
|
||||||
|
|
||||||
// reads soil moisture multiple times and calculates average to eliminate noise
|
void setupCapacitiveSoilMoistureSensor() {
|
||||||
|
// pinMode(PIN_MS, INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
int readCapacitiveSoilMoistureSensor() {
|
int readCapacitiveSoilMoistureSensor() {
|
||||||
int total = 0; // the running total
|
int total = 0; // the running total
|
||||||
// read from the sensor
|
// read from the sensor:
|
||||||
for (int readIndex = 0; readIndex < numReadings; readIndex++) {
|
for (int readIndex = 0; readIndex < numReadings; readIndex++) {
|
||||||
total = total + analogRead(PIN_MS);
|
total = total + analogRead(PIN_MS);
|
||||||
delay(2);
|
delay(2);
|
||||||
}
|
}
|
||||||
int measurement = total / numReadings;
|
int measurement = total / numReadings;
|
||||||
|
|
||||||
// map measurement to relative soil moisture value in %
|
|
||||||
int finalRes = map(measurement, VALUE_AIR, VALUE_WATER, 0, 100);
|
int finalRes = map(measurement, VALUE_AIR, VALUE_WATER, 0, 100);
|
||||||
Serial.print("current soil moisture: ");
|
Serial.print("current soil moisture: ");
|
||||||
Serial.println(finalRes);
|
Serial.println(finalRes);
|
||||||
|
|
||||||
// clamp mesurement to a value between 0 and 100
|
|
||||||
if (finalRes < 0) {
|
if (finalRes < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (finalRes > 100) {
|
} else if (finalRes > 100) {
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
void setupCapacitiveSoilMoistureSensor();
|
||||||
int readCapacitiveSoilMoistureSensor();
|
int readCapacitiveSoilMoistureSensor();
|
||||||
@ -1,5 +1,4 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
// this common Header file defines commonly used hardware and buildtime constants
|
|
||||||
|
|
||||||
// PUBLISH FREQUENCY (MS)
|
// PUBLISH FREQUENCY (MS)
|
||||||
#define FREQUENCY 60000
|
#define FREQUENCY 60000
|
||||||
|
|||||||
@ -31,7 +31,6 @@ WiFiClient client;
|
|||||||
AutoConnectConfig Config;
|
AutoConnectConfig Config;
|
||||||
PubSubClient mqttClient(client);
|
PubSubClient mqttClient(client);
|
||||||
|
|
||||||
// spins wifi up and activates green status light when wifi is conencted
|
|
||||||
void connectWiFi() {
|
void connectWiFi() {
|
||||||
yield();
|
yield();
|
||||||
Serial.println("Start WiFi...");
|
Serial.println("Start WiFi...");
|
||||||
@ -40,7 +39,6 @@ void connectWiFi() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handles MQTT messages and keeps track of MQTT connection. starts reconnect timer if connection lost.
|
|
||||||
void mqttLoop(void *parameter) {
|
void mqttLoop(void *parameter) {
|
||||||
do {
|
do {
|
||||||
yield();
|
yield();
|
||||||
@ -58,12 +56,11 @@ void mqttLoop(void *parameter) {
|
|||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup MQTT connection and spins up task to handle connection and messages
|
|
||||||
void connectMQTT() {
|
void connectMQTT() {
|
||||||
yield();
|
yield();
|
||||||
if (mqttClient.connected()) return;
|
if (mqttClient.connected()) return;
|
||||||
Serial.println("Connecting to MQTT...");
|
Serial.println("Connecting to MQTT...");
|
||||||
|
// mqttClient.begin(MQTT_HOST, MQTT_PORT, client);
|
||||||
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
|
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
|
||||||
mqttClient.disconnect();
|
mqttClient.disconnect();
|
||||||
mqttClient.connect(getDeviceIDcharArr());
|
mqttClient.connect(getDeviceIDcharArr());
|
||||||
@ -85,7 +82,6 @@ void connectMQTT() {
|
|||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handles lost wifi connection
|
|
||||||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
Serial.printf("[WiFi-event] event: %d\n", event);
|
Serial.printf("[WiFi-event] event: %d\n", event);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
@ -109,7 +105,6 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mqtt callback handles incoming messages
|
|
||||||
void onMqttMessage(char *topic, byte *payload, unsigned int payload_length) {
|
void onMqttMessage(char *topic, byte *payload, unsigned int payload_length) {
|
||||||
Serial.print("Message arrived [");
|
Serial.print("Message arrived [");
|
||||||
Serial.print(topic);
|
Serial.print(topic);
|
||||||
@ -120,7 +115,7 @@ void onMqttMessage(char *topic, byte *payload, unsigned int payload_length) {
|
|||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
if (strcmp(topic, MQTT_LIGHT_PROPERTIES) == 0) {
|
if (strcmp(topic, MQTT_LIGHT_PROPERTIES) == 0) {
|
||||||
Serial.println("receiving light threshold...");
|
Serial.println("receiving light treshold...");
|
||||||
Serial.println(topic);
|
Serial.println(topic);
|
||||||
StaticJsonDocument<1024> doc;
|
StaticJsonDocument<1024> doc;
|
||||||
DeserializationError err = deserializeJson(doc, payload);
|
DeserializationError err = deserializeJson(doc, payload);
|
||||||
@ -166,7 +161,6 @@ void onMqttMessage(char *topic, byte *payload, unsigned int payload_length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generates mqtt topics based on device-uuid
|
|
||||||
void constructMQTTpaths() {
|
void constructMQTTpaths() {
|
||||||
strcpy(MQTT_VALVE_COMMAND, MQTT_TOPIC_BASE_SUB "/");
|
strcpy(MQTT_VALVE_COMMAND, MQTT_TOPIC_BASE_SUB "/");
|
||||||
strcat(MQTT_VALVE_COMMAND, getDeviceIDcharArr());
|
strcat(MQTT_VALVE_COMMAND, getDeviceIDcharArr());
|
||||||
@ -191,17 +185,16 @@ void constructMQTTpaths() {
|
|||||||
Serial.println(MQTT_AUTO_PROPERTIES);
|
Serial.println(MQTT_AUTO_PROPERTIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initializes Wifi and MQTT connections
|
|
||||||
void setupConnections() {
|
void setupConnections() {
|
||||||
constructMQTTpaths();
|
constructMQTTpaths();
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.println();
|
Serial.println();
|
||||||
// disable Watchdog Task. This task made ESP stopped working, probably caused by working with arduino framework combined with multicore-concurrent patterns
|
|
||||||
disableCore0WDT();
|
disableCore0WDT();
|
||||||
|
// disableCore1WDT();
|
||||||
Config.autoReconnect = true;
|
Config.autoReconnect = true;
|
||||||
|
// Config.autoReset = true;
|
||||||
Portal.config(Config);
|
Portal.config(Config);
|
||||||
|
|
||||||
// FreeRTOS Timer to handle loss of connections
|
|
||||||
mqttReconnectTimer = xTimerCreate(
|
mqttReconnectTimer = xTimerCreate(
|
||||||
"mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectMQTT));
|
"mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void *)0, reinterpret_cast<TimerCallbackFunction_t>(connectMQTT));
|
||||||
wifiReconnectTimer = xTimerCreate(
|
wifiReconnectTimer = xTimerCreate(
|
||||||
@ -216,7 +209,6 @@ void setupConnections() {
|
|||||||
setupNTP();
|
setupNTP();
|
||||||
}
|
}
|
||||||
|
|
||||||
// method to delegate publish from other modules to connecions module
|
|
||||||
void publishMessage(const char *topic, const char *msg) {
|
void publishMessage(const char *topic, const char *msg) {
|
||||||
if(mqttClient.connected()) {
|
if(mqttClient.connected()) {
|
||||||
mqttClient.publish(topic, msg);
|
mqttClient.publish(topic, msg);
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include <Adafruit_Sensor.h>
|
||||||
#include <BH1750.h>
|
#include <BH1750.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <lightSensor.h>
|
#include <lightSensor.h>
|
||||||
|
|||||||
@ -17,8 +17,8 @@ void setupSensors() {
|
|||||||
setupLightSensor();
|
setupLightSensor();
|
||||||
setupPWM();
|
setupPWM();
|
||||||
setupTemperatureSensor();
|
setupTemperatureSensor();
|
||||||
|
setupCapacitiveSoilMoistureSensor();
|
||||||
|
|
||||||
// generates MQTT topics based on device ID
|
|
||||||
strcpy(MQTT_SENSOR_DATA_TOPIC, MQTT_TOPIC_BASE_PUB "/");
|
strcpy(MQTT_SENSOR_DATA_TOPIC, MQTT_TOPIC_BASE_PUB "/");
|
||||||
strcat(MQTT_SENSOR_DATA_TOPIC, getDeviceIDcharArr());
|
strcat(MQTT_SENSOR_DATA_TOPIC, getDeviceIDcharArr());
|
||||||
strcat(MQTT_SENSOR_DATA_TOPIC, "/data");
|
strcat(MQTT_SENSOR_DATA_TOPIC, "/data");
|
||||||
@ -26,7 +26,6 @@ void setupSensors() {
|
|||||||
Serial.println(MQTT_SENSOR_DATA_TOPIC);
|
Serial.println(MQTT_SENSOR_DATA_TOPIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function to collect sensor data and delegate collected data as json to mqtt-task
|
|
||||||
void readSensors() {
|
void readSensors() {
|
||||||
Serial.println();
|
Serial.println();
|
||||||
StaticJsonDocument<128> doc;
|
StaticJsonDocument<128> doc;
|
||||||
@ -35,7 +34,7 @@ void readSensors() {
|
|||||||
Serial.print(lxValue);
|
Serial.print(lxValue);
|
||||||
Serial.println(" lx");
|
Serial.println(" lx");
|
||||||
doc["brightness"] = lxValue;
|
doc["brightness"] = lxValue;
|
||||||
if (automaticLight && (lxValue < minimumLightValueLX && checkForDay())) {
|
if ((lxValue < minimumLightValueLX) && checkForDay()) {
|
||||||
triggerLight();
|
triggerLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@ bool automaticIrrigation = false;
|
|||||||
// Make sure device irrigates until fieldcapacity is reached
|
// Make sure device irrigates until fieldcapacity is reached
|
||||||
bool irrigateUntilFC = false;
|
bool irrigateUntilFC = false;
|
||||||
|
|
||||||
// stores properties to non-volatile-flash
|
|
||||||
void persistSoilProps(int FC, int PWP, int SAT) {
|
void persistSoilProps(int FC, int PWP, int SAT) {
|
||||||
Serial.println("persistSoilProps");
|
Serial.println("persistSoilProps");
|
||||||
bool f = NVS.setInt("fieldCapacity", FC);
|
bool f = NVS.setInt("fieldCapacity", FC);
|
||||||
@ -33,7 +32,6 @@ void persistSoilProps(int FC, int PWP, int SAT) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// restores properties from nvs on boot
|
|
||||||
void restoreSoilProps() {
|
void restoreSoilProps() {
|
||||||
Serial.println("restoreSoilProps");
|
Serial.println("restoreSoilProps");
|
||||||
int fc = NVS.getInt("fieldCapacity");
|
int fc = NVS.getInt("fieldCapacity");
|
||||||
@ -56,7 +54,6 @@ void restoreSoilProps() {
|
|||||||
Serial.println(soilSaturation);
|
Serial.println(soilSaturation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// will be executed in setup process when booting µC
|
|
||||||
void setupStore() {
|
void setupStore() {
|
||||||
NVS.begin("store");
|
NVS.begin("store");
|
||||||
initDeviceID();
|
initDeviceID();
|
||||||
@ -65,7 +62,6 @@ void setupStore() {
|
|||||||
restoreAutoProps();
|
restoreAutoProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets soil properties and calls funtion to persist them
|
|
||||||
void setSoilProperties(int FC, int PWP, int SAT) {
|
void setSoilProperties(int FC, int PWP, int SAT) {
|
||||||
fieldCapacity = FC;
|
fieldCapacity = FC;
|
||||||
permanentWiltingPoint = PWP;
|
permanentWiltingPoint = PWP;
|
||||||
@ -129,7 +125,6 @@ void persistAutoProps(bool light, bool irrigation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// restores properties from nvs on boot
|
|
||||||
void restoreAutoProps() {
|
void restoreAutoProps() {
|
||||||
Serial.println("restoreLightProps");
|
Serial.println("restoreLightProps");
|
||||||
int li = NVS.getInt("automaticLight");
|
int li = NVS.getInt("automaticLight");
|
||||||
@ -150,7 +145,6 @@ void setAutoProperties(bool light, bool irrigation) {
|
|||||||
|
|
||||||
String DEVICE_ID = "";
|
String DEVICE_ID = "";
|
||||||
|
|
||||||
// generates device UUID on first boot and stores it to NVS. UUID will be restored from NVS after each subsequent boot
|
|
||||||
void initDeviceID() {
|
void initDeviceID() {
|
||||||
DEVICE_ID = NVS.getString("UUID");
|
DEVICE_ID = NVS.getString("UUID");
|
||||||
if (!DEVICE_ID.isEmpty()) {
|
if (!DEVICE_ID.isEmpty()) {
|
||||||
|
|||||||
@ -5,12 +5,11 @@
|
|||||||
#define DHTPIN PIN_DHT11
|
#define DHTPIN PIN_DHT11
|
||||||
#define DHTTYPE DHT11
|
#define DHTTYPE DHT11
|
||||||
|
|
||||||
// set pin and type
|
// specify pin and type
|
||||||
DHT_Unified dht(DHTPIN, DHTTYPE);
|
DHT_Unified dht(DHTPIN, DHTTYPE);
|
||||||
|
|
||||||
// initialize temperature sensor
|
// initialize temperature sensor
|
||||||
void setupTemperatureSensor() {
|
void setupTemperatureSensor() {
|
||||||
// Serial.begin(9600);
|
|
||||||
dht.begin();
|
dht.begin();
|
||||||
Serial.println(F("DHT11 Unified Sensor Ready"));
|
Serial.println(F("DHT11 Unified Sensor Ready"));
|
||||||
sensor_t sensor;
|
sensor_t sensor;
|
||||||
|
|||||||
@ -9,7 +9,6 @@ extern "C" {
|
|||||||
|
|
||||||
#include <valve.h>
|
#include <valve.h>
|
||||||
|
|
||||||
// open valve and set status led to blue while irrigating
|
|
||||||
bool openValve() {
|
bool openValve() {
|
||||||
digitalWrite(PIN_VALVE, HIGH);
|
digitalWrite(PIN_VALVE, HIGH);
|
||||||
digitalWrite(PIN_LED_G, LOW);
|
digitalWrite(PIN_LED_G, LOW);
|
||||||
@ -17,7 +16,6 @@ bool openValve() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// close valve and set status back to green
|
|
||||||
bool closeValve() {
|
bool closeValve() {
|
||||||
digitalWrite(PIN_VALVE, LOW);
|
digitalWrite(PIN_VALVE, LOW);
|
||||||
digitalWrite(PIN_LED_G, HIGH);
|
digitalWrite(PIN_LED_G, HIGH);
|
||||||
@ -25,9 +23,7 @@ bool closeValve() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function to handle valve control, see documentation for visual representation of control flow
|
|
||||||
void valveTask(void *parameter) {
|
void valveTask(void *parameter) {
|
||||||
// this parameter is used to determine if task was triggered manually by mqtt or by the sensor loop
|
|
||||||
bool isAutomatic = (bool)parameter;
|
bool isAutomatic = (bool)parameter;
|
||||||
Serial.print(isAutomatic);
|
Serial.print(isAutomatic);
|
||||||
Serial.println(" Valve task triggered.");
|
Serial.println(" Valve task triggered.");
|
||||||
@ -59,7 +55,6 @@ void valveTask(void *parameter) {
|
|||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new task which handles valve control concurrently
|
|
||||||
void toggleValve(bool automatic) {
|
void toggleValve(bool automatic) {
|
||||||
xTaskCreate(
|
xTaskCreate(
|
||||||
valveTask, /* Task function. */
|
valveTask, /* Task function. */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user