Здравейте ,
Искам да ви представя моята идея за автоматична поливна система.
Системата съм я замислил за универсално ползване: за различни култури, смесено (оранжерия и градина), райграс и цветя....
За целта трябва да е изградена на модулен принцип.
1. Датчици за почвена влага -> полагат се на места с идентични по нужда от влага растения или на различни места като нужда от поливане
2. Изпълнителни устройства -> вентили за водата в поливната система
3. Централен модул -> "мозъка" на системата. Трябва да позволява изпълнение на различни предварително зададени програми
4. Ръчен режим. Мисля да се ползва смартфон, тъй като обикновено "винаги е в джоба".
Опции:
- контрол нивото на резервоар за водата за поливане със опция за следене на количеството изразходвана вода
- автоматично допълване на резервоара чрез помпа
Тъй като проекта е доста обемист, сега ще ви представя само точка 1 - датчиците за влага
Тъй като датчиците ще са разхвърляни на различни места е задължително да бъдат енергонезависими и безжични.
За целта ползвам китайски капацитивен датчик за влага, който побългарих. Може да се направи и самостоятелно, но е проблем самата сонда. Задължително трябва да е водонепропусклива!
За изпращане на данните ползвам ESP8266 - Контролер с вградено WiFi. Ползвам чисто ESP8266 v12 за по-ниска консумация в режим сън.
Данните се записват MQTT сървър. Имам си вдигнат мой личен на едно старо лаптопче с Debian. Но има и много free из нета.
ESP-то го свързвам по стандартния начин:
Прикачени файлове:
scheme-full.jpg [ 26.58 KiB | Прегледано 2583 пъти ]
GPIO12 го ползвам за захранване на датчика и за следене нивото на батерията
GPIO14 мери дължината на периода на импулса / от там съответно влагата
Прикачени файлове:
datchik.jpg [ 32.19 KiB | Прегледано 2583 пъти ]
Пропуснал съм на картинката да сложа извода към ADC на контролера. Взема се от делителя на напрежение 10к - 1к.
Принципа на мерене на датчика е осцилатор, на който във времезадаващата верига вместо кондензатор се ползва сонда, забита в почвата. Влагата играе роля на електролит, повишава капацитета на сондата и увеличава периода на колебанията. На оригиналния датчик, сондата беше включена в една диферинцираща верига след осцилатора ( с константна честота ) затова се наложи да я побългаря. В противен случай трябваше да ползвам единствения аналогов пин на контролера, който сега ми се освободи за мерене състоянието на батерията.
Прикачени файлове:
1605103768627.jpg [ 2.5 MiB | Прегледано 2583 пъти ]
ето и променения датчик:
Прикачени файлове:
1605103768637.jpg [ 3.94 MiB | Прегледано 2583 пъти ]
А това е кода, който трябва да се качи на контролера:
Код за потвърждение:
#include "EspMQTTClient.h"
#include <Arduino.h>
#define power 12 // GPIO12 се използва като захранване на осцилатора и за мерене на батерията
#define pulse_ip 14 // GPIO14 са ползва за мерене на периода на генерирания сигнал
int DeepSleep;
int minPeriod, maxPeriod;
EspMQTTClient client(
"името_на_вашата_мрежа", // име на WiFi мрежата
"паролата_за_вашата_мрежа", // парола за мрежата
"IP_адреса_MQTT", // адрес на MQTT брокера
"MQTTUsername", // може да се пропусне, ако не е необходимо
"MQTTPassword",
"Measture meter1", // Име на клиента, с което ще се идентифицира устройството
1883 // MQTT порт ( по подразбиране е 1883)
);
void setup()
{
Serial.begin(115200);
pinMode(power,OUTPUT);
Serial.println("Traying to connect......");
pinMode(BUILTIN_LED,OUTPUT);
digitalWrite(BUILTIN_LED, LOW);
client.enableDebuggingMessages(); // Enable debugging messages sent to serial output
}
void onConnectionEstablished()
{
// вземаме настройките
client.subscribe("mytopic/settingsM/minPeriod", [](const String & payload) { minPeriod=payload.toInt(); });
client.subscribe("mytopic/settingsM/maxPeriod", [](const String & payload) { maxPeriod=payload.toInt(); });
client.subscribe("mytopic/settingsM/deepSleep", [](const String & payload) { DeepSleep=payload.toInt(); });
}
void loop()
{
client.loop();
if ((minPeriod>0) && (maxPeriod>0) && (DeepSleep>0)){ getdata();} // изчакваме докато се вземат настройките
// таймаут 20сек !!!! ако свързването към рутера става по-бавно е необходимо да се коригира стойността от 20000 на 30000 и повече...
if (millis()>20000){Serial.println("Cannot connect....."); if (DeepSleep==0){DeepSleep=900;} Serial.println("Deep sleep for " + String(DeepSleep) + " seconds..."); uint32_t mDeepSleep = DeepSleep * 1000000; ESP.deepSleep(mDeepSleep);}
}
void getdata(){
if (DeepSleep > 4200){DeepSleep=4200;} //4200сек. е около максимума като време за приспиване за ESP8266
Serial.println("Connect success...");
Serial.println("minPeriod:" + String(minPeriod) + " maxPeriod:" + String(maxPeriod) + " DeepSleep:" + String(DeepSleep));
digitalWrite(power,HIGH); // включваме осцилатора
delay(10);
int sensorValue = analogRead(A0);
delay(10);
double bat= sensorValue*10.565; // коефициента го подбираме опитно, в зависимост от точността на делителя. Принципно трябва да е 10000mV/1024 = 9.765mV/bit
delay(100);
int i;
float hPeriod;
for (i=0; i<100; i++){ // мерим 100 пъти и вземаме средно аритметично за по-голяма точност
int ontime = pulseIn(pulse_ip,HIGH,2000); // тук третия параметър е таймаута в милисекунди. Може да се наложи да се увеличи, ако мин. честота е по-ниска
int offtime = pulseIn(pulse_ip,LOW,2000);
int period = ontime+offtime;
hPeriod=hPeriod+period;
}
hPeriod=hPeriod/100; // вземаме средноаритметично
Serial.println("Period is : " + String(hPeriod));
float period=hPeriod;
// if (hPeriod<minPeriod){hPeriod=minPeriod;}
float percent= map(hPeriod,minPeriod,maxPeriod,0,100); // преобразуваме в проценти
// публикуваме данните
client.publish("mytopic/Measture/percent1",String(percent),true);
delay(100);
client.publish("mytopic/Measture/Period1",String(period),true);
delay(100);
client.publish("mytopic/Measture/voltage1",String(bat/1000),true);
delay(100);
client.publish("mytopic/Measture/battery1",String(map(bat/1000,2.7,3.2,0,100)),true);
// гасим захранването на осцилатора и за мерене нивото на батерията
digitalWrite(power,LOW);
digitalWrite(BUILTIN_LED, HIGH);
pinMode(BUILTIN_LED,INPUT);
delay(100);
Serial.println("Deep sleep for " + String(DeepSleep) + " seconds...");
uint32_t mDeepSleep = DeepSleep * 1000000;
ESP.deepSleep(mDeepSleep); // приспиваме контролера
}
Захранвам датчика с две батерии ААА. По груби сметки би трябвало да издържат около 6 месеца. Оставил съм го забучен в една саксия, ще видим колко ще издържи.
Иначе е по-удачно с една литиева батерия през един силициев диод и малко соларно панелче... Ама това за по-нататък..
За ръчния режим ползвам MQTTDash инсталиран на телефона. Правя трите настройки (mytopic/settingsM/minPeriod........) като "Retained". Естествено, могат да се казват например "Vilata/Polivane/minimum1". Като ,разбира се, така трябва да се промени и в кода горе.
Ето и готовия датчик:
Прикачени файлове:
1605103768631.jpg [ 4.95 MiB | Прегледано 2583 пъти ]
Сигурно съм пропуснал нещо важно, ако има интерес, питайте..
