Merge branch 'develop' into sherzog_dev

This commit is contained in:
Sebastian 2020-07-23 12:20:34 +02:00
commit dd2a831ade
21 changed files with 264 additions and 285 deletions

View File

@ -1,8 +1,7 @@
/*
Code for the Capacitive Soil Moisture Sensor
*/
#include <header.h>
#include <common.h>
const int numReadings = 20;
@ -10,12 +9,10 @@ void setupCapacitiveSoilMoistureSensor() {
// pinMode(PIN_MS, INPUT);
}
int readCapacitiveSoilMoistureSensor()
{
int total = 0; // the running total
int readCapacitiveSoilMoistureSensor() {
int total = 0; // the running total
// read from the sensor:
for (int readIndex = 0; readIndex < numReadings; readIndex++)
{
for (int readIndex = 0; readIndex < numReadings; readIndex++) {
total = total + analogRead(PIN_MS);
delay(2);
}

View File

@ -0,0 +1,2 @@
void setupCapacitiveSoilMoistureSensor();
int readCapacitiveSoilMoistureSensor();

46
src/common.h Normal file
View File

@ -0,0 +1,46 @@
#include <Arduino.h>
// PUBLISH FREQUENCY (MS)
#define FREQUENCY 20000
// fix for core panic during wifi initialization
// #define configMINIMAL_STACK_SIZE 4096
// #define CONFIG_TIMER_TASK_STACK_SIZE 8192
// BH1750 lightsensor
#define MIN_LIGHT 0
#define MAX_LIGHT 54612
// DHT11
#define PIN_DHT11 14
// MQ-135
#define PIN_MQ135_A 12
#define PIN_MQ135_D 13
// MOISTURE SENSOR // A7
#define PIN_MS 35
#define VALUE_WATER 1650
#define VALUE_AIR 3500
// Ventil
#define PIN_VALVE 32
#define MAX_VALVE_TIMEOUT 5000
// STATUS LED
#define PIN_LED_R 2
#define PIN_LED_G 0
#define PIN_LED_B 4
// LIGHT LED
#define LIGHT_LED_PIN_R 27
#define LIGHT_LED_PIN_G 26
#define LIGHT_LED_PIN_B 25
#define MAX_LIGHT_TIMEOUT (FREQUENCY - 5)
// MQTT
#define MQTT_HOST "mqtt.timovolkmann.de"
#define MQTT_PORT 1883
#define MQTT_TOPIC_BASE_SUB "smartgarden/commands"
#define MQTT_TOPIC_BASE_PUB "smartgarden/updates"
#define MQTT_PATH_SUB MQTT_TOPIC_BASE_SUB "/#"

View File

@ -1,17 +1,19 @@
#include <ArduinoJson.h>
// #include <MQTT.h>
#include <AutoConnect.h>
#include <PubSubClient.h>
#include <header.h>
#include <WebServer.h>
#include <WiFi.h>
#include <common.h>
#include <store.h>
#include <valve.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
// #define MQTT_VALVE_COMMAND(device_id) (MQTT_TOPIC_BASE_SUB "/" device_id "/valve")
// #define MQTT_SOIL_PROPERTIES(device_id) (MQTT_TOPIC_BASE_SUB "/" device_id "/soil")
// #define MQTT_LIGHT_PROPERTIES(device_id) (MQTT_TOPIC_BASE_SUB "/" device_id "/light")
// #define MQTT_AUTO_PROPERTIES(device_id) (MQTT_TOPIC_BASE_SUB "/" device_id "/automatic")
#include <connections.h>
char MQTT_VALVE_COMMAND[72];
char MQTT_SOIL_PROPERTIES[72];
char MQTT_LIGHT_PROPERTIES[72];
@ -77,13 +79,6 @@ void connectMQTT() {
2,
&mqttTask,
1);
// xTaskCreate(
// mqttLoop, /* Task function. */
// "mqttLoop", /* String with name of task. */
// 8192, /* Stack size in bytes. */
// NULL, /* Parameter passed as input of the task */
// 1, /* Priority of the task. */
// &mqttTask); /* Task handle. */
}
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {

5
src/connections.h Normal file
View File

@ -0,0 +1,5 @@
void connectWiFi();
void mqttLoop(void *parameter);
void connectMQTT();
void setupConnections();
void publishMessage(const char *topic, const char *msg);

View File

@ -1,112 +0,0 @@
/*
Header file for the SmartGarden project
*/
#define HEADER_H
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <BH1750.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <WiFi.h>
#include <WebServer.h>
#include <AutoConnect.h>
#include "time.h"
// fix for core panic during wifi initialization
#define configMINIMAL_STACK_SIZE 4096
#define CONFIG_TIMER_TASK_STACK_SIZE 8192
// BH1750 lightsensor
#define MIN_LIGHT 0
#define MAX_LIGHT 54612
// DHT11
#define PIN_DHT11 14
// MQ-135
#define PIN_MQ135_A 12
#define PIN_MQ135_D 13
// MOISTURE SENSOR // A7
#define PIN_MS 35
#define VALUE_WATER 1650
#define VALUE_AIR 3500
// Ventil
#define PIN_VALVE 32
#define MAX_VALVE_TIMEOUT 5000
// STATUS LED
#define PIN_LED_R 2
#define PIN_LED_G 0
#define PIN_LED_B 4
// LIGHT LED
#define LIGHT_LED_PIN_R 27
#define LIGHT_LED_PIN_G 26
#define LIGHT_LED_PIN_B 25
#define MAX_LIGHT_TIMEOUT 10000
// MQTT
#define MQTT_HOST "mqtt.timovolkmann.de"
#define MQTT_PORT 1883
#define MQTT_TOPIC_BASE_SUB "smartgarden/commands"
#define MQTT_TOPIC_BASE_PUB "smartgarden/updates"
#define MQTT_PATH_SUB MQTT_TOPIC_BASE_SUB "/#"
// MQTT_DEVICE_ID "/#"
// PUBLISH FREQUENCY (MS)
#define FREQUENCY 20000
// moisture
extern void setupCapacitiveSoilMoistureSensor();
extern int readCapacitiveSoilMoistureSensor();
// light
extern void setupLightSensor();
extern float readLightSensorValue();
// temperature & humidity
extern void setupTemperatureSensor();
extern float readHumidity();
extern float readTemperature();
// mqtt & wifi
extern void setupConnections();
extern void publishMessage(const char *topic, const char *msg);
// RGB PWM LED
extern void setupPWM();
extern void setValueNM(int NM);
extern void getColorBasedOnValueNM(int valueNM);
extern void triggerLight();
// NTP Timestamps
void printTimestamp();
void setupNTP();
bool checkForDay();
int getCurrentHour();
// sensors
void readSensors();
void toggleValve(bool automatic);
void setSoilProperties(int FC, int PWP, int SAT);
void setupStore();
void setLightProperties(int NM, int minLX);
void restoreLightProps();
void persistLightProps(int NM, int minLX);
void restoreAutoProps();
void persistAutoProps(bool light, bool irrigation);
void setAutoProperties(bool light, bool irrigation);
void initDeviceID();
String getDeviceID();
const char *getDeviceIDcharArr();
void takeSemaphore();
void releaseSemaphore();

View File

@ -1,4 +1,4 @@
#include <header.h>
#include <common.h>
// Bool to check if light is already active
bool lightActive = false;
@ -79,7 +79,6 @@ bool activateLight() {
// Activate light for given amount of time if not already activated
void lightTask(void *parameter) {
takeSemaphore();
unsigned long lightTimeoutTimer = millis();
if (lightActive == false) {
lightActive = activateLight();
@ -88,7 +87,6 @@ void lightTask(void *parameter) {
}
lightActive = shutdownLight();
}
releaseSemaphore();
vTaskDelete(NULL);
}

3
src/lightChecker.h Normal file
View File

@ -0,0 +1,3 @@
void setupPWM();
void setValueNM(int NM);
void triggerLight();

View File

@ -1,4 +1,7 @@
#include <header.h>
#include <Adafruit_Sensor.h>
#include <BH1750.h>
#include <Wire.h>
#include <lightSensor.h>
// New BH1750 class
BH1750 lightMeter;

2
src/lightSensor.h Normal file
View File

@ -0,0 +1,2 @@
void setupLightSensor();
float readLightSensorValue();

View File

@ -2,9 +2,10 @@
Main file for the SmartGarden project
*/
#include <header.h>
#include <string>
#include <common.h>
#include <sensors.h>
#include <store.h>
#include <connections.h>
#define TIME_TO_SLEEP 30
volatile int noSleepTasks = 0;
@ -23,13 +24,10 @@ void setup() {
digitalWrite(PIN_VALVE, LOW);
setupStore();
setupSensors();
setupConnections();
setupLightSensor();
setupPWM();
setupTemperatureSensor();
setupCapacitiveSoilMoistureSensor();
setupNTP();
// esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * 1000000);
Serial.println("Setup complete...");
Serial.println();
@ -39,22 +37,9 @@ void setup() {
}
void loop() {
// read sensors
// main loop: read sensors
if (millis() - sensorReadTimer >= FREQUENCY) {
readSensors();
sensorReadTimer = millis();
// if(noSleepTasks == 0) {
// delay(200);
// esp_deep_sleep_start();
// }
}
}
void takeSemaphore() {
noSleepTasks++;
}
void releaseSemaphore() {
noSleepTasks--;
}

View File

@ -1,4 +1,6 @@
#include <header.h>
#include <common.h>
#include <WiFi.h>
#include <ntpManager.h>
// Url to ntp server
const char* ntpServer = "pool.ntp.org";

4
src/ntpManager.h Normal file
View File

@ -0,0 +1,4 @@
void setupNTP();
bool checkForDay();
int getCurrentHour();
void printTimestamp();

65
src/sensors.cpp Normal file
View File

@ -0,0 +1,65 @@
#include <ArduinoJson.h>
#include <capacitiveSoilMoistureSensor.h>
#include <connections.h>
#include <lightChecker.h>
#include <lightSensor.h>
#include <ntpManager.h>
#include <sensors.h>
#include <valve.h>
#include <store.h>
#include <temperatureSensor.h>
#include <common.h>
char buffer[128];
char MQTT_SENSOR_DATA_TOPIC[64];
void setupSensors() {
setupLightSensor();
setupPWM();
setupTemperatureSensor();
setupCapacitiveSoilMoistureSensor();
setupNTP();
strcpy(MQTT_SENSOR_DATA_TOPIC, MQTT_TOPIC_BASE_PUB "/");
strcat(MQTT_SENSOR_DATA_TOPIC, getDeviceIDcharArr());
strcat(MQTT_SENSOR_DATA_TOPIC, "/data");
Serial.println("MQTT_SENSOR_DATA_TOPIC:");
Serial.println(MQTT_SENSOR_DATA_TOPIC);
}
void readSensors() {
Serial.println();
StaticJsonDocument<128> doc;
float lxValue = readLightSensorValue();
Serial.print("Light intensity: ");
Serial.print(lxValue);
Serial.println(" lx");
doc["brightness"] = lxValue;
if ((lxValue < minimumLightValueLX) && checkForDay()) {
triggerLight();
}
int mstValue = readCapacitiveSoilMoistureSensor();
Serial.print("Soil moisture: ");
Serial.println(mstValue);
if (automaticIrrigation) {
toggleValve(true);
}
doc["moisture"] = mstValue;
float humidityValue = readHumidity();
Serial.print("Humidity: ");
Serial.println(humidityValue);
doc["humidity"] = humidityValue;
float temperatureValue = readTemperature();
Serial.print("Temperature: ");
Serial.println(temperatureValue);
doc["temperature"] = temperatureValue;
serializeJson(doc, buffer);
publishMessage(MQTT_SENSOR_DATA_TOPIC, buffer);
}

2
src/sensors.h Normal file
View File

@ -0,0 +1,2 @@
void setupSensors();
void readSensors();

View File

@ -1,19 +1,8 @@
#include <ArduinoJson.h>
#include <ArduinoNvs.h>
#include <ESPRandom.h>
#include <header.h>
#include <stdlib.h>
#include <string>
//using namespace std;
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
}
char MQTT_SENSOR_DATA_TOPIC[64];
char buffer[128];
#include <common.h>
#include <lightChecker.h>
#include <store.h>
// Feldkapazität des Bodens in Prozent: Standard ist Humus
int fieldCapacity = 44;
@ -29,103 +18,7 @@ bool automaticIrrigation = true;
// make sure device irrigates until fieldcapacity is reached
bool irrigateUntilFC = false;
void readSensors() {
Serial.println();
StaticJsonDocument<128> doc;
float lxValue = readLightSensorValue();
Serial.print("Light intensity: ");
Serial.print(lxValue);
Serial.println(" lx");
doc["brightness"] = lxValue;
if((lxValue < minimumLightValueLX) && checkForDay()) {
triggerLight();
}
int mstValue = readCapacitiveSoilMoistureSensor();
Serial.print("Soil moisture: ");
Serial.println(mstValue);
if (automaticIrrigation) {
toggleValve(true);
}
doc["moisture"] = mstValue;
float humidityValue = readHumidity();
Serial.print("Humidity: ");
Serial.println(humidityValue);
doc["humidity"] = humidityValue;
float temperatureValue = readTemperature();
Serial.print("Temperature: ");
Serial.println(temperatureValue);
doc["temperature"] = temperatureValue;
serializeJson(doc, buffer);
publishMessage(MQTT_SENSOR_DATA_TOPIC, buffer);
}
bool openValve() {
digitalWrite(PIN_VALVE, HIGH);
digitalWrite(PIN_LED_G, LOW);
digitalWrite(PIN_LED_B, HIGH);
return true;
}
bool closeValve() {
digitalWrite(PIN_VALVE, LOW);
digitalWrite(PIN_LED_G, HIGH);
digitalWrite(PIN_LED_B, LOW);
return false;
}
void valveTask(void *parameter) {
takeSemaphore();
bool isAutomatic = (bool) parameter;
Serial.print(isAutomatic);
Serial.println(" Valve task triggered.");
unsigned long valveTimeoutTimer = millis();
bool valveOpen = false;
int initialSoilMoisture = readCapacitiveSoilMoistureSensor();
if (initialSoilMoisture <= permanentWiltingPoint || irrigateUntilFC) {
valveOpen = openValve();
irrigateUntilFC = true;
} else {
Serial.println("Soil contains enough water. No irrigation needed. ");
}
while (valveOpen) {
delay(500);
int mstValue = readCapacitiveSoilMoistureSensor();
if (mstValue > fieldCapacity) { // && isAutomatic
Serial.println("Field capacity reached. No irrigation needed. ");
valveOpen = closeValve();
irrigateUntilFC = false;
}
if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) {
Serial.println("Irrigation timeout reached. close valve. ");
valveOpen = closeValve();
}
}
releaseSemaphore();
vTaskDelete(NULL);
}
void toggleValve(bool automatic) {
xTaskCreate(
valveTask, /* Task function. */
"valveTask", /* String with name of task. */
2048, /* Stack size in bytes. */
&automatic, /* Parameter passed as input of the task */
3, /* Priority of the task. */
NULL); /* Task handle. */
}
void persistSoilProps(int FC, int PWP, int SAT) {
takeSemaphore();
Serial.println("persistSoilProps");
bool f = NVS.setInt("fieldCapacity", FC);
bool p = NVS.setInt("permanentWilt", PWP);
@ -137,7 +30,6 @@ void persistSoilProps(int FC, int PWP, int SAT) {
else {
Serial.println("error occured while trying to persist soil properties");
}
releaseSemaphore();
}
void restoreSoilProps() {
@ -163,18 +55,11 @@ void restoreSoilProps() {
}
void setupStore() {
NVS.begin("store");
initDeviceID();
restoreSoilProps();
restoreLightProps();
restoreAutoProps();
strcpy(MQTT_SENSOR_DATA_TOPIC, MQTT_TOPIC_BASE_PUB "/");
strcat(MQTT_SENSOR_DATA_TOPIC, getDeviceIDcharArr());
strcat(MQTT_SENSOR_DATA_TOPIC, "/data");
Serial.println("MQTT_SENSOR_DATA_TOPIC:");
Serial.println(MQTT_SENSOR_DATA_TOPIC);
}
void setSoilProperties(int FC, int PWP, int SAT) {
@ -191,7 +76,6 @@ void setSoilProperties(int FC, int PWP, int SAT) {
}
void persistLightProps(int NM, int minLX) {
takeSemaphore();
Serial.println("persistLightProps");
bool n = NVS.setInt("nanoMeter", NM);
bool m = NVS.setInt("minimumLux", minLX);
@ -202,7 +86,6 @@ void persistLightProps(int NM, int minLX) {
else {
Serial.println("error occured while trying to persist light properties");
}
releaseSemaphore();
}
void restoreLightProps() {
@ -227,7 +110,6 @@ void setLightProperties(int NM, int minLX) {
}
void persistAutoProps(bool light, bool irrigation) {
takeSemaphore();
Serial.println("persistAutoProps");
// saved in NVS as Integer: 1 = true, 2 = false, 0 = not persisted, use standard settings
bool n = NVS.setInt("automaticLight", (light ? 1 : 2));
@ -238,7 +120,6 @@ void persistAutoProps(bool light, bool irrigation) {
} else {
Serial.println("error occured while trying to persist auto properties");
}
releaseSemaphore();
}
void restoreAutoProps() {

29
src/store.h Normal file
View File

@ -0,0 +1,29 @@
// Feldkapazität des Bodens in Prozent: Standard ist Humus
extern int fieldCapacity;
// PWP des Bodens in Prozent: Standard ist Humus
extern int permanentWiltingPoint;
// Boden vollständig gesättigt bei (Prozent): Standard ist Humus
extern int soilSaturation;
// Helligkeitswert der mindestens vorhanden sein muss
extern int minimumLightValueLX;
// switches for automatic light and irrigation control
extern bool automaticLight;
extern bool automaticIrrigation;
// make sure device irrigates until fieldcapacity is reached
extern bool irrigateUntilFC;
// Device UUID will be set on first boot.
extern String DEVICE_ID;
void persistSoilProps(int FC, int PWP, int SAT);
void restoreSoilProps();
void setupStore();
void setSoilProperties(int FC, int PWP, int SAT);
void persistLightProps(int NM, int minLX);
void restoreLightProps();
void setLightProperties(int NM, int minLX);
void persistAutoProps(bool light, bool irrigation);
void restoreAutoProps();
void setAutoProperties(bool light, bool irrigation);
void initDeviceID();
String getDeviceID();
const char* getDeviceIDcharArr();

View File

@ -1,7 +1,9 @@
#include <header.h>
#include <DHT.h>
#include <DHT_U.h>
#include <common.h>
#define DHTPIN PIN_DHT11
#define DHTTYPE DHT11

3
src/temperatureSensor.h Normal file
View File

@ -0,0 +1,3 @@
void setupTemperatureSensor();
float readHumidity();
float readTemperature();

66
src/valve.cpp Normal file
View File

@ -0,0 +1,66 @@
#include <capacitiveSoilMoistureSensor.h>
#include <common.h>
#include <store.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
}
#include <valve.h>
bool openValve() {
digitalWrite(PIN_VALVE, HIGH);
digitalWrite(PIN_LED_G, LOW);
digitalWrite(PIN_LED_B, HIGH);
return true;
}
bool closeValve() {
digitalWrite(PIN_VALVE, LOW);
digitalWrite(PIN_LED_G, HIGH);
digitalWrite(PIN_LED_B, LOW);
return false;
}
void valveTask(void *parameter) {
bool isAutomatic = (bool)parameter;
Serial.print(isAutomatic);
Serial.println(" Valve task triggered.");
unsigned long valveTimeoutTimer = millis();
bool valveOpen = false;
int initialSoilMoisture = readCapacitiveSoilMoistureSensor();
if (initialSoilMoisture <= permanentWiltingPoint || irrigateUntilFC) {
valveOpen = openValve();
irrigateUntilFC = true;
} else {
Serial.println("Soil contains enough water. No irrigation needed. ");
}
while (valveOpen) {
delay(500);
int mstValue = readCapacitiveSoilMoistureSensor();
if (mstValue > fieldCapacity) { // && isAutomatic
Serial.println("Field capacity reached. No irrigation needed. ");
valveOpen = closeValve();
irrigateUntilFC = false;
}
if (millis() - valveTimeoutTimer >= MAX_VALVE_TIMEOUT) {
Serial.println("Irrigation timeout reached. close valve. ");
valveOpen = closeValve();
}
}
vTaskDelete(NULL);
}
void toggleValve(bool automatic) {
xTaskCreate(
valveTask, /* Task function. */
"valveTask", /* String with name of task. */
2048, /* Stack size in bytes. */
&automatic, /* Parameter passed as input of the task */
3, /* Priority of the task. */
NULL); /* Task handle. */
}

1
src/valve.h Normal file
View File

@ -0,0 +1 @@
void toggleValve(bool automatic);