// библиотеки за Wi-Fi, Adafruit IO и LCD екран
#include <WiFi.h>
#include "AdafruitIO_WiFi.h"
#include <LiquidCrystal_I2C.h>
// настройки за LCD екрана
#define LCD_ADDR 0x27 // I2C адрес на LCD-то
#define LCD_COLUMNS 16 // 16 колони
#define LCD_ROWS 2 // 2 реда
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLUMNS, LCD_ROWS);
// настройки за Wi-Fi и Adafruit IO
#define IO_USERNAME "tomi45bg" // име на акаунта в Adafruit IO
#define IO_KEY "aio_crKm25sx8aoI3nBxZDBl1Mxy4pky" // ключ за Adafruit IO
const char* SSID = "Wokwi-GUEST"; // SSID за Wi-Fi
const char* PASS = ""; // парола
// Клиент за Adafruit IO през Wi-Fi
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, SSID, PASS);
// Feed, който се следи и записва в cloud платформата Adafruit
AdafruitIO_Feed *soilFeed = io.feed("soil_moisture"); // указател към feed, който следи за влажността
// Пинове
#define SOIL_MOISTURE_PIN 34 // вход към потенциометърът
#define RELAY_PIN 12 // изход към реле (което симулира помпа/лампа)
#define BUZZER_PIN 5 // изход към бъзър/аларма
// Някои променливи
int buzzerVolume = 255; // аларма
int simulatedMoisture = 40; // стартова стойност за симулация/автоматичен режим
bool useSimulation = false; // false = ползва се потенциометъра; true = симулация/автоматично
// Функция, изпълняваща се само веднъж в началото на програмата
void setup() {
Serial.begin(9600); // серийна конзола
pinMode(SOIL_MOISTURE_PIN, INPUT); // Входящ пин за влажността
pinMode(RELAY_PIN, OUTPUT); // Изходящ пин за релето/помпата
pinMode(BUZZER_PIN, OUTPUT); // Изходащ пин за алармата
digitalWrite(RELAY_PIN, LOW); // Релето е изключено в началото
// Свързване с Adafruit IO (блокиращо изчакване до свързване)
io.connect();
while (io.status() < AIO_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("Свърза се с Adafruit IO!");
// Инициализация на LCD екрана
lcd.begin(16, 2); // 16x2 екран
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0); // Първоначално местоположение на курсора
lcd.print("Moisture level"); // Първи ред на екрана
}
// Функция, която се изпълнява многократно (в цикъл)
void loop() {
io.run(); // Поддържа активна връзка и обработва Adafruit IO задачи
int moisture; // стойност за текущата влага (от 0% до 100%)
// Симулиран/автоматичен режим
if (useSimulation) {
simulatedMoisture -= 4; // симулира естественото намаляне на влагата с някаква стойност
// При стойност под 30% почва да предупреждава за ниска влажност
if (simulatedMoisture <= 30){
// Релето се активирва + лампа, сигнализираща ниско количество вода
digitalWrite(RELAY_PIN, HIGH);
// Алармата се активирва
tone(BUZZER_PIN, 500, buzzerVolume);
}
// При стойност под 15% симулирва наливане на вода до 80%
if (simulatedMoisture <= 15) {
simulatedMoisture = 80; // поливане до 80%
// съобщение до конзолата
Serial.println("Почвата е твърде суха! Поливане до 80%!");
}
moisture = simulatedMoisture; // текущата симулирана стойност
} else {
// реален режим; четене от потенциометърът
int soilVal = analogRead(SOIL_MOISTURE_PIN); // четеме стойността от пина
moisture = map(soilVal, 0, 4095, 0, 100); // превръщаме в четим вариант от 0 до 100
}
// Съобщение до конзолата за нивото на влажността
Serial.print("Ниво на влажността: ");
Serial.println(moisture);
// Обновяване на втория ред на екрана (стойността на влажността)
lcd.print(" "); // изчистване на реда
lcd.setCursor(0, 1); // позициониране на курсора
lcd.print(moisture); //пишем нивото на влагата
lcd.print("%");
// Изпращане към Adafruit IO
soilFeed->save(moisture);
// управление на влагата/релето/алармата при различни нива на влагата
if (moisture < 15) {
// сухо: включва се помпата/лампата и кратък звуков сигнал
// плюс предупреждения да се полее вода ръчно (тук се използва потенциометърът)
digitalWrite(RELAY_PIN, HIGH); //включване на релето/лампата
tone(BUZZER_PIN, 500, buzzerVolume); // по-силна аларма при суха почва
Serial.println("Полей растението!!!!");
} else if (moisture > 80) {
// твърде много вода
digitalWrite(RELAY_PIN, HIGH);
tone(BUZZER_PIN, 250, buzzerVolume); // аларма
Serial.println("Твърде много вода!!");
} else {
// идеална влага (всичко е изключено)
digitalWrite(RELAY_PIN, LOW);
noTone(BUZZER_PIN);
Serial.println("Нивото на влагата е идеално.");
}
delay(2000); // цикъл през 2 секунди
}