#define BLYNK_TEMPLATE_ID "TMPL32wGxn7EA"
#define BLYNK_TEMPLATE_NAME "Smart Soil Nutrition Monitoring System for Sustain"
#define BLYNK_AUTH_TOKEN "Your Auth Token"
// Comment this out to disable prints and save space
#define BLYNK_PRINT Serial
// Header files
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
// Virtual Pin Declarations
#define V0 0
#define V1 1
#define V3 3
#define V4 4
// Widget-Datastream Mapping
WidgetLED led_V3(V3);
WidgetLED led_V4(V4);
// Function prototypes
void Print_to_console(const char* text);
void Non_Active_lane(const int* LanePins);
void Next_Active_lane(const int* LanePins);
void TrafficController(int trafficCount, const int* LanePins);
// Pins connected to the potentiometer
const int Lane_A_Traffic = 34;
const int Lane_B_Traffic = 35;
// Your WiFi credentials. Set password to "" for open networks.
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
/*
The traffic array contains pins which are the pins of corresponding traffic lights
it contains three lights in the below format
Lane_X_Pins[]= {Red , Yellow, Green}
Used for easy accessing of corresponding traffic lights
*/
const int Lane_A_Pins[] = {0, 2, 15};
const int Lane_B_Pins[] = {17, 16, 4};
// Index variable that refers to the color of the traffic light
const int Red = 0, Yellow = 1, Green = 2;
// ThreshHolds
const int Quater_Traffic_ThreshHold = 3071;
const int Full_Traffic_ThreshHold = 4095;
// Lane Flags
bool Lane_A_flag = true, Lane_B_flag = false;
// temporary stores console msg to avoid format problems
// used for formatting string and storing it
// snprintf(Variable_for_string, Ammount-of-buffer-that-string-can-hold,"String",format_var);
char consoleMessageTemp[256];
// Alert mesg flag
bool Alter_Flag = true;
// Lanes which are available (Free lanes)
char Lanes_Available_Queue[3]={'A','B'};
void setup() {
Serial.begin(115200); // Initialize serial communication
// Set the resolution for analog reading to 12 bits (range: 0-4095)
analogReadResolution(12);
// Set potentiometer pin as input
pinMode(Lane_A_Traffic, INPUT);
pinMode(Lane_B_Traffic, INPUT);
// Set traffic light pins as output
for(int i = 0; i < 3; i++){
pinMode(Lane_A_Pins[i], OUTPUT); // Lane A pins
pinMode(Lane_B_Pins[i], OUTPUT); // Lane B pins
}
// Connect to the Blynk server
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
Print_to_console("Traffic Management System\n"
"Initialized Traffic Lanes");
Print_to_console("Traffic Status on Lanes\n"
"L-1: No Traffic L-2: No Traffic");
//Assigning that all lanes are available
Blynk.virtualWrite(V3, "L-A:Available____L-B:Available");
Blynk.virtualWrite(V4, "L-A:🟢 L-B:🟢");
}
void loop() {
Blynk.run(); // Allows Blynk to process incoming commands
// Clearing temp store console msg var after using it
if (sizeof(consoleMessageTemp) != 0)
memset(consoleMessageTemp, 0, sizeof(consoleMessageTemp));
// Read potentiometer value (simulated vehicle count)
int Lane_A_vehicle_count = analogRead(Lane_A_Traffic);
int Lane_B_vehicle_count = analogRead(Lane_B_Traffic);
// Send potentiometer (Lane's vehicle Count) value to Blynk
Blynk.virtualWrite(V0, Lane_A_vehicle_count);
Blynk.virtualWrite(V1, Lane_B_vehicle_count);
// Call TrafficController function with Lane's vehicle Count and Lane Pins
if (Lane_A_flag) {
if (Lane_A_vehicle_count < Quater_Traffic_ThreshHold) {
Non_Active_lane(Lane_B_Pins);
} else if (Lane_A_vehicle_count == Full_Traffic_ThreshHold) {
Lane_A_flag = false;
Lane_B_flag = true;
Next_Active_lane(Lane_B_Pins);
Alter_Flag = true;
if (Alter_Flag) {
snprintf(consoleMessageTemp, sizeof(consoleMessageTemp), "Traffic Management System\n"
"LANE A is blocked due to heavy traffic and the traffic is diverted to LANE B\n"
"Traffic Status on Lanes\n"
"L-1: Blocked L-2: %d", Lane_B_vehicle_count);
Print_to_console(consoleMessageTemp);
led_V3.off(); // L-A Available
led_V4.on(); // L-A Blocked, L-B Available
}
} else if (Lane_A_vehicle_count >= Quater_Traffic_ThreshHold) {
Next_Active_lane(Lane_B_Pins);
if (Alter_Flag) {
snprintf(consoleMessageTemp, sizeof(consoleMessageTemp), "Traffic Management System\n"
"LANE A traffic is about to be diverted to LANE B due to heavy traffic buildup\n"
"Traffic Status on Lanes\n"
"L-1: %d L-2: %d", Lane_A_vehicle_count, Lane_B_vehicle_count);
Print_to_console(consoleMessageTemp);
Alter_Flag = false;
}
}
TrafficController(Lane_A_vehicle_count, Lane_A_Pins);
}
if (Lane_B_flag) {
if (Lane_B_vehicle_count < Quater_Traffic_ThreshHold) {
Non_Active_lane(Lane_A_Pins);
} else if (Lane_B_vehicle_count == Full_Traffic_ThreshHold) {
Lane_B_flag = false;
Alter_Flag = true;
if (Alter_Flag) {
snprintf(consoleMessageTemp, sizeof(consoleMessageTemp), "Traffic Management System\n"
"LANE B is blocked due to heavy traffic\n"
"Traffic Status on Lanes\n"
"L-1: Blocked L-2: Blocked");
Print_to_console(consoleMessageTemp);
Alter_Flag = false;
led_V3.on(); // L-A Blocked, L-B Blocked
led_V4.on(); // L-A Blocked, L-B Blocked
}
} else if (Lane_B_vehicle_count >= Quater_Traffic_ThreshHold) {
Next_Active_lane(Lane_A_Pins);
if (Alter_Flag) {
snprintf(consoleMessageTemp, sizeof(consoleMessageTemp), "Traffic Management System\n"
"LANE B traffic is about to be blocked due to heavy traffic buildup\n"
"Traffic Status on Lanes\n"
"L-1: Blocked L-2: %d", Lane_B_vehicle_count);
Print_to_console(consoleMessageTemp);
Alter_Flag = false;
}
}
TrafficController(Lane_B_vehicle_count, Lane_B_Pins);
}
// Alert message when all lanes are blocked due to heavy traffic
if (!Lane_A_flag && !Lane_B_flag) {
snprintf(consoleMessageTemp, sizeof(consoleMessageTemp), "Traffic Management System\n"
"All lanes are blocked.\n"
"Traffic Status on Lanes\n"
"L-1: Blocked L-2: Blocked");
Print_to_console(consoleMessageTemp);
}
}
/*
Lights Controling functions
*/
// Active lane control function
void TrafficController(int trafficCount, const int* LanePins) {
if (trafficCount >= Quater_Traffic_ThreshHold && trafficCount < Full_Traffic_ThreshHold) {
// Traffic is at quarter threshold, turn on the yellow light
digitalWrite(LanePins[Red], LOW);
digitalWrite(LanePins[Yellow], HIGH);
digitalWrite(LanePins[Green], HIGH);
}
// Check if traffic is at full threshold
else if (trafficCount >= Full_Traffic_ThreshHold) {
// Traffic is at full threshold, turn on the red light
digitalWrite(LanePins[Red], HIGH);
digitalWrite(LanePins[Yellow], LOW);
digitalWrite(LanePins[Green], LOW);
}
else {
// Traffic is below quarter threshold, turn on the green light
digitalWrite(LanePins[Red], LOW);
digitalWrite(LanePins[Yellow], LOW);
digitalWrite(LanePins[Green], HIGH);
}
}
// Initiallizing initial non active lanes
void Non_Active_lane(const int* LanePins){
digitalWrite(LanePins[Red], HIGH);
digitalWrite(LanePins[Yellow], LOW);
digitalWrite(LanePins[Green], LOW);
}
// Function for activating next lane
void Next_Active_lane(const int* LanePins){
digitalWrite(LanePins[Red], HIGH);
digitalWrite(LanePins[Yellow], HIGH);
digitalWrite(LanePins[Green], LOW);
}
// Function for printing alert msg on console
void Print_to_console(const char* text) {
int textLength = strlen(text);
int borderLength = textLength + 4;
// Print the top border
for (int i = 0; i < borderLength; i++) {
Serial.print("*");
}
Serial.println();
// Print the text with border
Serial.print("* ");
Serial.print(text);
Serial.println(" *");
// Print the bottom border
for (int i = 0; i < borderLength; i++) {
Serial.print("*");
}
Serial.println();
}