#include <Servo.h>
#include <SD.h>
#include <SPI.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
// Pin definitions
const int trigPins[] = {22, 24, 26, 28}; // Ultrasonic sensor trigger pins
const int echoPins[] = {23, 25, 27, 29}; // Ultrasonic sensor echo pins
const int servoPins[] = {2, 3, 4}; // Servo motor pins
const int buttonPins[] = {5, 6, 7, 19, 20}; // Push button pins (including Continue and Go Back)
const int proximitySensorPins[] = {32, 33}; // Inductive proximity sensor pins
const int buzzerPins[] = {34, 35}; // Buzzer pins
const int chipSelect = 10; // SD card chip select pin
const int servo4Pin = 36;
const int servo5Pin = 37;
// GSM Module Pins
SoftwareSerial sim(15, 16); // TX, RX (Use Pins 30 and 31 for the GSM module)
// LCD2004 Pins (Parallel Mode)
LiquidCrystal lcd2004(8, 9, 11, 12, 13, 14);
bool useLCD2004 = true; // Set to true for LCD2004, false for ST7920
// Variables
long duration[4];
int distance[4];
int buttonState[5];
int lastButtonState[5] = {LOW, LOW, LOW, LOW, LOW};
int servoCount[3] = {0, 0, 0};
int selectedItem = -1; // -1 means no item selected
bool waitingForContinue = false; // True when waiting for Continue button
bool countingBottles = false; // True when counting PET bottles
int PET_BottleCount = 0;
const int PET_BOTTLE_COUNT_LIMIT = 10; // Set your PET bottle count limit
Servo servos[3];
Servo servo4; // Only declare once
Servo servo5; // Only declare once
File dataFile;
void setup() {
// Initialize serial communication
Serial.begin(9600);
sim.begin(9600);
delay(1000);
// Initialize pins
for (int i = 0; i < 4; i++) {
pinMode(trigPins[i], OUTPUT);
pinMode(echoPins[i], INPUT);
}
for (int i = 0; i < 3; i++) {
pinMode(buttonPins[i], INPUT);
servos[i].attach(servoPins[i]);
}
pinMode(buttonPins[3], INPUT); // Continue button
pinMode(buttonPins[4], INPUT); // Go Back button
// Initialize SD card
if (!SD.begin(chipSelect)) {
Serial.println("SD card initialization failed!");
return;
}
Serial.println("SD card initialized.");
// Initialize LCD
lcd2004.begin(20, 4);
lcd2004.clear();
lcd2004.setCursor(0, 0);
lcd2004.print("Select an item");
lcd2004.setCursor(0, 1);
lcd2004.print("1) Distilled Water");
lcd2004.setCursor(0, 2);
lcd2004.print("2) Skyflakes");
lcd2004.setCursor(0, 3);
lcd2004.print("3) Instant noodles");
}
void loop() {
for (int i = 0; i < 3; i++) {
int reading = digitalRead(buttonPins[i]);
if (reading != lastButtonState[i]) {
lastButtonState[i] = reading;
if (reading == HIGH && !waitingForContinue) {
selectedItem = i;
displayItemConfirmation(i);
waitingForContinue = true;
}
}
// Ultrasonic distance measurement
digitalWrite(trigPins[i], LOW);
delayMicroseconds(2);
digitalWrite(trigPins[i], HIGH);
delayMicroseconds(10);
digitalWrite(trigPins[i], LOW);
duration[i] = pulseIn(echoPins[i], HIGH);
distance[i] = duration[i] * 0.034 / 2;
// Check distances and display messages
if (distance[i] > 20 && servoCount[i] >= 3) {
switch (i) {
case 0:
displayMessage(i, "Low on supply: Lucky Me noodles");
break;
case 1:
displayMessage(i, "Low on supply: Mineral water");
break;
case 2:
displayMessage(i, "Low on supply: Sky Flakes");
break;
}
SendMessage();
servoCount[i] = 0;
}
}
// Check the 4th ultrasonic sensor for critical level
digitalWrite(trigPins[3], LOW);
delayMicroseconds(2);
digitalWrite(trigPins[3], HIGH);
delayMicroseconds(10);
digitalWrite(trigPins[3], LOW);
duration[3] = pulseIn(echoPins[3], HIGH);
distance[3] = duration[3] * 0.034 / 2;
if (distance[3] < 150) {
SendMessageCriticalLevel();
}
// Check for Continue and Go Back button presses
for (int i = 3; i < 5; i++) {
int reading = digitalRead(buttonPins[i]);
if (reading != lastButtonState[i]) {
lastButtonState[i] = reading;
if (reading == HIGH) {
if (i == 3) {
// Continue button action
if (selectedItem != -1) {
lcd2004.clear();
lcd2004.setCursor(0, 1);
lcd2004.print("Bottles Inserted");
countingBottles = true;
PET_BottleCount = 0;
waitingForContinue = false;
while (countingBottles) {
checkProximitySensor();
if (PET_BottleCount >= getPETBottleCountLimit(selectedItem)) {
lcd2004.clear();
lcd2004.setCursor(0, 0);
lcd2004.print("The Right amount of");
lcd2004.setCursor(0, 1);
lcd2004.print("PET bottles has been");
lcd2004.setCursor(0, 2);
lcd2004.print("inserted");
delay(2000);
rotateServo(selectedItem);
logToSD(selectedItem);
returnToSelectItem();
selectedItem = -1;
countingBottles = false;
break;
}
}
}
} else if (i == 4) {
// Go Back button action
selectedItem = -1;
waitingForContinue = false;
returnToSelectItem();
}
}
}
}
delay(500); // Short delay to avoid spamming the loop
}
void rotateServo(int index) {
servos[index].write(180); // Rotate to 180 degrees
delay(500);
servos[index].write(0); // Rotate back to 0 degrees
delay(500);
}
void logToSD(int index) {
dataFile = SD.open("data.txt", FILE_WRITE);
if (dataFile) {
switch (index) {
case 0:
dataFile.println("Lucky Me noodles dispensed");
break;
case 1:
dataFile.println("Mineral water dispensed");
break;
case 2:
dataFile.println("Sky Flakes dispensed");
break;
}
dataFile.close();
Serial.println("Data logged to SD card.");
} else {
Serial.println("Error opening data.txt");
}
}
void SendMessage() {
sim.println("AT+CMGF=1");
delay(1000);
sim.println("AT+CMGS=\"+YOUR_NUMBER_HERE\"\r"); // Replace with your phone number
delay(1000);
sim.println("Low on supply, please resupply!");
delay(100);
sim.println((char)26);
delay(1000);
}
void SendMessageCriticalLevel() {
sim.println("AT+CMGF=1");
delay(1000);
sim.println("AT+CMGS=\"+YOUR_NUMBER_HERE\"\r"); // Replace with your phone number
delay(1000);
sim.println("Bottles storage in critical level!");
delay(100);
sim.println((char)26);
delay(1000);
}
void displayItemConfirmation(int itemIndex) {
if (useLCD2004) {
lcd2004.clear();
lcd2004.setCursor(0, 1);
switch (itemIndex) {
case 0:
lcd2004.print("Distilled Water = ");
lcd2004.print(PET_BOTTLE_COUNT_LIMIT);
break;
case 1:
lcd2004.print("Skyflakes = ");
lcd2004.print(PET_BOTTLE_COUNT_LIMIT + 2);
break;
case 2:
lcd2004.print("Instant Noodles = ");
lcd2004.print(PET_BOTTLE_COUNT_LIMIT + 5);
break;
}
lcd2004.setCursor(0, 2);
lcd2004.print("Continue or Go Back?");
}
}
void displayMessage(int index, const char* message) {
if (useLCD2004) {
lcd2004.clear();
lcd2004.setCursor(0, 0);
lcd2004.print(message);
}
}
void returnToSelectItem() {
lcd2004.clear();
lcd2004.setCursor(0, 0);
lcd2004.print("Select an item");
lcd2004.setCursor(0, 1);
lcd2004.print("1) Distilled Water");
lcd2004.setCursor(0, 2);
lcd2004.print("2) Skyflakes");
lcd2004.setCursor(0, 3);
lcd2004.print("3) Instant noodles");
}
void checkProximitySensor() {
// Check both slide switches (proximity sensors)
int sensorValue1 = digitalRead(proximitySensorPins[0]);
int sensorValue2 = digitalRead(proximitySensorPins[1]);
// Only count the bottle if both sensors are LOW (indicating both switches are on)
if (sensorValue1 == LOW && sensorValue2 == LOW) {
// Detected a PET bottle
PET_BottleCount++;
if (PET_BottleCount <= getPETBottleCountLimit(selectedItem)) {
lcd2004.setCursor(0, 2);
lcd2004.print("PET Bottle Count: ");
lcd2004.print(PET_BottleCount);
}
delay(1000); // Delay to prevent counting the same bottle multiple times
}
// Rotate Servo 4 if slide switch 1 is turned on
if (sensorValue1 == LOW) {
rotateServo4();
}
// Rotate Servo 5 if slide switch 2 is turned on
if (sensorValue2 == LOW) {
rotateServo5();
}
}
void rotateServo4() {
servo4.attach(servo4Pin);
servo4.write(180);
delay(1500); // Rotate for 1.5 seconds
servo4.write(0);
delay(500); // Hold the position before detaching
servo4.detach();
}
void rotateServo5() {
servo5.attach(servo5Pin);
servo5.write(180);
delay(1500); // Rotate for 1.5 seconds
servo5.write(0);
delay(500); // Hold the position before detaching
servo5.detach();
}
int getPETBottleCountLimit(int itemIndex) {
switch (itemIndex) {
case 0:
return PET_BOTTLE_COUNT_LIMIT;
case 1:
return PET_BOTTLE_COUNT_LIMIT + 2;
case 2:
return PET_BOTTLE_COUNT_LIMIT + 5;
default:
return PET_BOTTLE_COUNT_LIMIT;
}
}