Dr. Vernon Cox
Published © MIT

CAPSTONE_BusAlerter

This is a design that helps people know when their bus is coming to their bus stop.

BeginnerFull instructions provided2 days60
CAPSTONE_BusAlerter

Things used in this project

Hardware components

Argon
Particle Argon
×1
LoRa Module
Wireless-Tag LoRa Module
×1
Flora GPS Module
Adafruit Flora GPS Module
×1
Rotary Encoder with Push-Button
Rotary Encoder with Push-Button
×1
Seeed Studio Grove - OLED Display 0.66" (SSD1306)- IIC - 3.3V/5V
Seeed Studio Grove - OLED Display 0.66" (SSD1306)- IIC - 3.3V/5V
×1
Grove - Optocoupler Relay (M281)
Seeed Studio Grove - Optocoupler Relay (M281)
×1
Solar Cockroach Vibrating Disc Motor
Brown Dog Gadgets Solar Cockroach Vibrating Disc Motor
×1
Breadboard (generic)
Breadboard (generic)
×1

Software apps and online services

Visual Studio Code Extension for Arduino
Microsoft Visual Studio Code Extension for Arduino
Microsoft Project
Microsoft MS Visio
Adobe PDF
Microsoft Excel

Hand tools and fabrication machines

Mastech MS8217 Autorange Digital Multimeter
Digilent Mastech MS8217 Autorange Digital Multimeter
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Plier, Needle Nose
Plier, Needle Nose
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

BusAlertHandunit

This is the unit that people with have when they want to know where there bus is.

BusAlertHandunit

BusAlerterBus

This is the unit that will be connect to each bus in a bus system

BusAlertBusunit

This is the unit that is place on each bus in a bus system

Code

BusAlertHandunit

C/C++
This is the code that is used to activate and control the busAlerter handheld unit
/*
 * Project Capstone: BusAlerter
 * Description: BusConnection prototype
 * Modified by Vernon Cox and Edward Ishman Authored by: Brian Rashap and Christian Chavez
 * Date: 24-MAR-2023 _ 21Apr23
 */


#include "Adafruit_SSD1306.h"
#include "Encoder.h"
#include <IoTClassroom_CNM.h>
#define OLED_RESET D4
 
//Adafruit_OLED
Adafruit_SSD1306 display(OLED_RESET);
IoTTimer myTimer;

Encoder busEnc(D12,D11); //This is where the A and B pin are mapped.

// Define User and Credentials
String password = "AA4104132968BA2224299079021594AB"; // AES128 password
String myName = "DrVernonCox";
const int RADIOADDRESS = 0xC6; // Get address from Instructor, it will be a value between 0xC1 - 0xCF
const int TIMEZONE = -6;

// Define Constants
const int RADIONETWORK = 4;    // range of 0-16
const int SENDADDRESS = 0;   // address of radio to be sent to

// Declare Variables
float lat,lon,alt;
int sat;
static int busSe;
int busNmbr[]={53,53,53,53,53,53};
const int busBuzz=D5;//vibr buzzer
int busFind;
int busName;
int busHold;
int mappedBus;

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
SYSTEM_MODE(SEMI_AUTOMATIC);


void setup() {
  Serial.begin(9600);
  waitFor(Serial.isConnected, 5000);
  Serial1.begin(115200);
  reyaxSetup(password);
  delay(10000);

  pinMode(busBuzz,OUTPUT);
  digitalWrite(busBuzz,HIGH);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 
  display.display(); // show splashscreen


}

void loop() {

   mappedBus=busEnc.read();
   busFind=map(mappedBus, 0,4,0,1);
 
   if (busFind>4){
    busFind=4;
   }
   if (busFind<0){
    busFind=0;
   }
 
busName=busNmbr[busFind];
Serial.printf(" %i \n", busName);

  // listen for incoming lora messages and then send GPS back
  if (Serial1.available())  { // full incoming buffer: +RCV=203,50,35.08,9,-36,41 
    String parse0 = Serial1.readStringUntil('=');  //+RCV
    String parse1 = Serial1.readStringUntil(',');  // address received from
    String parse2 = Serial1.readStringUntil(',');  // buffer length
    String parse3 = Serial1.readStringUntil(',');  // fuseSound
    String parse4 = Serial1.readStringUntil(',');  // fuseDust
    String parse5 = Serial1.readStringUntil(',');  // rssi
    String parse6 = Serial1.readStringUntil(','); // snr
    String parse7 = Serial1.readStringUntil('\n'); // busNmbr
    String parse8 = Serial1.readString();          // extra

    Serial.printf("parse0: %s\nparse1: %s\nparse2: %s\nparse3: %s\nparse4: %s\nparse5: %s\nparse6: %s\nparse7: %s\nparse8: %s\n", parse0.c_str(), parse1.c_str(), parse2.c_str(), parse3.c_str(), parse4.c_str(), parse5.c_str(), parse6.c_str(), parse7.c_str(), parse8.c_str());
    delay(100);
      myTimer.startTimer(5000);
      digitalWrite(D7,HIGH);

           busHold=atoi(parse6.c_str());   
          Serial.printf("bushold %i ", busHold);
           if(busHold == busName) {
            display.clearDisplay();
            display.setTextSize(2);
            display.setTextColor(WHITE);
            display.setCursor(0,0);
            display.printf("Bus %i is coming\n",busHold);
            display.display();
        
          //using these lines to activate vibr motor
         digitalWrite(busBuzz,HIGH);
         delay(7350);
         digitalWrite(busBuzz,LOW);
  
   }
}
}


void reyaxSetup(String password) {
  // following four paramaters have most significant effect on range
  // recommended within 3 km: 10,7,1,7
  // recommended more than 3 km: 12,4,1,7
  const int SPREADINGFACTOR = 10;
  const int BANDWIDTH = 7;
  const int CODINGRATE = 1;
  const int PREAMBLE = 7;
  String reply; // string to store replies from module

  Serial1.printf("AT+ADDRESS=%i\r\n", RADIOADDRESS); // set the radio address
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply from address\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Reply address: %s\n", reply.c_str());
  }

  Serial1.printf("AT+NETWORKID=%i\r\n", RADIONETWORK); // set the radio network
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply from networkid\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Reply network: %s\n", reply.c_str());
  }

  Serial1.printf("AT+CPIN=%s\r\n", password.c_str());
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply from password\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Reply: %s\n", reply.c_str());
  }

  Serial1.printf("AT+PARAMETER=%i,%i,%i,%i\r\n", SPREADINGFACTOR, BANDWIDTH, CODINGRATE, PREAMBLE);
  delay(200);
  if (Serial1.available() > 0) {
    reply = Serial1.readStringUntil('\n');
    Serial.printf("reply: %s\n", reply.c_str());
  }

  Serial1.printf("AT+ADDRESS?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Radio Address: %s\n", reply.c_str());
  }

  Serial1.printf("AT+NETWORKID?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Radio Network: %s\n", reply.c_str());
  }

  Serial1.printf("AT+PARAMETER?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("RadioParameters: %s\n", reply.c_str());
  }

  Serial1.printf("AT+CPIN?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Radio Password: %s\n", reply.c_str());
  }
}

BusAlerterBus

C/C++
This is the C++ code used to control the busAlerter unit that is placed on each bus in a bus system.
/*
 * Project Capstone_BusAlerter
 * Description: BusConnection prototype
 * Modified by Vernon Cox and Edward Ishman Authored by: Brian Rashap and Christian Chavez
 * Date: 24-MAR-2023 _ 21Apr23
 */


SYSTEM_MODE(SEMI_AUTOMATIC);

#include <Adafruit_GPS.h>
#include <IoTClassroom_CNM.h>
 
Adafruit_GPS GPS(&Wire);

IoTTimer myTimer;

// Define User and Credentials
String password = "AA4104132968BA2224299079021594AB"; // AES128 password
String busName = "53";
const int RADIOADDRESS = 0xC2; // Get address from Instructor, it will be a value between 0xC1 - 0xCF
const int TIMEZONE = -6;

// Define Constants
const int RADIONETWORK = 4;    // range of 0-16
const int SENDADDRESS =0 ;   // address of radio to be sent to

// Declare Variables
float lat,lon,alt;
int sat;
const int busNumbr=53;


void setup() {
  Serial.begin(9600);
  waitFor(Serial.isConnected, 5000);

  Serial1.begin(115200);
  reyaxSetup(password);
  delay(10000);

  //Initialize GPS
  GPS.begin(0x10);  // The I2C address to use is 0x10
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); 
  GPS.sendCommand(PGCMD_ANTENNA);
  delay(1000);
  GPS.println(PMTK_Q_RELEASE);

//sendData(busName, lat, lon, sat);
  delay(2000);
}

void loop() {
  // Get data from GSP unit (best if you do this continuously)
  GPS.read();


  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA())) {
      return;
    }   
  }

    getGPS(&lat,&lon,&alt,&sat);

    if(lat != 0) {
      sendData(busName, lat, lon, sat);
    }
    else {
      sendData(busName, 33.400322, -104.534897, 0);
    }



 
  if (myTimer.isTimerReady()){
         digitalWrite(D7,LOW);
  }
  delay(17000);
}


void getGPS(float *latitude, float *longitude, float *altitude, int *satellites) {
  int theHour;

  theHour = GPS.hour + TIMEZONE;
  if (theHour < 0) {
    theHour = theHour + 24;
  }

  Serial.printf("Time: %02i:%02i:%02i:%03i\n", theHour, GPS.minute, GPS.seconds, GPS.milliseconds);
  Serial.printf("Dates: %02i-%02i-%02i\n", GPS.month, GPS.day, GPS.year);
  Serial.printf("Fix: %i, Quality: %i", (int)GPS.fix, (int)GPS.fixquality);
  if (GPS.fix) {
    *latitude = GPS.latitudeDegrees;
    *longitude = GPS.longitudeDegrees;
    *altitude = GPS.altitude;
    *satellites = (int)GPS.satellites;
  }
}

void sendData(String name, float latitude, float longitude, int satelittes) {
  char buffer[60];

  Serial.printf("Sending GPS Data to bus station\n");
  sprintf(buffer, "AT+SEND=%i,60,%f,%f,%i,%s\r\n", SENDADDRESS, latitude, longitude, satelittes, name.c_str());
  Serial1.printf("%s",buffer);
  Serial.printf("%s",buffer); 
  delay(1000);
  if (Serial1.available() > 0)
  {
    Serial.printf("Awaiting Reply from send\n");
    String reply = Serial1.readStringUntil('\n');
    Serial.printf("Send reply: %s\n", reply.c_str());
  }
}

void reyaxSetup(String password) {
  // following four paramaters have most significant effect on range
  // recommended within 3 km: 10,7,1,7
  // recommended more than 3 km: 12,4,1,7
  const int SPREADINGFACTOR = 10;
  const int BANDWIDTH = 7;
  const int CODINGRATE = 1;
  const int PREAMBLE = 7;
  String reply; // string to store replies from module

  Serial1.printf("AT+ADDRESS=%i\r\n", RADIOADDRESS); // set the radio address
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply from address\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Reply address: %s\n", reply.c_str());
  }

  Serial1.printf("AT+NETWORKID=%i\r\n", RADIONETWORK); // set the radio network
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply from networkid\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Reply network: %s\n", reply.c_str());
  }

  Serial1.printf("AT+CPIN=%s\r\n", password.c_str());
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply from password\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Reply: %s\n", reply.c_str());
  }

  Serial1.printf("AT+PARAMETER=%i,%i,%i,%i\r\n", SPREADINGFACTOR, BANDWIDTH, CODINGRATE, PREAMBLE);
  delay(200);
  if (Serial1.available() > 0) {
    reply = Serial1.readStringUntil('\n');
    Serial.printf("reply: %s\n", reply.c_str());
  }

  Serial1.printf("AT+ADDRESS?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Radio Address: %s\n", reply.c_str());
  }

  Serial1.printf("AT+NETWORKID?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Radio Network: %s\n", reply.c_str());
  }

  Serial1.printf("AT+PARAMETER?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("RadioParameters: %s\n", reply.c_str());
  }

  Serial1.printf("AT+CPIN?\r\n");
  delay(200);
  if (Serial1.available() > 0) {
    Serial.printf("Awaiting Reply\n");
    reply = Serial1.readStringUntil('\n');
    Serial.printf("Radio Password: %s\n", reply.c_str());
  }
}

Credits

Dr. Vernon Cox

Dr. Vernon Cox

2 projects • 5 followers
My project management philosophy is to create a team atmosphere that allows open communication, teamwork, as well as, employee involvement.

Comments

Add projectSign up / Login