#include <TimeLib.h>
#include <DHT.h>
#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
#include "P.h"
SemaphoreHandle_t xSerialSem;
QueueHandle_t xFila;
SemaphoreHandle_t xSerialSem2;
TaskHandle_t Task1;
TaskHandle_t Task2;
TaskHandle_t Task3;
TaskHandle_t Task4;
TaskHandle_t Task5;
// LED pins
const int led1 = 2;
const int led2 = 4;
int connected = 0;
DHT dht(12, DHT22);
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 16, 2);
#define NTP_SERVER "ru.pool.ntp.org"
#define UTC_OFFSET 3 // Moscow Time (UTC+3)
#define UTC_OFFSET_DST 0
#define SPEAKER_PIN 5
int tamFila = 200;
void setup()
{
Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(SPEAKER_PIN, OUTPUT);
if (xSerialSem == NULL)
{
xSerialSem = xSemaphoreCreateMutex();
if (xSerialSem != NULL)
xSemaphoreGive(xSerialSem);
}
if (xSerialSem2 == NULL)
{
xSerialSem2 = xSemaphoreCreateMutex();
if (xSerialSem2 != NULL)
xSemaphoreGive(xSerialSem2);
}
xFila = xQueueCreate(tamFila, sizeof(String));
if (xFila == NULL)
{
Serial.println("Erro criando fila");
}
LCD.init();
LCD.backlight();
// Create tasks
xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, &Task1, 0);
xTaskCreatePinnedToCore(Task2code, "Task2", 10000, NULL, 1, &Task2, 0);
xTaskCreatePinnedToCore(Task3code, "Task3", 10000, NULL, 1, &Task3, 1);
xTaskCreatePinnedToCore(Task4code, "Task4", 10000, NULL, 1, &Task4, 1);
xTaskCreatePinnedToCore(Task5code, "Task5", 10000, NULL, 1, &Task5, 0);
}
void Task1code(void *pvParameters)
{
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for (;;)
{
digitalWrite(led1, HIGH);
vTaskDelay(1000);
digitalWrite(led1, LOW);
vTaskDelay(1000);
}
}
void Task2code(void *pvParameters)
{
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID());
for (;;)
{
digitalWrite(led2, HIGH);
vTaskDelay(700);
digitalWrite(led2, LOW);
vTaskDelay(700);
}
}
void Task3code(void *pvParameters)
{
Serial.print("Task3 running on core ");
Serial.println(xPortGetCoreID());
for (;;)
{
if (connected == 1)
{
if (xSemaphoreTake(xSerialSem, (TickType_t)5) == pdTRUE)
{
Serial.println("Task 3");
Serial.println("Temp: " + String(dht.readTemperature(), 1) + " \260C");
Serial.println("Hum: " + String(dht.readHumidity(), 1) + " %");
if (xSemaphoreTake(xSerialSem2, (TickType_t)10) == pdTRUE)
{
String minhaString = String(dht.readTemperature(), 1) + " \260C";
xQueueSend(xFila, (void *)&minhaString, portMAX_DELAY);
xSemaphoreGive(xSerialSem2);
}
printLocalTime();
vTaskDelay(1000);
xSemaphoreGive(xSerialSem);
}
}
else
{
vTaskDelay(700);
}
}
}
void Task4code(void *pvParameters)
{
Serial.print("Task4 running on core ");
Serial.println(xPortGetCoreID());
for (;;)
{
if (connected == 0)
{
if (xSemaphoreTake(xSerialSem, (TickType_t)5) == pdTRUE)
{
Serial.println("Task 4");
LCD.setCursor(0, 0);
LCD.print("Connecting to ");
LCD.setCursor(0, 1);
LCD.print("WiFi ");
WiFi.begin("Wokwi-GUEST", "", 6); // Replace with your Wi-Fi credentials
while (WiFi.status() != WL_CONNECTED)
{
vTaskDelay(10);
spinner();
Serial.print("."); // Print dots while waiting for WiFi
}
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
LCD.clear();
LCD.setCursor(0, 0);
LCD.println("Online");
LCD.setCursor(0, 1);
LCD.println("Updating time...");
connected = 1;
configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);
vTaskDelay(5000); // Wait for 5 seconds before attempting to get time
struct tm timeinfo;
if (getLocalTime(&timeinfo))
{
Serial.println("Time synchronized!");
}
else
{
Serial.println("Failed to get time");
}
xSemaphoreGive(xSerialSem);
}
}
vTaskDelay(1000);
}
}
void Task5code(void *pvParameters)
{
Serial.print("Task5 running on core ");
Serial.println(xPortGetCoreID());
for (;;)
{
if (xSemaphoreTake(xSerialSem2, (TickType_t)10) == pdTRUE)
{
struct tm timeinfo;
if (getLocalTime(&timeinfo))
{
char buffer[50]; // Buffer for storing formatted time
char *formato = "%Y-%m-%d %H:%M:%S";
strftime(buffer, sizeof(buffer), formato, &timeinfo);
Serial.println(buffer);
}
Serial.println("Imprimindo e limpando a fila:");
while (uxQueueMessagesWaiting(xFila) > 0)
{
String mensagem;
if (xQueueReceive(xFila, &mensagem, portMAX_DELAY) == pdPASS)
{
Serial.print(mensagem);
Serial.print("|");
}
}
Serial.println("Fila limpa!");
xSemaphoreGive(xSerialSem2);
}
vTaskDelay(15000);
}
}
void loop()
{
}
void spinner()
{
static int8_t counter = 0;
const char *glyphs = "\xa1\xa5\xdb";
LCD.setCursor(15, 1);
LCD.print(glyphs[counter++]);
if (counter == strlen(glyphs))
{
counter = 0;
}
}
void printLocalTime()
{
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
LCD.setCursor(0, 1);
LCD.println("Connection Err");
connected = 0;
return;
}
LCD.setCursor(8, 0);
LCD.println(&timeinfo, "%H:%M:%S");
tone(SPEAKER_PIN, NOTE_G5);
vTaskDelay(10);
noTone(SPEAKER_PIN);
LCD.setCursor(0, 1);
LCD.println(&timeinfo, "%d/%m/%Y %Z");
}