# StreetLight Intensity Mapping
Why: Every year millions of people meet with road accidents and the reasons are vast and varied. Poor street lighting is one of them, which causes a rider or driver to crash due to a lack of visibility.
In 2016 in Kerala according to their data nearly 250 from 5-6 PM but 350 from 6-7 PM a year.
Rajashekar experienced an accident on a poorly light road, on an unmarked road hump.
With increasing accidents due to potholes around the city, he felt strongly that most of us should not have such experiences.
To reduce the chances of such accidents, he is working to measure streetlight levels near road humps and a system to report dangerous potholes. The data will allow him to make a 2 pronged approach to engaging governance around streetlights and reflectors.
How:A GPS-enabled IoT device uses light-intensity sensors to collect data and a data logger to mark the location.
What (Output): Wants to be able to map this data and make a report/presentation to authorities
so that he can draw their attention to this issue and enable them to make data-based interventions.
Reference Link for Standards:
The link will be added soon
GitHub Link:
Data collected so far:
Data Sheet :
[LAMP Data Sheet - Google Sheets]
WireMapping
Prerequisites:
Install Arduino IDE
Install ESP on Arduino IDE > Install version 2.7.4 only as this version allows you to push data to a Google sheet
Libraries to install for GPS to work
Image of the prototype (V1) :
PCB Version(V2) :
COMPONENTS :
- NodeMCU
- Digital Light Intensity Sensor (BH1750)
- Neo6M GPS module
- Micro USB Cable
- Powerbank
- WIFI Connection
- During Building: Laptop with Arduino installed
CODE :
// libraries for GPS module
#include <ESP8266WiFi.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <BH1750.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <WiFiClientSecure.h>
#include <WiFiManager.h>
TinyGPSPlus gps; // The TinyGPS++ object
SoftwareSerial ss(2, 14); //we are creating a software connection between GPS and NodeMCU here
float latitude , longitude, lux;
BH1750 lightMeter(0x23);
String latlong, lat_str, lng_str, speedkmph;
int sats;
//Server Setup
const char* host = "script.google.com";
//String AQMno = "RS001";
const int httpsPort = 443;
WiFiClientSecure client;
const char* fingerprint = "46 B2 C3 44 9C 59 09 8B 01 B6 F8 BD 4C FB 00 74 91 2F EF F6";
String GAS_ID = "AKfycbymduICB_WVvZJVPIoA7_Cly1OCtfB7Nlx7YUcAoJ4d69qUtaRgzfqdX9I5Dl8mRuc"; // Replace by your GAS service id
const long utcOffsetInSeconds = 19800; //converts time recieved by GPS to IST
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
ss.begin(9600);
Serial.println();
Wire.begin();
// begin returns a boolean that can be used to detect setup problems.
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE_2)) {
Serial.println(F("BH1750 Advanced begin"));
}
else {
Serial.println(F("Error initialising BH1750"));
}
WiFiManager wifiManager;
wifiManager.setTimeout(180);
if (!wifiManager.autoConnect("SetUpWifionRS001")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
delay(3000);
}
void loop() {
// put your main code here, to run repeatedly:
while (ss.available() > 0) //while data is available
if (gps.encode(ss.read())) //read gps data
{
if (gps.location.isValid()) //check whether gps location is valid
{
latitude = gps.location.lat();
lat_str = String(latitude , 6); // latitude location is stored in a string
longitude = gps.location.lng();
lng_str = String(longitude , 6); //longitude location is stored in a string
latlong = lat_str + "," + lng_str;
Serial.println(latlong);
sats = gps.satellites.value();
speedkmph = gps.speed.kmph();
if (lightMeter.measurementReady()) {
lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
}
client.setInsecure();
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
} else {
Serial.println("certificate doesn't match");
}
//String string_y = String(sendvalue);
//String url = "/macros/s/" + GAS_ID + "/exec?A=" + latlong + "&B=" + lux;
String url = "/macros/s/" + GAS_ID + "/exec?A=" + latlong +"&B=" + sats+"&C=" + speedkmph+"&D=" + lux;
Serial.print("requesting URL: ");
Serial.println(url);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: BuildFailureDetectorESP8266\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
Serial.println("headers received");
break;
}
}
String line = client.readStringUntil('\n');
if (line.startsWith("{\"state\":\"success\"")) {
Serial.println("esp8266/Arduino CI successfull!");
} else {
Serial.println("esp8266/Arduino CI has failed");
}
Serial.println("reply was:");
Serial.println("==========");
Serial.println(line);
Serial.println("==========");
Serial.println("closing connection");
}
}
}
Image of the Version 3(V3)
In this version, we have added the feature of mapping problem statements by just clicking a button(Also called Data Logger)
COMPONENTS :
- Above mentioned components
- Buttons
- Resistors(10k)
Data Sheet:
https://docs.google.com/spreadsheets/d/1feByiI4lip0q4ODRvIWoWGAScQg90u9Uqrvls-M8uos/edit#gid=0
CODE :
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <BH1750.h>
#include <Wire.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <WiFiClientSecure.h>
/*
This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
It requires the use of SoftwareSerial and assumes that you have a
4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 0, TXPin = 2;
static const uint32_t GPSBaud = 9600;
//Light sensor
BH1750 lightMeter(0x23);
float latitude , longitude, lux;
String latlong, lat_str, lng_str, speedkmph;
int sats;
//Button
int button = 12;
int button2 = 14;
int buttonpress, buttonpress2 = 0;
volatile bool potholeFlag, streetlightFlag = 0;
//Device ID
String DevID = "RS002";
String tim = "";
String url = "";
String issue;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
//Google Server Setup Section
const char* host = "script.google.com";
const int httpsPort = 443;
WiFiClientSecure client;
const char* fingerprint = "46 B2 C3 44 9C 59 09 8B 01 B6 F8 BD 4C FB 00 74 91 2F EF F6";
String GAS_ID = "AKfycbysWuYi2TWR59n8338W5HUXsEWDuRHKY-_cB3P0LKby6blFZ-nImt6TG3BWP9XzKcQ"; // Replace by your Google App S service id
//Set up to send to GSheets
String readString;
void ICACHE_RAM_ATTR potholeButtonClick() {
potholeFlag = true;
// buttonpress = digitalRead (button);
Serial.println("pothole interrupt was triggered");
}
void ICACHE_RAM_ATTR streetlightButtonClick() {
streetlightFlag = true;
// buttonpress2 = digitalRead (button2);
Serial.println("streetlight interrupt was triggered");
}
void setup()
{
Serial.begin(115200);
ss.begin(GPSBaud);
pinMode(button, INPUT);
pinMode(button2, INPUT);
attachInterrupt(digitalPinToInterrupt(button), potholeButtonClick, RISING);
attachInterrupt(digitalPinToInterrupt(button2), streetlightButtonClick, RISING);
WiFiManager wifiManager;
wifiManager.setTimeout(180);
//Light sensor bit
Wire.begin();
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE_2)) {
Serial.println(F("BH1750 Advanced begin"));
}
else {
Serial.println(F("Error initialising BH1750"));
}
if (!wifiManager.autoConnect("SetupWIFIDataLogger")) {
Serial.println("failed to connect and hit timeout");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
delay(3000);
}
void loop()
{
buttonpress = digitalRead (button);
if (buttonpress != 0) {
Serial.println("button pressed");
// displayInfo();
}
buttonpress2 = digitalRead (button2);
if (buttonpress2 != 0) {
Serial.println("button2 pressed");
// displayInfo();
}
// This sketch displays information every time a new sentence is correctly encoded
//while changed to if because the whole function is a loop
if (ss.available() > 0){
if (gps.encode(ss.read())) {
if (gps.location.isValid()) //check whether gps location is valid
{
latitude = gps.location.lat();
lat_str = String(latitude , 6); // latitude location is stored in a string
longitude = gps.location.lng();
lng_str = String(longitude , 6); //longitude location is stored in a string
latlong = lat_str + "," + lng_str;
Serial.println(latlong);
sats = gps.satellites.value();
speedkmph = gps.speed.kmph();
if (lightMeter.measurementReady()) {
lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
}
//String string_y = String(sendvalue);
//String url = "/macros/s/" + GAS_ID + "/exec?A=" + latlong + "&B=" + lux;
issue = "";
if(potholeFlag)
{
Serial.print("came into pothole part");
issue = "pothole";
potholeFlag=false;
streetlightFlag=false;
}
if(streetlightFlag)
{
issue="streetlight";
Serial.print("came into streetlight part");
streetlightFlag=false;
potholeFlag=false;
}
String url = "/macros/s/" + GAS_ID + "/exec?A=" + latlong + "&B=" + sats + "&C=" + speedkmph + "&D=" + lux + "&device=" + DevID + "&issue=" + issue;
senddata(url);
}
}
}
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("No GPS detected: check wiring."));
}
}
void displayInfo()
{
Serial.print(F("Location: "));
if (gps.location.isValid())
{
Serial.print(gps.location.lat(), 6);
Serial.print(F(","));
Serial.print(gps.location.lng(), 6);
}
else
{
Serial.print(F("INVALID"));
}
Serial.print(F(" Date/Time: "));
if (gps.date.isValid())
{
Serial.print(gps.date.month());
Serial.print(F("/"));
Serial.print(gps.date.day());
Serial.print(F("/"));
Serial.print(gps.date.year());
}
else
{
Serial.print(F("INVALID"));
}
Serial.print(F(" "));
if (gps.time.isValid())
{
if (gps.time.hour() < 10) Serial.print(F("0"));
Serial.print(gps.time.hour());
Serial.print(F(":"));
if (gps.time.minute() < 10) Serial.print(F("0"));
Serial.print(gps.time.minute());
Serial.print(F(":"));
if (gps.time.second() < 10) Serial.print(F("0"));
Serial.print(gps.time.second());
Serial.print(F("."));
if (gps.time.centisecond() < 10) Serial.print(F("0"));
Serial.print(gps.time.centisecond());
}
else
{
Serial.print(F("INVALID"));
}
Serial.println();
}
void senddata(String url) {
client.setInsecure();
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
} else {
Serial.println("certificate doesn't match");
}
Serial.print("requesting URL: ");
Serial.println(url);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: BuildFailureDetectorESP8266\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
Serial.println("headers received");
break;
}
}
String line = client.readStringUntil('\n');
if (line.startsWith("{\"state\":\"success\"")) {
Serial.println("esp8266/Arduino CI successfull!");
} else {
Serial.println("esp8266/Arduino CI has failed");
}
Serial.println("reply was:");
Serial.println("==========");
Serial.println(line);
Serial.println("==========");
Serial.println("closing connection");
}