#include <Adafruit_Sensor.h>
#include <DHT_U.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <FastLED.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define DHTPIN 12
#define LED_HEATING 26 // Пин за отоплителния LED
#define LED_STRIP1_PIN 4 // Пин за WS812 LED лента
#define LED_STRIP2_PIN 5 // Пин за WS812 LED лента
#define LED_STRIP3_PIN 2 // Пин за WS812 LED лента
#define LED_STRIP4_PIN 0 // Пин за WS812 LED лента
#define NUM_LEDS 16 // Брой на LED в лентите
#define NUM_STRIPS 3 // Броя на LED кръговете
#define SCREEN_WIDTH 128 // Широчина на OLED дисплея
#define SCREEN_HEIGHT 64 // Височина на OLED дисплея
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Параметри за DHT сензора
#define DHTTYPE DHT22
DHT_Unified dht(DHTPIN, DHTTYPE);
CRGB leds[NUM_STRIPS][NUM_LEDS];
// MQTT данни за достъп
const char* ssid = "Wokwi-GUEST"; // SSID на вашия Wi-Fi мрежа
const char* password = ""; // Парола на Wi-Fi мрежата
const char* mqttServer = "broker.hivemq.com";
const int mqttPort = 1883;
const char* clientID = "ZlatkoSmartStudio"; // Идентификатор на клиента
const char* topic = "Tempdata"; // Тема за публикуване на данни
// Флаг за контрол на LED диода и LED ринговете
bool ledOn = false;
bool ring_1_on = false;
bool ring_2_on = false;
bool ring_3_on = false;
// Променливи за управление на времето
unsigned long previousMillis = 0;
const long interval = 1000; // 1 секунда
String msgStr = ""; // Буфер за MQTT съобщение
float temp = 0.0; // Променлива за температура
float hum = 0.0; // Променлива за влажност
int red, green, blue; // Променливи за цветовете на ринговете
// Настройка на Wi-Fi и MQTT клиент
WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi() {
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
while (!client.connected()) {
if (client.connect(clientID)) {
Serial.println("MQTT connected");
client.subscribe("lights");
client.subscribe("lights/LED_HEATING"); // Абониране за тема на LED_HEATING
client.subscribe("lights/neopixel1"); // Абониране за тема на NeoPixel1
client.subscribe("lights/neopixel1_OnOff"); // Абониране за тема на NeoPixel1 ON OFF
client.subscribe("lights/neopixel2"); // Абониране за тема на NeoPixel2
client.subscribe("lights/neopixel2_OnOff"); // Абониране за тема на NeoPixel2 ON OFF
client.subscribe("lights/neopixel3"); // Абониране за тема на NeoPixel3
client.subscribe("lights/neopixel3_OnOff"); // Абониране за тема на NeoPixel3 ON OFF
Serial.println("Topic Subscribed");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000); // Изчакване 5 секунди и опит за повторно свързване
}
}
}
// Callback функция за абониране
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message: ");
String data = "";
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
data += (char)payload[i];
}
Serial.println();
Serial.print("Message size: ");
Serial.println(length);
Serial.println();
Serial.println("-----------------------");
Serial.println(data);
if (String(topic) == "lights/LED_HEATING") {
if (data == "ON") {
Serial.println("LED ON");
ledOn = true;
digitalWrite(LED_HEATING, HIGH); // Включване на LED диода
}
else if (data == "OFF") {
Serial.println("LED OFF");
ledOn = false;
digitalWrite(LED_HEATING, LOW); // Изключване на LED диода
}
}
if (String(topic) == "lights/neopixel1_OnOff") {
if (data == "ON LED Ring 1") {
Serial.println("LED RING 1 ON");
ring_1_on = true;
}
else if (data == "OFF LED Ring 1") {
Serial.println("OFF LED Ring 1");
ring_1_on = false;
fill_solid(leds[0], NUM_LEDS, CRGB::Black); // Изгасяне на всички диоди в Ring-a
FastLED.show();
}
}
if (String(topic) == "lights/neopixel2_OnOff") {
if (data == "ON LED Ring 2") {
Serial.println("LED RING 2 ON");
ring_2_on = true;
}
else if (data == "OFF LED Ring 2") {
Serial.println("OFF LED Ring 2");
ring_2_on = false;
fill_solid(leds[1], NUM_LEDS, CRGB::Black); // Изгасяне на всички диоди в Ring-a
FastLED.show();
}
}
if (String(topic) == "lights/neopixel3_OnOff") {
if (data == "ON LED Ring 3") {
Serial.println("LED RING 3 ON");
ring_3_on = true;
}
else if (data == "OFF LED Ring 3") {
Serial.println("OFF LED Ring 3");
ring_3_on = false;
fill_solid(leds[2], NUM_LEDS, CRGB::Black); // Изгасяне на всички диоди в Ring-a
FastLED.show();
}
}
if (String(topic) == "lights/neopixel1" && ring_1_on) {
sscanf(data.c_str(), "%d,%d,%d", &red, &green, &blue); // Анализиране на получените данни в RGB стойности
Serial.print("Setting NeoPixel1 color to (R,G,B): ");
Serial.print(red);
Serial.print(",");
Serial.print(green);
Serial.print(",");
Serial.println(blue);
fill_solid(leds[0], NUM_LEDS, CRGB(red, green, blue)); // Слагане на определен цвят на всички диоди в ринг 1
FastLED.show(); //Промяна на цвета на LED STRIP 1
}
else if (String(topic) == "lights/neopixel2" && ring_2_on) {
sscanf(data.c_str(), "%d,%d,%d", &red, &green, &blue); // Анализиране на получените данни в RGB стойности
Serial.print("Setting NeoPixel2 color to (R,G,B): ");
Serial.print(red);
Serial.print(",");
Serial.print(green);
Serial.print(",");
Serial.println(blue);
fill_solid(leds[1], NUM_LEDS, CRGB(red, green, blue)); // Слагане на определен цвят на всички диоди в ринг 2
FastLED.show(); //Промяна на цвета на LED STRIP 2
}
else if (String(topic) == "lights/neopixel3" && ring_3_on) {
int red, green, blue;
sscanf(data.c_str(), "%d,%d,%d", &red, &green, &blue); // Анализиране на получените данни в RGB стойности
Serial.print("Setting NeoPixel3 color to (R,G,B): ");
Serial.print(red);
Serial.print(",");
Serial.print(green);
Serial.print(",");
Serial.println(blue);
fill_solid(leds[2], NUM_LEDS, CRGB(red, green, blue)); // Слагане на определен цвят на всички диоди в ринг 3
FastLED.show(); //Промяна на цвета на LED STRIP 3
}
}
void setup() {
Serial.begin(115200);
// Инициализация на устройството.
dht.begin();
// Получаване на подробности за температурния сензор.
sensor_t sensor;
dht.temperature().getSensor(&sensor);
dht.humidity().getSensor(&sensor);
pinMode(LED_HEATING, OUTPUT);
digitalWrite(LED_HEATING, LOW); // Изключване на LED диода
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
//Текст на дисплея
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Welcome!");
display.setCursor(0, 10);
display.println("ZLATKO SMART STUDIO");
display.setCursor(0, 20);
display.println("ON!!!");
display.display();
delay(1000);
// Настройка на WS2812 LED лента
FastLED.addLeds<WS2812, LED_STRIP1_PIN, GRB>(&leds[0][0], NUM_LEDS);
FastLED.addLeds<WS2812, LED_STRIP2_PIN, GRB>(&leds[1][0], NUM_LEDS);
FastLED.addLeds<WS2812, LED_STRIP3_PIN, GRB>(&leds[2][0], NUM_LEDS);
setup_wifi();
client.setServer(mqttServer, 1883); // Задаване на MQTT сървъра
client.setCallback(callback); // Дефиниране на функция, която ще се извика при получаване на съобщение
}
void loop() {
if (!client.connected()) { // Ако клиентът не е свързан
reconnect(); // Опитайте да се свържете отново
}
client.loop();
unsigned long currentMillis = millis(); // Четене на текущото време
if (currentMillis - previousMillis >= interval) { // Ако текущото време - последното време > 5 секунди
previousMillis = currentMillis;
// Четене на температурата и влажността
sensors_event_t event;
dht.temperature().getEvent(&event);
if (isnan(event.temperature)) {
Serial.println(F("Error reading temperature!"));
}
else {
Serial.print(F("Temperature: "));
temp = event.temperature;
Serial.print(temp);
Serial.println(F("°C"));
}
// Получаване на влажността и извеждане на стойността й
dht.humidity().getEvent(&event);
if (isnan(event.relative_humidity)) {
Serial.println(F("Error reading humidity!"));
}
else {
Serial.print(F("Humidity: "));
hum = event.relative_humidity;
Serial.print(hum);
Serial.println(F("%"));
}
msgStr = String(temp) + "," + String(hum) + ",";
byte arrSize = msgStr.length() + 1;
char msg[arrSize];
Serial.print("PUBLISH DATA: ");
Serial.println(msgStr);
msgStr.toCharArray(msg, arrSize);
client.publish(topic, msg);
msgStr = "";
delay(1);
display.clearDisplay();
display.setCursor(0, 0);
display.printf("TEMP: %.2f C\n", temp); // извеждане на температурата на OLED display
display.setCursor(0, 10);
display.printf("Humidity: %.2f %%\n", hum); // извеждане на влажността на OLED display
//извеждане данни дали са включени Neopixel Ring-овете на OLED display
if(ring_1_on == true){
display.setCursor(0, 20);
display.println("LED RING 1 ON");
}
else {
display.setCursor(0, 20);
display.println("LED RING 1 OFF");
}
if(ring_2_on == true){
display.setCursor(0, 30);
display.println("LED RING 2 ON");
}
else {
display.setCursor(0, 30);
display.println("LED RING 2 OFF");
}
if(ring_3_on == true){
display.setCursor(0, 40);
display.println("LED RING 3 ON");
}
else {
display.setCursor(0, 40);
display.println("LED RING 3 OFF");
}
// Извеждане на данни дали е включено отпоплението (В случая LED HEATING диода)
if(ledOn == true){
display.setCursor(0, 50);
display.println("LED HEATING ON");
}
else {
display.setCursor(0, 50);
display.println("LED HEATING OFF");
}
display.display();
delay(100);
}
}