Saturday, October 9, 2021

0000 0000 0111 0110

ESP32 Traffic Light Changer

I spent quite a few happy hours fiddling around with traffic light changers after my last blog and video which used the PFS154 and a button to make the changes. The crazy part is that there is not one single traffic light on my 35 minute commute to work - so...huh?

Anyway, first I looked at an interrupt driven change on the ATTiny13 version, then a simple loop driven change for an ESP32

BTW, there are so many incarnations of the ESP32 that the list covers several pages on my Arduino-IDE.

After choosing the appropriate variant in the IDE I coded the following three versions:

1. Button press activated

2. WiFi activated

3. Bluetooth activated

Button Press:

int red = 13;
int yellow = 12;
int green = 14;
int button = 23;
int buttonValue = 0;

void setup(){
pinMode(button,INPUT);
pinMode(red,OUTPUT);
pinMode(yellow,OUTPUT);
pinMode(green,OUTPUT);
pinMode(button,INPUT);
digitalWrite(red,HIGH);
}

void loop(){
buttonValue = digitalRead(button);
if (buttonValue == HIGH){
changeLights();
    delay(4000);
    digitalWrite(green, LOW);
    digitalWrite(yellow, HIGH);
    delay(1000);
    digitalWrite(yellow, LOW);
    digitalWrite(red, HIGH);
    delay(2000);
    buttonValue = LOW;
}
}
void changeLights(){
  // red off, yellow for 1 seconds
  digitalWrite(red, LOW);
  digitalWrite(yellow, HIGH);
  delay(1000);

  // turn off yellow, then turn green on
  digitalWrite(yellow, LOW);
  digitalWrite(green, HIGH);
}

Wifi:

#include "WiFi.h"

int red = 13;
int yellow = 12;
int green = 14;

// Replace with your network credentials
const char* ssid = "**********";
const char* password = "**********";

WiFiServer server(80);
String header;
String buttonState = "red";

unsigned long currentTime = millis();
unsigned long previousTime = 0;
const long timeoutTime = 2000;

void setup() {
  pinMode(red, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(green, OUTPUT);
  digitalWrite(red, HIGH);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  Serial.begin(115200);
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void changeLights() {
  digitalWrite(red, LOW);
  digitalWrite(yellow, HIGH);
  delay(1000);

  digitalWrite(yellow, LOW);
  digitalWrite(green, HIGH);
  delay(4000);

  digitalWrite(green, LOW);
  digitalWrite(yellow, HIGH);
  delay(1000);

  digitalWrite(yellow, LOW);
  digitalWrite(red, HIGH);
  delay(2000);

}

void loop() {
  WiFiClient client = server.available();

  if (client) {
    currentTime = millis();
    previousTime = currentTime;
    String currentLine = "";
    while (client.connected() && currentTime - previousTime <= timeoutTime) {
      currentTime = millis();
      if (client.available()) {
        char c = client.read();
        header += c;
        if (c == '\n') {
          if (currentLine.length() == 0) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            if (header.indexOf("GET /26/green") >= 0) {
              buttonState = "green";
            } else if (header.indexOf("GET /26/red") >= 0) {
              buttonState = "red";
              changeLights();
            }

            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            client.println("<body><h1>Traffic Light Changer</h1>");

            if (buttonState == "red") {
              client.println("<p><a href=\"/26/red\"><button class=\"button\">GREEN</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/green\"><button class=\"button button2\">RED</button></a></p>");
            }

            client.println("</body></html>");

            client.println();
            break;
          } else {
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
      }
    }
    header = "";
    client.stop();
  }
}

Bluetooth (on the C3 version - BLE):

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
float txValue = 0;

// the following are the RGB leds for the C3
const byte red = 3;
const byte green = 4;
const byte blue = 5;


#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

void changeLights() {
  digitalWrite(red, HIGH);
  digitalWrite(green, HIGH);
  digitalWrite(blue, LOW);
  delay(2000);

  digitalWrite(red, LOW);
  digitalWrite(green, HIGH);
  digitalWrite(blue, LOW);
  delay(4000);

  digitalWrite(red, HIGH);
  digitalWrite(green, HIGH);
  digitalWrite(blue, LOW);
  delay(2000);

  digitalWrite(red, HIGH);
  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);

}
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {


        for (int i = 0; i < rxValue.length(); i++) {
        } 
        if (rxValue.find("G") != -1) {
          changeLights();
        }
      }
    }
};

void setup() {
  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);

  digitalWrite(red, HIGH);
  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);
  BLEDevice::init("Traffic Light Changer");
  BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_TX,
                      BLECharacteristic::PROPERTY_NOTIFY
                    );

  pCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
  pServer->getAdvertising()->start();
}

void loop() {
  if (deviceConnected) {
  }
  delay(1000);
}

Given the distinct dearth of traffic lights in Tasmania, I'm not sure how directly useful any of these devices will be in shortening my daily commute, but I can say that it opens up some possibilities for monitoring sensors and activating motors/pumps, etc, around the property. So perhaps overall it was a useful exercise!?

I also "enjoyed" the wrestle with the C3-BLE version of the ESP32, which I think may be very interesting to play with in the future.




No comments:

Post a Comment