/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
/* Fill-in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID "TMPLoSqj_vws"
#define BLYNK_TEMPLATE_NAME "Quickstart Template"
#define BLYNK_AUTH_TOKEN "KnVeXgWsPFSFbEnuGHbLS4f4QbPSgZ55"
/*
the project as a whole is going to have a LCD display displaying the speed of the fan and the current time of the day,
a psuhbutton to manually control the power of the fan(ON/OFF), as well as a potentiometer to control
the speed of the fan<-- these components will all be on a breadboard. Inside the BLYNK app, you will also be
able to see the speed of the fan, control the fan speed, and lastly if the fan goes over a certain voltage the
fan will turn off and will have to be manually turned on again as a safety feature.
*/
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Library for LCD
#include <OneWire.h>
#include <DallasTemperature.h> // Library for DS18B20 Temperature Sensor
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Blynk virtual pin assignments
#define VIRTUAL_SPEED_PIN V3
#define VIRTUAL_TEMP_PIN V4
#define VIRTUAL_TIME_PIN V1
#define VIRTUAL_DATE_PIN V2
// LCD configuration
#define LCD_ADDRESS 0x27
#define LCD_COLUMNS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
// Push button pin
#define BUTTON_ON_PIN 2
#define BUTTON_MODE_PIN 15
// Fan Motor -> L298N Motor Driver
int motor1Pin1 = 27;
int motor1Pin2 = 26;
int enable1Pin = 14;
int POTENTIOMETER_PIN = 34; // Potentiometer pin
// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
// Setting PWM properties
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 200;
// Fan control pin
#define FAN_PIN 13
// Fan speed variables
int fanSpeed = 0;
int maxVoltage = 4096; // Maximum reading from the potentiometer
int minTemperature = 20; // Minimum temeprature value
int maxTemperature = 40;
BlynkTimer timer;
WidgetRTC rtc;
bool manualMode = true; // Intially set auto mode
bool fanOnFlag = false; // Initially turn off fan
unsigned long lastManualCheckTime = millis(); // note current time
// Digital clock display of the time
void clockDisplay() {
// You can call hour(), minute(), ... at any time
// Please see Time library examples for details
String currentTime = String(hour()) + ":" + minute() + ":" + second();
String currentTimeDisp = String(hour()) + ":" + minute();
String currentDate = String(day()) + " " + month() + " " + year();
// Serial.print("Current time: ");
// Serial.print(currentTime);
// Serial.print(" ");
// Serial.print(currentDate);
// Serial.println();
lcd.setCursor(0, 0); // Set lcd cursor on this position for time
lcd.print(currentTime); // display time on lcd
lcd.print(" ");
// Send time to the App
Blynk.virtualWrite(VIRTUAL_TIME_PIN, currentTime);
// Send date to the App
Blynk.virtualWrite(VIRTUAL_DATE_PIN, currentDate);
}
BLYNK_CONNECTED() {
// Synchronize time on connection
rtc.begin();
}
void setup() {
// Debug console
Serial.begin(115200);
lcd.init(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
lcd.print("Starting");
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// You can also specify server:
//Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, "blynk.cloud", 80);
//Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass, IPAddress(192,168,1,100), 8080);
// Other Time library functions can be used, like:
// timeStatus(), setSyncInterval(interval)...
// Read more: http://www.pjrc.com/teensy/td_libs_Time.html
// Initialize push button
pinMode(BUTTON_ON_PIN, INPUT_PULLUP);
pinMode(BUTTON_MODE_PIN, INPUT_PULLUP);
// Initialize potentiometer
pinMode(POTENTIOMETER_PIN, INPUT);
// Initialize fan control pin
// sets the pins as outputs:
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(enable1Pin, OUTPUT);
// configure LED PWM functionalitites
ledcSetup(pwmChannel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(enable1Pin, pwmChannel);
// Start the DS18B20 sensor
sensors.begin();
setSyncInterval(10 * 60); // Sync interval in seconds (10 minutes)
lcd.clear(); // clear lcd
lcd.setCursor(9, 0);
lcd.print("Off");
lcd.setCursor(13, 1);
lcd.print("M"); // On display print M for manual mode
lcd.setCursor(12, 0);
lcd.print("0 % ");
// Display digital clock every 10 seconds
timer.setInterval(1000L, clockDisplay);
timer.setInterval(2100L, getTemperature);
}
void loop() {
Blynk.run();
timer.run();
if ((digitalRead(BUTTON_MODE_PIN) == LOW) && (manualMode == false)) {
manualMode = true; // start manual mode
lcd.setCursor(13, 1);
lcd.print("M"); // On display print M for manual mode
customDelay(100); // debounce time
} else if ((digitalRead(BUTTON_MODE_PIN) == LOW) && (manualMode == true)) {
manualMode = false; // stop manual mode
lcd.setCursor(13, 1);
lcd.print("A"); // On display print A for Auto mode
getTemperature(); // call temperature function
customDelay(100); // debounce time
}
if ((digitalRead(BUTTON_ON_PIN) == LOW) && (fanOnFlag == false)) {
fanOnFlag = true; // start Fan
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
lcd.setCursor(9, 0);
lcd.print("On");
lcd.print(" ");
customDelay(100); // debounce time
} else if ((digitalRead(BUTTON_ON_PIN) == LOW) && (fanOnFlag == true)) {
fanOnFlag = false; // stop fan
digitalWrite(motor1Pin1, LOW); // Turn off fan
digitalWrite(motor1Pin2, LOW);
ledcWrite(pwmChannel, 0);
Blynk.virtualWrite(VIRTUAL_SPEED_PIN, 0);
lcd.setCursor(9, 0);
lcd.print("Off");
customDelay(100); // debounce time
}
if ((manualMode == true) && ((millis() - lastManualCheckTime) > 1000) && (fanOnFlag)) {
// Read potentiometer value
int potValue = analogRead(POTENTIOMETER_PIN);
// Map potentiometer value to fan speed (0-255)
fanSpeed = map(potValue, 0, maxVoltage, 0, 255);
// Update LCD for fan speed
int perFanSpeed = map(fanSpeed, 0, 255, 0, 100); // map current pwm speed as percentage speed
// Update Blynk
Blynk.virtualWrite(VIRTUAL_SPEED_PIN, perFanSpeed);
// Control fan speed
lcd.setCursor(12, 0);
lcd.print(perFanSpeed);
lcd.print("% ");
ledcWrite(pwmChannel, fanSpeed); // change fan speed
lastManualCheckTime = millis(); // note current time
}
}
void customDelay(unsigned long waitTime) {
unsigned long cTime = millis();
while ((millis() - cTime) < waitTime) {
Blynk.run();
timer.run();
}
}
void getTemperature() {
sensors.requestTemperatures();
int temperatureC = sensors.getTempCByIndex(0);
float temperatureF = sensors.getTempFByIndex(0);
Serial.print(temperatureC);
Serial.println("ºC");
Serial.print(temperatureF);
Serial.println("ºF");
Blynk.virtualWrite(VIRTUAL_TEMP_PIN, temperatureC);
lcd.setCursor(0, 1); // set cursor on next line
lcd.print(temperatureC);
lcd.print(" *C ");
if ((manualMode == false) && (fanOnFlag == true)) {
// In case of manual mode set fan speed according to temperature
int fanSpeed = map(temperatureC, minTemperature, maxTemperature, 0, 255); // Map current temperature to min and max defined above
ledcWrite(pwmChannel, fanSpeed); // change fan speed
int perFanSpeed = map(fanSpeed, 0, 255, 0, 100); // map current pwm speed as percentage speed
// Update Blynk
Blynk.virtualWrite(VIRTUAL_SPEED_PIN, perFanSpeed);
lcd.setCursor(12, 0);
lcd.print(perFanSpeed);
lcd.print("% ");
}
}