//=== Chayla Grempel ====
// Module #5 project
#include <WiFi.h>// Wifi header
#include <PubSubClient.h>// MQTT publish and subscribe header file
#include <Wire.h>// I2C header file
#include <LiquidCrystal_I2C.h>// I2C Icd header file
const char* ssid = "Wokwi-GUEST";
const char* password = "";// This is the password to the SSID. For the smart mini router
const char* mqttServer = "test.mosquitto.org";
int port = 1883;
String stMac;
char mac[50];
char clientId[50];
//For our test.mosquitto.org broker, we just generate user client ID
WiFiClient espClient;
PubSubClient client(espClient);
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int redLightNorthSouth = 18;
const int yellowLightNorthSouth = 19;
const int greenLightNorthSouth = 23;
const int redLightEastWest = 16;
const int yellowLightEastWest = 17;
const int greenLightEastWest = 5;
int crossWalkButtonState = 1;
const int crossWalkButton = 4;
const int emergencyBlueLED = 2;
const int buzzerPin = 15;
int loopcount;
int secondsLeft;
int iotControl = 0;
//traffic controller
void setup() {
Serial.begin(115200);
randomSeed(analogRead(35));
delay(10);
Serial.println();
Serial.println("Connecting to");
Serial.println(ssid);
wifiConnect();
Serial.println("");
Serial.println("WiFi Connected");
Serial.println("IP address");
Serial.println(WiFi.localIP());
Serial.println(WiFi.macAddress());
stMac = WiFi.macAddress();
stMac.replace(":", "_");
Serial.println(stMac);
client.setServer(mqttServer, port);
client.setCallback(callback);
pinMode(crossWalkButton, INPUT_PULLUP);
attachInterrupt(crossWalkButton, buttonPressed, FALLING);
//interrupts on falling edges
pinMode(redLightNorthSouth, OUTPUT);
pinMode(yellowLightNorthSouth, OUTPUT);
pinMode(greenLightNorthSouth, OUTPUT);
pinMode(redLightEastWest, OUTPUT);
pinMode(yellowLightEastWest, OUTPUT);
pinMode(greenLightEastWest, OUTPUT);
pinMode(emergencyBlueLED, OUTPUT);
pinMode(buzzerPin, OUTPUT);
tone(buzzerPin, 0);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("===CEIS-114===");
}
void wifiConnect() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
void mqttReconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
long r = random(1000);
sprintf(clientId, "clientId-%Id", r);
if (client.connect(clientId)) {
Serial.print(clientId);
Serial.println("connected");
client.subscribe("LED");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println("try again in 5 seconds");
delay(5000);
}
}
}
void callback(char*topic, byte* message, unsigned int length) {
String stMessage;
for (int i = 0; i < length; i++) {
stMessage += (char)message[i];
}
if (String(topic) == "LED") {
if (stMessage == "ON") {
iotControl = 1;
}
else if (stMessage == "OFF") {
iotControl = 0;
}
}
}
void loop() {
if (!client.connected()) {
mqttReconnect();
}
while (iotControl == 0) {
lcd.setCursor(0, 1);
lcd.print("=Do Not Walk=");
Serial.println("==Do Not Walk==");
digitalWrite(emergencyBlueLED, LOW);
if (crossWalkButtonState == 0) {}
digitalWrite(yellowLightNorthSouth, LOW);
digitalWrite(greenLightNorthSouth, LOW);
digitalWrite(yellowLightEastWest, LOW);
digitalWrite(greenLightEastWest, LOW);
lcd.setCursor(0, 1);
lcd.print("==Walk!==");
secondsLeft = 15;
}
while (secondsLeft >= 10) {
if (secondsLeft >= 10) {
Serial.print("==Walk==");
Serial.println(secondsLeft);
lcd.setCursor(14, 1);
lcd.print(secondsLeft);
}
else {
Serial.print(" == Walk == "); // If timer has a single digit. Line up the numbers
Serial.println(secondsLeft); // Display the timer value
lcd.setCursor(14, 1); // set the cursor to column 15, line 2
lcd.print(" "); // clear anything on the last 2 columns
lcd.setCursor(15, 1); // set the cursor to column 15, line 2
lcd.print(secondsLeft); // display number of seconds left
}
digitalWrite(redLightNorthSouth, HIGH); // This should turn on the RED LED NS
digitalWrite(redLightEastWest, HIGH); // This should turn on the RED Yellow LED NS
tone(buzzerPin, 200);
delay(500); // wait 0.5 seconds
digitalWrite(redLightNorthSouth, LOW); // This should turn off the Red LED NS
digitalWrite(redLightEastWest, LOW); // This should turn off the Red LED EW
tone(buzzerPin, 250);
delay(500); // wait 0.5 seconds
secondsLeft -= 1; // Decrement timer count by one second
client.loop(); // Check if new MQTT messages have been published
if ( iotControl == 1) { // If iotControl variable is high.
break; // Break out of the while() loop
}
//} // end of while() loop
//} // end of if statement
else {
crossWalkButtonState = 1 ; // Set the crosswalk variable high. This should get us out of the cross
// walk routine
// The next three lines of code turn on the red LED NS
digitalWrite(redLightNorthSouth, HIGH); // This should turn on the Red LED NS
digitalWrite(yellowLightNorthSouth, LOW); // This should turn off the Yellow LED NS
digitalWrite(greenLightNorthSouth, LOW); // This should turn off the Green LED NS
digitalWrite(redLightEastWest, HIGH); // This should turn on the Red LED EW
digitalWrite(yellowLightEastWest, LOW); // This should turn off the Yellow LED EW
digitalWrite(greenLightEastWest, LOW); // This should turn off the Green LED EW
client.loop(); // Check if new MQTT messages have been published
delay(1000);
if ( iotControl == 1) { // If iotControl variable is high.
break; // Break out of the while() loop
}
// The next three lines of code turn on the red Yellow LED NS
digitalWrite(redLightEastWest, LOW); // This should turn off the Red LED EW
digitalWrite(yellowLightEastWest, LOW); // This should turn off the Yellow LED EW
digitalWrite(greenLightEastWest, HIGH); // This should turn on the Green LED EW
delay(2000); // wait for 2 seconds
// The next three lines of client.loop(); // Check if new MQTT messages have been published
if ( iotControl == 1) { // If iotControl variable is high.
break; // Break out of the while() loop
}
// code to turn on the red LED NS
digitalWrite(redLightNorthSouth, HIGH); // This should turn on the Red LED NS
digitalWrite(yellowLightNorthSouth, LOW); // This should turn off the Yellow LED NS
digitalWrite(greenLightNorthSouth, LOW); // This should turn off the Green LED NS
// The next three lines of code turn on the red Yellow LED NS
digitalWrite(redLightEastWest, LOW); // This should turn off the Red LED EW
digitalWrite(yellowLightEastWest, HIGH); // This should turn on the Yellow LED EW
digitalWrite(greenLightEastWest, LOW); // This should turn off the Green LED EW
delay(2000); // wait for 2 seconds
client.loop(); // Check if new MQTT messages have been published
if ( iotControl == 1) { // If iotControl variable is high.
break; // Break out of the while() loop
}
// The next three lines of code turn on the red Yellow LED NS
digitalWrite(redLightEastWest, HIGH); // This should turn on the Red LED NS
digitalWrite(yellowLightEastWest, LOW); // This should turn off the Yellow LED NS
digitalWrite(greenLightEastWest, LOW); // This should turn off the Green LED NS
delay(1000); //Extended time for Red light#2 before the Green of the other side turns ON
client.loop(); // Check if new MQTT messages have been published
if ( iotControl == 1) { // If iotControl variable is high.
break; // Break out of the while() loop
}
// The next three lines of code turn on the yellow LED NS
digitalWrite(redLightNorthSouth, LOW); //This should turn off the Red LED NS
digitalWrite(yellowLightNorthSouth, LOW); // This should turn off the Yellow LED NS
digitalWrite(greenLightNorthSouth, HIGH); // This should turn on the Green LED NS
delay(2000); // wait for 2 seconds
client.loop(); // Check if new MQTT messages have been published
if ( iotControl == 1) { // If iotControl variable is high.
break; // Break out of the while() loop
}
// The next three lines of code turn on the yellow LED NS
digitalWrite(redLightNorthSouth, LOW); // This should turn off the Red LED NS
digitalWrite(yellowLightNorthSouth, HIGH); // This should turn on the Yellow LED NS
digitalWrite(greenLightNorthSouth, LOW); // This should turn off the Green LED NS
// The next three lines of code turn on the red Yellow LED NS
digitalWrite(redLightEastWest, HIGH); // This should turn on the Red LED EW
digitalWrite(yellowLightEastWest, LOW); // This should turn off the Yellow LED EW
digitalWrite(greenLightEastWest, LOW); // This should turn off the Green LED EW
delay(2000); // wait for 2 seconds
client.loop(); // Check if new MQTT messages have been published
if ( iotControl == 1) { // If iotControl variable is high.
break; // Break out of the while() loop
}
}
} // end of while() loop
while ( iotControl == 1) {
lcd.setCursor(0, 1); // set the cursor to column 1, line 2
lcd.println("= Emergency! =");
Serial.println("= Emergency! =");
digitalWrite(yellowLightNorthSouth, LOW); // This should turn off the Yellow LED NS
digitalWrite(greenLightNorthSouth, LOW); // This should turn off the Green LED NS
digitalWrite(yellowLightEastWest, LOW); // This should turn off the Yellow LED EW
digitalWrite(greenLightEastWest, LOW); // This should turn off the Yellow LED EW
digitalWrite(redLightNorthSouth, HIGH); // This should turn on the RED LED NS
digitalWrite(redLightEastWest, HIGH); // This should turn on the RED Yellow LED NS
digitalWrite(emergencyBlueLED, HIGH); // This should turn on the Remergency blue LED
tone(buzzerPin, 200); // This should turn on the active buzzer
delay(500);
digitalWrite(emergencyBlueLED, LOW); // This should turn off the Remergency blue LED
tone(buzzerPin, 0); // This should turn off the active buzzer
delay(500);
client.loop();
client.loop(); // Check if new MQTT messages have been published
if ( iotControl == 1)
{ // If iotControl variable is high.
break; // Break out of the while() loop
}
}
client.loop(); // Check if new MQTT messages have been published one last time
}
void buttonPressed() // Function to handle any cross walk button presses
{
static unsigned long lastInterruptTime = 0; // Create variable for holding interrupt time
unsigned long interruptTime = millis(); // Store current time in milli-seconds
// If interrupts come faster than 200ms, assume it's a bounce and ignore
if (interruptTime - lastInterruptTime > 20)
{
crossWalkButtonState = 0; // Change the value of the variable that holds the state of the button
}
lastInterruptTime = interruptTime; // Save the timer
}