Smart bus stop

A city bus stop with different sensors to help make the area safer and better for the environment.

projectImage

Things used in this project

 

Hardware components

HARDWARE LIST
1 DFRobot Gravity: Analog CH4 Gas Sensor (MQ4) For Arduino
1 DFRobot Carbon Monoxide Sensor (MQ7)
1 DFRobot Gravity: Analog Flame Sensor For Arduino
1 Seeed Studio Grove - Air quality sensor v1.3
1 SparkFun Atmospheric Sensor Breakout - BME280
1 Photodiode, 45 °
1 Adafruit NeoPixel Ring: WS2812 5050 RGB LED
1 Load Cell, Low Profile
1 SparkFun Ultrasonic Sensor - HC-SR04
1 Speaker: 0.25W, 8 ohms
1 SparkFun MP3 Player Shield
1 Axial Fan, 12 VDC
1 PIR Motion Sensor (generic)
1 DFRobot Gravity:Digital Push Button (Yellow)

Story

 

We were working on a smart bus stop, outfitted with many different sensors to help make public transportation safer in the community and for the environment. All together we have eight different sensors along with two neo pixel LEDs, a fan, and a button.

 

Every sensor is reading and collecting data. This data is being sent to Adafruit, where it’s being displayed and updated every 30 seconds. This is helpful to see what the air quality is like in specific areas if there are more bus stops like this. Speaking of the air quality, let’s look at the different sensors that are reading these levels.

 

There are 3 different sensors that are measuring the air quality, we have the air quality sensor that just reads the overall quality of the air. There is the Flying Fish MQ4 and MQ7 sensor. The MQ4 reads methane gases and the MQ7 reads CO2 gases. Paired with these sensors, we also have the BME280 sensor to read the temperature of the area and a fan. The fan will turn on once the temperature is above any value that we set and the air quality index is at an acceptable range. Which gives us the ability to have the fan on, but once the air quality goes above the air quality index, fan will turn off.

 

There is also a Neo Pixel light that is at the top of the bus stop with a photodiode that is mapped to the brightness of the lights. As it gets brighter outside, the lights will start to dim. Once the sun is setting and it gets darker, the lights will start to get brighter to keep the bus stop well lit. the lights are also working with an emergency button we have here. Once the button has been pressed the lights will turn red to indicate that the emergency button has been pressed. And once pressed, the speaker will let the individual who pressed the button, know that a uniformed officer will arrive to the location.

 

Next we have our smart trash can. There are two sensors built into the smart trash can, and one sensor above the trash can. The loadcell, at the bottom, to measure the weight, and the ultra-sonic sensor, at the top, to measure the distance. We want to measure the distance, so we know how close to the top the trash is getting. And we want to measure the weight because no one wants to take out a heavy trash bag. The ultra sonic sensor has been mapped to have an inverse value so it will make the graph easier to read and understand. Above the trash can is a fire sensor. Just as the name says it will detect a fire. Dealing with trash is already a messy business, but we also don’t want to deal with a garbage fire.

 

We also have a camera to show a live feed of the bus stop. This will give a better visual of what is going on at the bus stop. There is also a motion sensor that is included with the bus stop

Custom parts and enclosures

icon trashlid2_oOOanhkyH6.zip 121KB Download(0)

Schematics

icon bus_fritz_3_XraT5O9gsM.zip 213KB Download(0)
icon bus_fritz_3_tkGVs7R4UO.zip 285KB Download(0)

Code

CODE
#include "Adafruit_MQTT_SPARK.h"
#include "DFRobotDFPlayerMini.h"
#include "Grove-Ultrasonic-Ranger.h"
#include "HX711.h"
#include "TCreds.h"
#include "neopixel.h"
#include <Adafruit_BME280.h>
#include <Adafruit_MQTT.h>
#include <math.h>

DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

Ultrasonic ultrasonic(A0);
const int MQ4ANALOGPIN = A1;
const int FLAMEPIN = A2;
const int MQ7ANALOGPIN = A3;
const int PHOTODIODEPIN = A4;
const int AQPIN = A5;
HX711 loadCell(D2, D13);
const int FANPIN = D3;
const int EMERGENCYBUTTON = D4;
const int LEDPIN = D5;
// const int FLAMEPINDIGITAL = D6;
const int MOTIONSENSOR = D6;
const int PLAYTIME = 10000;
const int NUMBERTRACKS = 1;

Adafruit_BME280 bme;

bool status2;
int p, timer3;
int flameSensor;
int currentTime, currentTime1, currentTime2, currentTime3, currentTime4, currentTime5, currentTime6, currentTime7, currentTime8, currentTime9;
int lastTime, lastTime1, lastTime2, lastTime3, lastTime4, lastTime5, lastTime6, lastTime7, lastTime8, lastTime9;
int mq4Analog;
int mq7Analog;
int diodeNum;
int nightLed;
int motion;
int AqSensor;
bool button;
int oldButton;
int onOff;
float tempC, tempF;
int hexAddress = 0x76;
bool status;
int i;
int pixelCount = 24;
int pixelType = WS2812B;
int pixelBri;
int ultraSonicSensor;
int trashMesure;

unsigned int timer;
unsigned int timer2;
bool redState;

Adafruit_NeoPixel strip(pixelCount, LEDPIN, pixelType);
const int CAL_FACTOR = 2333;
const int SAMPLES = 10;
float weight, rawData, calibration;
int offset;

TCPClient TheClient;

Adafruit_MQTT_SPARK mqtt(&TheClient, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

Adafruit_MQTT_Publish mqttUltraSonic = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Trash_can_Ultrasonic");
Adafruit_MQTT_Publish mqttFire = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Fire_Sensor");
Adafruit_MQTT_Publish mqttMethane = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Methane_Sensor");
Adafruit_MQTT_Publish mqttAlcohol = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/MQ7_Sensor");
Adafruit_MQTT_Publish mqttPhotoDiode = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Daylight_Sensor");
Adafruit_MQTT_Publish mqttTemp = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Temperature");
Adafruit_MQTT_Publish mqttLoadCell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Trash_Can_Loadcell");
Adafruit_MQTT_Publish mqttAqSensor = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Air_Quality_Sensor");
Adafruit_MQTT_Publish mqttTrashIsFull = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Trash_Is_Full");

SYSTEM_MODE(SEMI_AUTOMATIC);

void setup() {
    Serial.begin(9600);
    Serial1.begin(9600);
    
    // pinMode(FLAMEPIN, INPUT);
    pinMode(MQ4ANALOGPIN, INPUT);
    pinMode(MQ7ANALOGPIN, INPUT);
    pinMode(PHOTODIODEPIN, INPUT);
    pinMode(EMERGENCYBUTTON, INPUT);
    pinMode(LEDPIN, OUTPUT);
    pinMode(AQPIN, INPUT);
    pinMode(FANPIN, OUTPUT);
    pinMode(LEDPIN, OUTPUT);
    pinMode(MOTIONSENSOR, INPUT);
    strip.begin();
    strip.show();

    // MP3
    status2 = myDFPlayer.begin(Serial1, false);
    myDFPlayer.volume(25); //  0 to 30
    p = 0;
    timer3 = -PLAYTIME;
    // LOADCELL
    loadCell.set_scale();
    loadCell.tare();
    loadCell.set_scale(CAL_FACTOR);
    // WIFI
    WiFi.connect();
    while (WiFi.connecting()) {
        Serial.printf(".");
    }
    // BME
    status = bme.begin(hexAddress);
    if (status == false) {
        Serial.printf("BME280 at address 0x%02X failed to start", hexAddress);
    }
}
void loop() {

    MQTT_connect();
    long RangeInCentimeters;

    diodeNum = analogRead(PHOTODIODEPIN);
    // Serial.printf("motion:%i\n", motion);

    motion = digitalRead(MOTIONSENSOR);

     
    // test, now delete

    button = digitalRead(EMERGENCYBUTTON);  

    if(button!=oldButton){
        if (button == true) {
            onOff = !onOff;
        }
            oldButton = button;
        }
        //Serial.printf("onOff:%i\n", onOff);

    if(onOff==0){
        if (diodeNum > 3000) {
    diodeNum = 3000;
    }
    if (diodeNum < 80) {
    diodeNum = 80;
     }
     pixelBri = map(diodeNum, 80, 3000, 255, 0);
     for (i = 0; i < 24; i++) {
     strip.setBrightness(pixelBri);
     strip.setPixelColor(i, 255, 241, 224);
      strip.show();
     }
    }
    
    if (onOff == 1) {    
        if (millis() - timer2 > 10000) {
            onOff = false;
            timer2 = millis();
        }
        if (millis() - timer > 1000) {
            redState = !redState;
            // FLASHRED
            flashRed();
            // mp3
            mp3();
            timer = millis();
        }

        Serial.printf("Emergency button has been pressed.\n", button);
    }

    // Ultrasonic Sensor
    ultraSonicSensor = (ultrasonic.MeasureInCentimeters());

    if ((millis() - lastTime1) > 30000) {
        mq4Analog = analogRead(MQ4ANALOGPIN);
        mq7Analog = analogRead(MQ7ANALOGPIN);

        mq4Analog = analogRead(MQ4ANALOGPIN);
        mq7Analog = analogRead(MQ7ANALOGPIN);

        if (mqtt.Update()) {

            // MQ4 & MQ7 Sensors
            // indoor reading: 1800-2100 by an exhaust is around 3200-3400

            mqttMethane.publish(mq7Analog);
            Serial.printf("Publishing MQ7 level:: %i \n", mq7Analog);
            mqttAlcohol.publish(mq4Analog);
            Serial.printf("Publishing MQ4 level:: %i \n", mq4Analog);

            // Ultra Sonic
            trashMesure = map(ultraSonicSensor,0,10,500,0);
            mqttUltraSonic.publish(trashMesure);
            Serial.printf("Publishing Ultra Sonic Sensor  %i\n", trashMesure);

             Flame Sensor
             flameSensor = analogRead(FLAMEPIN);
             if (flameSensor < 1500) {
                 Serial.printf("Flame Detected!");
                 mqttFire.publish(flameSensor);
                 Serial.printf("Publishing flameSensor:%i \n", flameSensor);
             }

            // Photo Diode Sensor
            mqttPhotoDiode.publish(diodeNum);
            Serial.printf("Publishing Daylight Sensor:%i \n", diodeNum);

            weight = loadCell.get_units(SAMPLES);
            rawData = loadCell.get_offset();
            calibration = loadCell.get_scale();

            // Load Cell Sensor
            mqttLoadCell.publish(weight);
            Serial.printf("Publishing trash can weight:%0.2f \n", weight);

            // Air Quality Sensor
            AqSensor = analogRead(AQPIN);
            mqttAqSensor.publish(AqSensor);
            Serial.printf("Publishing Air Quality:%i \n", AqSensor);

            // Temperature/BME
            tempC = bme.readTemperature();
            tempF = tempC * (9.0 / 5.0) + 32.2;

            mqttTemp.publish(tempF);
            Serial.printf("Publishing temparture:%0.2f \n", tempF);

            lastTime1 = millis();
        }
    }
    if (tempF > 69 && AqSensor < 1500) {
        digitalWrite(FANPIN, 1);
    } else {
        digitalWrite(FANPIN, 0);
    }
}

void MQTT_connect() {
    int8_t ret;

    // Stop if already connected.
    if (mqtt.connected()) {
        return;
    }

    Serial.print("Connecting to MQTT... ");

    while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
        Serial.printf("%s\n", (char *)mqtt.connectErrorString(ret));
        Serial.printf("Retrying MQTT connection in 5 seconds..\n");
        // mqtt.disconnect();
        delay(5000); // wait 5 seconds
    }
    Serial.printf("MQTT Connected!\n");
}

void flashingLights() {
    strip.clear();
    for (i = 0; i < 24; i++) {
        currentTime3 = millis();
        if ((currentTime3 - lastTime3) > 1000) {
            strip.setPixelColor(i, 255, 0, 0);
            lastTime3 = millis();
        }
        currentTime4 = millis();
        if ((currentTime4 - lastTime4) > 1000) {
            strip.setPixelColor(i, 255, 255, 255);
            lastTime4 = millis();
        }
    }
    strip.show();
}

void flashRed() {
    int i;
    int j;

   
        if (redState) {
             for (j = 0; j < 24; j++) {
            strip.setPixelColor(j, 0XFF0000);
            strip.setBrightness(20);
            strip.show();
             }
        }
        if (redState == false) {
             for (j = 0; j < 24; j++) {
            strip.setPixelColor(j, 0,0,0);
            strip.setBrightness(20);
            strip.show();
             }
        }
    }


void mp3() {
        Serial.printf("Play Next - Track\n");
        myDFPlayer.play(1); // Play next mp3 every 3 second.
        delay(6000);
    }


void printDetail(uint8_t type, int value) {
    switch (type) {
    case TimeOut:
        Serial.printf("Time Out!\n");
        break;
    case WrongStack:
        Serial.printf("Stack Wrong!\n");
        break;
    case DFPlayerCardInserted:
        Serial.printf("Card Inserted!\n");
        break;
    case DFPlayerCardRemoved:
        Serial.printf("Card Removed!\n");
        break;
    case DFPlayerCardOnline:
        Serial.printf("Card Online!\n");
        break;
    case DFPlayerPlayFinished:
        Serial.printf("Number: %i Play Finished\n", value);
        break;
    case DFPlayerError:
        Serial.printf("DFPlayerError: ");
        switch (value) {
        case Busy:
            Serial.printf("Card not found\n");
            break;
        case Sleeping:
            Serial.printf("Sleeping\n");
            break;
        case SerialWrongStack:
            Serial.printf("Get Wrong Stack\n");
            break;
        case CheckSumNotMatch:
            Serial.printf("Check Sum Not Match\n");
            break;
        case FileIndexOut:
            Serial.printf("File Index Out of Bound\n");
            break;
        case FileMismatch:
            Serial.printf("Cannot Find File\n");
            break;
        case Advertise:
            Serial.printf("In Advertise\n");
            break;
        default:
            break;
        }
        break;
    default:
        break;
    }
}

The article was first published in hackster, April 22, 2022

cr: https://www.hackster.io/dennis-davis/smart-bus-stop-ec9914

author: Dennis Davis, Thomas Abeyta

License
All Rights
Reserved
licensBg
0