Skip to content

Instantly share code, notes, and snippets.

@kakopappa
Last active March 27, 2024 06:18
Show Gist options
  • Save kakopappa/50ae7f8e6a30c46fea1845ee72a7593a to your computer and use it in GitHub Desktop.
Save kakopappa/50ae7f8e6a30c46fea1845ee72a7593a to your computer and use it in GitHub Desktop.
#ifndef _CAPACITIVESOILMOISTURESENSOR_H_
#define _CAPACITIVESOILMOISTURESENSOR_H_
#include <SinricProDevice.h>
#include <Capabilities/ModeController.h>
#include <Capabilities/RangeController.h>
#include <Capabilities/PushNotification.h>
class CapacitiveSoilMoistureSensor
: public SinricProDevice
, public ModeController<CapacitiveSoilMoistureSensor>
, public RangeController<CapacitiveSoilMoistureSensor>
, public PushNotification<CapacitiveSoilMoistureSensor> {
friend class ModeController<CapacitiveSoilMoistureSensor>;
friend class RangeController<CapacitiveSoilMoistureSensor>;
friend class PushNotification<CapacitiveSoilMoistureSensor>;
public:
CapacitiveSoilMoistureSensor(const String &deviceId) : SinricProDevice(deviceId, "CapacitiveSoilMoistureSensor") {};
};
#endif
// #define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG_ESP_PORT Serial
#define NODEBUG_WEBSOCKETS
#define NDEBUG
#endif
#include <Arduino.h>
#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef ESP32
#include <WiFi.h>
#endif
#include <SinricPro.h>
#include "CapacitiveSoilMoistureSensor.h"
// Grab it from https://portal.sinric.pro.
#define APP_KEY "" //Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET "" //Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
#define DEVICE_ID "" //Should look like "6534xxxxxxxc08c6ea1b"
#define SSID "" // Your WiFi SSID
#define PASS "" // Your WiFi Password
#define BAUD_RATE 115200 // Change baudrate to your need (used for serial monitor)
#define EVENT_WAIT_TIME 60000 // send event every 60 seconds
#if defined(ESP8266)
const int adcPin = A0;
#elif defined(ESP32)
const int adcPin = 34;
#elif defined(ARDUINO_ARCH_RP2040)
const int adcPin = 26;
#endif
const int VERY_DRY = 720; // TODO: This is when soil is dry. Adjust according to your sensor
const int VERY_WET = 560; // TODO: This is when soil is wet. Adjust according to your sensor
const int NEITHER_DRY_OR_WET = 620; // TODO: This is when soil is neither wet or dry. Adjust according to your sensor
const int DRY_PUSH_NOTIFICATION_THRESHHOLD = 700; // TODO: This is when to send a push notification to the mobile phone. Adjust according to your sensor
const int UNPLUGGED = 735; // This is the value sensor produce when it's not in the ground.
int lastSoilMoisture = 0;
String lastSoilMoistureStr = "";
CapacitiveSoilMoistureSensor &capacitiveSoilMoistureSensor = SinricPro[DEVICE_ID];
void updateSoilState(String mode) {
capacitiveSoilMoistureSensor.sendModeEvent("modeInstance1", mode, "PHYSICAL_INTERACTION");
}
void updateMoistureLevel(int value) {
capacitiveSoilMoistureSensor.sendRangeValueEvent("rangeInstance1", value);
}
void sendPushNotification(String message) {
capacitiveSoilMoistureSensor.sendPushNotification(message);
}
void handleCapacitiveSoilMoistureSensor() {
if (SinricPro.isConnected() == false) {
return;
}
static unsigned long last_millis;
unsigned long current_millis = millis();
if (last_millis && current_millis - last_millis < EVENT_WAIT_TIME) return;
last_millis = current_millis;
int soilMoisture = analogRead(adcPin);
int percentage = map(soilMoisture, VERY_WET, VERY_DRY, 100, 0);
percentage = constrain(percentage, 1, 100);
Serial.printf("Soil Moisture: %d. as a percentage: %d%%\r\n", soilMoisture, percentage);
if (isnan(soilMoisture)) { // reading failed...
Serial.printf("Capacitive Soil Moisture Sensor reading failed!\r\n"); // print error message
return; // try again next time
}
if (soilMoisture == lastSoilMoisture) {
Serial.printf("Soil moisture did not changed. do nothing...!\r\n");
return;
}
// Determine Wet or Dry.
String soilMoistureStr = "";
if(soilMoisture > NEITHER_DRY_OR_WET) {
soilMoistureStr = "Dry"; // NOTE: must be Wet, Dry. This is from modes list in template.
} else {
soilMoistureStr = "Wet";
}
// Update Moisture label
if(lastSoilMoistureStr != soilMoistureStr) {
lastSoilMoistureStr = soilMoistureStr;
updateSoilState(soilMoistureStr);
}
delay(500);
// Update Moisture level label
updateMoistureLevel(percentage);
// Send push notifications
if(soilMoisture > DRY_PUSH_NOTIFICATION_THRESHHOLD) {
sendPushNotification("Plants are too dry. Time to water the plants!");
}
if(soilMoisture > UNPLUGGED) {
sendPushNotification("Sensor seems to be unhooked. Please check!");
}
lastSoilMoisture = soilMoisture; // save to compare next time.
}
/*********
* Setups *
*********/
void setupSinricPro() {
SinricPro.onConnected([]{ Serial.printf("[SinricPro]: Connected\r\n"); });
SinricPro.onDisconnected([]{ Serial.printf("[SinricPro]: Disconnected\r\n"); });
SinricPro.begin(APP_KEY, APP_SECRET);
};
void setupSensor() {
pinMode(adcPin, INPUT);
}
void setupWiFi() {
#if defined(ESP8266)
WiFi.setSleepMode(WIFI_NONE_SLEEP);
WiFi.setAutoReconnect(true);
#elif defined(ESP32)
WiFi.setSleep(false);
WiFi.setAutoReconnect(true);
#endif
WiFi.begin(SSID, PASS);
Serial.printf("[WiFi]: Connecting to %s", SSID);
while (WiFi.status() != WL_CONNECTED) {
Serial.printf(".");
delay(250);
}
Serial.printf("connected\r\n");
}
void setup() {
Serial.begin(BAUD_RATE);
setupSensor();
setupWiFi();
setupSinricPro();
}
/********
* Loop *
********/
void loop() {
SinricPro.handle();
handleCapacitiveSoilMoistureSensor();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment