Grove Traffic Light

by aflame143 in Circuits > Electronics

235 Views, 1 Favorites, 0 Comments

Grove Traffic Light

IMG_0344.jpg

This instructable is catered towards creating a simple traffic light! This will utilize The WIO Terminal as the main platform, the Grove Ultrasonic Ranger, the PIR Mini Motion Sensor, the built in TFT Display, and the built in Light Sensor!

When you are driving traffic lights change color based on whether or not they detect a vehicle. One signal might be red but as soon as a vehicle pulls up to that light and motion is detected a countdown begins. Once that countdown is complete the light on the other side turns yellow, and then red respectively and turns the light that is currently red to green. This instructable will mimic this functionality partially along with adding on light sensing as another trigger!

By the end of this instructable you will have a simple project that mimics the way that an everyday traffic light functions!

Supplies

To create this you will need the following supplies!

Wio Terminal:

https://www.seeedstudio.com/Wio-Terminal-p-4509.ht...

TFT Display:

This is already built into the WIO Terminal

Light Sensor:

This is already built into the WIO Terminal

Ultrasonic Ranger:

https://www.seeedstudio.com/Grove-Ultrasonic-Dista...

Mini PIR Motion Sensor:

https://www.seeedstudio.com/Grove-mini-PIR-motion-...

Setting Up the Terminal

IMG_0340.jpg

In this Step we will be getting our Wio Terminal Setup.

To start, unpack (if you haven't already) your WIO Terminal and use the provided USB A to USB C cable to plug it into your computer!

Tip* The USB C cable is necessary to power and transfer data to or from the terminal, none of this is doable without it!

To make sure we are connected properly on the left side of the terminal there is a slider, push down on that to turn the terminal on. You will know the terminal is on via the blue and green lights that show up on the bottom next where our cable is plugged in.

Adding on the External Sensors

IMG_0342.jpg
IMG_0341.jpg
IMG_0343.jpg

In this Step we will be connecting our external sensors to the Wio Terminal.

Images of these sensors are shown above.

To start we will be connecting the Ultrasonic Ranger to the port that is to the right of where our USB C cable is plugged in. Make sure the other end is connected to the port that is on the module itself as well.

Next we will be connecting the Motion Sensor to the port that is on the left of the USB C power cable. Once again make sure the other end is connected to the port that is on the module.

With this done both of our external sensors are now connected to our Wio Terminal.

The Code

In this step we will go through the code in detail. Attached will be code blocks along with annotations to let you know what purpose each block of code serves!

To Start We will need our Imports and Definitions! We will need to include our Ultrasonic Ranger Library and TFT Library!

//including ultrasonic ranger
#include <Ultrasonic.h>
//including built in tft display
#include <TFT_eSPI.h>

//define pin for PIR motion sensor
#define PIR PIN_WIRE_SCL

Ultrasonic ultrasonic(0);
TFT_eSPI tft; //LCD
TFT_eSprite spr = TFT_eSprite(&tft);
<br>

Next we will be setting up our Pins (so we are able to transfer data from our sensors to our Wio Terminal), our Serial Monitor (will allow us to monitor our program to make sure all of the correct values are being read), and our Display!

void setup() {
    Serial.begin(115200);
    pinMode(PIR, INPUT);
    tft.begin();
    tft.setRotation(3);
    pinMode(WIO_LIGHT,INPUT);
    digitalWrite(LCD_BACKLIGHT,LOW);

}//setup<br>

Next there are a couple of values that we will need to make the traffic light work. First we will need a lightvalue to monitor whether light is being detected which will serve as one of the triggers for the traffic light. Second we will need a value for inches and centimeters (for those metric folks out there), which will be used to calculate the distance from the motion sensor and a potential vehicle!

void loop() {

  //numeric values
  int lightvalue = analogRead(WIO_LIGHT);
  long RangeInInches;
  long RangeInCentimeters;<br>

After this we will need to calculate the actual values and print some of this information to our Serial Monitor for troubleshooting purposes!

//Measuring distance in inches
  Serial.println("The nearest obstacle is: ");
  ultrasonic.MeasureInInches();
  Serial.print(ultrasonic.RangeInInches); //0 - 157 inches
  Serial.println(" inch(es) away!");

  delay(250);

  //Measuring distance in centimeters
  Serial.println("The nearest obstacle is: ");
  ultrasonic.MeasureInCentimeters();
  Serial.print(ultrasonic.RangeInCentimeters); //0 - 400 cm
  Serial.println(" cm away!");
  delay(1250);
  <br>

In this next step we will be writing the code for our motion sensor, this serves as our second trigger for changing the color of the traffic light!

    if (digitalRead(PIR)){
    //detected Motion
    Serial.println("Motion has been Detected! Activating Traffic Light.");
    delay(1250);
    }
    else{
      Serial.println("No Motion Detected Yet!");
      delay(2000);
      }<br>

In this next step we will be creating an if condition, to see if light is detected or not. While in an actual traffic light we would never want it to be off, for this case we will have the screen be off until light and motion are detected, we could look at it as a way of saving power.

    if (lightvalue < 200){
    Serial.println("High Amount of Light Detected Increasing Traffic Light Brightness!");
}

In this next step we will be calculating if a vehicle has been detected within a specific range of the traffic light in this case it will be 40 inches. Once we have detected that we will be turning the light from green, to yellow and then red after a short 5 second delay. Our light will continue to stay at red until 10 seconds has passed at which point we turn it back to green. We will also be writing the actual color onto the screen for accessibility.

    if (lightvalue < 200){
      Serial.println("High Amount of Light Detected Increasing Traffic Light Brightness!");
      if (ultrasonic.RangeInInches < 40){
        digitalWrite(LCD_BACKLIGHT,HIGH);
        tft.fillScreen(TFT_YELLOW);
        tft.setTextColor(TFT_BLACK);
        tft.setTextSize(3); //1 to 7
        tft.drawString("Yellow",110,120);
        delay(5000);
        tft.fillScreen(TFT_RED);
        tft.setTextColor(TFT_BLACK);
        tft.setTextSize(3); //1 to 7
        tft.drawString("Red",110,120);
        delay(10000);
        }
          else {
            tft.fillScreen(TFT_GREEN);
            tft.setTextColor(TFT_BLACK);
            tft.setTextSize(3); //1 to 7
            tft.drawString("Green",110,120);
            }
            
    } // if lightvalue
<br>

In our final step we will be creating an else condition that keeps the traffic light off if there is no motion and light detected.

    //turn off screen when there is no motion or light detected to save power
    else {
      if (ultrasonic.RangeInInches < 40){
        digitalWrite(LCD_BACKLIGHT,LOW);
        tft.fillScreen(TFT_YELLOW);
        delay(5000);
        tft.fillScreen(TFT_RED);
        delay(10000);
        }
          else {
            tft.fillScreen(TFT_GREEN);
            }
      }<br>

With this our code is now completed! Below is the full version of the code without annotations in between for cross reference!

//including ultrasonic ranger
#include <Ultrasonic.h>
//including built in tft display
#include <TFT_eSPI.h>

//define pin for PIR motion sensor
#define PIR PIN_WIRE_SCL

Ultrasonic ultrasonic(0);
TFT_eSPI tft; //LCD
TFT_eSprite spr = TFT_eSprite(&tft);

void setup() {
    Serial.begin(115200);
    pinMode(PIR, INPUT);
    tft.begin();
    tft.setRotation(3);
    pinMode(WIO_LIGHT,INPUT);
    digitalWrite(LCD_BACKLIGHT,LOW);

}//setup

void loop() {

  //numeric values
  int lightvalue = analogRead(WIO_LIGHT);
  long RangeInInches;
  long RangeInCentimeters;

  //Measuring distance in inches
  Serial.println("The nearest obstacle is: ");
  ultrasonic.MeasureInInches();
  Serial.print(ultrasonic.RangeInInches); //0 - 157 inches
  Serial.println(" inch(es) away!");

  delay(250);

  //Measuring distance in centimeters
  Serial.println("The nearest obstacle is: ");
  ultrasonic.MeasureInCentimeters();
  Serial.print(ultrasonic.RangeInCentimeters); //0 - 400 cm
  Serial.println(" cm away!");
  delay(1250);
  
    if (digitalRead(PIR)){
    //detected Motion
    Serial.println("Motion has been Detected! Activating Traffic Light.");
    delay(1250);
    }
    else{
      Serial.println("No Motion Detected Yet!");
      delay(2000);
      }
    if (lightvalue < 200){
      Serial.println("High Amount of Light Detected Increasing Traffic Light Brightness!");
      if (ultrasonic.RangeInInches < 40){
        digitalWrite(LCD_BACKLIGHT,HIGH);
        tft.fillScreen(TFT_YELLOW);
        tft.setTextColor(TFT_BLACK);
        tft.setTextSize(3); //1 to 7
        tft.drawString("Yellow",110,120);
        delay(5000);
        tft.fillScreen(TFT_RED);
        tft.setTextColor(TFT_BLACK);
        tft.setTextSize(3); //1 to 7
        tft.drawString("Red",110,120);
        delay(10000);
        }
          else {
            tft.fillScreen(TFT_GREEN);
            tft.setTextColor(TFT_BLACK);
            tft.setTextSize(3); //1 to 7
            tft.drawString("Green",110,120);
            }
            
    } // if lightvalue

    //turn off screen when there is no motion or light detected to save power
    else {
      if (ultrasonic.RangeInInches < 40){
        digitalWrite(LCD_BACKLIGHT,LOW);
        tft.fillScreen(TFT_YELLOW);
        delay(5000);
        tft.fillScreen(TFT_RED);
        delay(10000);
        }
          else {
            tft.fillScreen(TFT_GREEN);
            }
      }
} //loop

Video Tutorial

Below is a link to a video tutorial, the video is unlisted so if you want to share it please feel free to send the link to anyone you want!

https://youtu.be/mHnl1i36D2I