#include <LiquidCrystal_I2C.h>
#include <TinyGPS++.h>
#include <HardwareSerial.h>
#include <Keypad.h>
// Initialize LCD
LiquidCrystal_I2C lcd(0x27, 16, 2);
TinyGPSPlus gps;
HardwareSerial SerialGPS(2); // UART2 for GPS
//Initialize Keypad module:
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {13, 12, 14, 27};
byte colPins[COLS] = {26, 25, 33, 32};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Predefined region thresholds
struct Region {
String name;
float threshold;
};
Region regionDatabase[] = {
{"001", 5.0},
{"003", 8.0},
{"008", 10.0}
};
String enteredRegion = "";
String enteredCode = "";
const String accessCode = "1234"; // Authority access code
// Define pins
const int potPin = 34; // Potentiometer to simulate alcohol level
const int buttonPin = 19; // Button for Uber booking
const int tamperButtonPin = 23; // Button for tamper detection
const int buzzerPin = 4; // Buzzer for tamper alert
const int relayPin = 18; // GPIO pin connected to the relay
bool uberBooked = false;
float BACThreshold = 8.0;
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
Serial.begin(9600);
SerialGPS.begin(9600); // GPS on UART2
Serial.println("Initializing Alcohol Lock System...");
// LCD Setup
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Please Blow into");
lcd.setCursor(0, 1);
lcd.print("Device");
// Configure pins
pinMode(potPin, INPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(tamperButtonPin, INPUT_PULLUP); // Set tamper button as input with pull-up
pinMode(buzzerPin, OUTPUT); // Set buzzer pin as output
pinMode(relayPin, OUTPUT);
delay(5000); // Initial message delay
lcd.clear();
Serial.println("System Ready");
}
void loop() {
// Check for tamper detection
if (digitalRead(tamperButtonPin) == LOW) {
Serial.println("Tamper button pressed");
activateBuzzer();
}
int alcoholLevel = analogRead(potPin); // Read alcohol level (0 - 4095 for ESP32)
float scaledLevel = alcoholLevel / 4095.0 * 100; // Scale to a percentage
char key = keypad.getKey();
if (key) {
if (key == 'A') {
// Initiate code entry for authorities
lcd.clear();
lcd.print("Enter Access Code:");
enteredCode = "";
while (enteredCode.length() < 4) {
key = keypad.getKey();
if (key && key != 'A') {
enteredCode += key;
lcd.setCursor(enteredCode.length(), 1);
lcd.print("*");
}
}
delay(500);
validateCode();
}
}
// Code to get latitude and longitude readings from the GPS module
while (SerialGPS.available() > 0) {
if (gps.encode(SerialGPS.read())) {
if (gps.location.isValid()) {
Serial.print(F("Latitude: "));
Serial.println(gps.location.lat(), 6);
Serial.print(F("Longitude: "));
Serial.println(gps.location.lng(), 6);
}
}
}
// Code to enable Alcohol Ignition Lock, if default threshold level is 8%
if (scaledLevel > BACThreshold) {
setLCD("Over Limit!", "Book Uber? Press");
Serial.print("Alcohol Level: ");
Serial.print(scaledLevel);
Serial.println("% - Over Limit! Prompting to Book Uber.");
//Dectivate relay
digitalWrite(relayPin, LOW);
// Check if the Uber booking button is pressed
if (digitalRead(buttonPin) == LOW && !uberBooked) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Uber Booked!");
Serial.println("Uber Booked!");
uberBooked = true;
delay(3000); // Show booking confirmation
}
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Clear to Drive");
Serial.print("Alcohol Level: ");
Serial.print(scaledLevel);
Serial.println("% - Clear to Drive");
digitalWrite(relayPin, HIGH);
uberBooked = false;
}
delay(500); // Update every half second
}
// Function to activate the buzzer and display tamper warning
void activateBuzzer() {
digitalWrite(buzzerPin, HIGH); // Turn on buzzer
Serial.println("Tamper detected! System has been tampered with.");
delay(2000); // Sound buzzer for 2 seconds
digitalWrite(buzzerPin, LOW); // Turn off buzzer
}
void validateCode() {
if (enteredCode == accessCode) {
lcd.clear();
lcd.print("Code Accepted");
Serial.println("Authority Access Granted");
delay(1000);
enterRegion();
} else {
lcd.clear();
lcd.print("Access Denied");
Serial.println("Access Denied");
delay(2000);
lcd.clear();
}
}
void enterRegion() {
lcd.clear();
lcd.print("Enter Region: ");
enteredRegion = "";
unsigned long startTime = millis(); // Initialize for timeout to handle inactivity
while (enteredRegion.length() < 3) {
char key = keypad.getKey(); // Read key within the loop
// Check for timeout (10 seconds)
if ((millis() - startTime) >= 10000) {
lcd.clear();
lcd.print("Entry Timeout");
delay(2000);
return; // Exit function on timeout
}
if (key) {
startTime = millis(); // Reset timer on keypress
if (key != 'A') { // Ignore 'A' key
enteredRegion += key;
lcd.setCursor(enteredRegion.length(), 1);
lcd.print(key);
}
}
}
lcd.clear();
setThreshold();
}
// Function to set the threshold based on the region
void setThreshold() {
bool regionFound = false;
for (Region r : regionDatabase) {
if (r.name == enteredRegion) {
BACThreshold = r.threshold;
lcd.clear();
setLCD("Threshold lvl:", BACThreshold);
Serial.print("New Threshold for ");
Serial.print(enteredRegion);
Serial.print(": ");
Serial.println(BACThreshold);
regionFound = true;
break;
}
}
if (!regionFound) {
lcd.clear();
setLCD("Entered region", "not found");
Serial.println("Region Not Found in Database");
}
delay(2000);
lcd.clear();
}
void setLCD(auto string1, auto string2){
lcd.setCursor(0,0);
lcd.print(String(string1));
lcd.setCursor(0,1);
lcd.print(String(string2));
}
Loading
esp32-devkit-c-v4
esp32-devkit-c-v4