Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Sujata
Created June 15, 2023

Automatic Delivery Collection Bot

An automated parcel collection robot

22
Automatic Delivery Collection Bot

Things used in this project

Story

Read more

Schematics

Circuit Diagram

Fritzing dIAGRAM

Fritzing file

Code

delivery_bot.ino

Arduino
Main Sketch to implement the parcel collection mechanism
/*
  Creator - Anindita Majumder
  Date -    08/06/23
  Platform - Arduino Cloud Web Editor
  Target -  DFRobot Firebeetle ESP32(Tested with WROOM ESP32 module as well)

  ///////////////////////////////////////////////////////////////////////////////////////////////////
  Sketch generated by the Arduino IoT Cloud Thing "Parcel_Collection_Bot"
  https://create.arduino.cc/cloud/things/206f9999-f994-484d-9233-x9519999e789 - changed for security

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String lcd_prompt;
  bool is_bot_awake;          
  bool is_delivery_guy_known;
  bool is_lid_open;
  bool user_servo_actuate;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"

// Include the required libraries
#include <Wire.h>             // I2C communication
#include <Servo.h>            // Servo motor control
#include <HuskyLensProtocol.h> // Husky Lens AI camera communication
#include <LiquidCrystal_I2C.h> // I2C LCD display

// Define the pins
#define START_BUTTON_PIN 2     // Start button pin
#define SERVO_PIN 5            // Servo motor pin

// Define the I2C address for the LCD display
#define LCD_ADDRESS 0x27

// Initialize objects
HUSKYLENS HuskyLens;
Servo servoMotor;
LiquidCrystal_I2C lcd(LCD_ADDRESS, 16, 2);

// Variables
bool startButtonPressed = false;
bool userResponseReceived = false;
char userResponse = ' ';

// Function prototypes
void initializeServo();
void initializeLCD();
void displayMessageOnLCD(const String& message);
void startButtonInterrupt();
void captureDeliveryAgentImage();
void processRecognizedDeliveryAgent(HUSKYLENSResult deliveryAgent);
void actuateServoMotor();
void sendImageToUser(const String& imagePath);
void sendSMSToUser(const String& message);
void checkUserResponse();
void handleUserResponse(const String& response);
void onLcdPromptChange();
void onUserServoActuateChange();

void setup() {
  // Initialize Serial communication
  Serial.begin(115200);

  // Initialize start button
  pinMode(START_BUTTON_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(START_BUTTON_PIN), startButtonInterrupt, FALLING);

  // Initialize servo motor
  initializeServo();

  // Initialize LCD display
  initializeLCD();
  displayMessageOnLCD("Please stand with your face in front of the camera to deliver the package");

  // Connect to Husky Lens camera
  HuskyLens.begin(&Wire);

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information youll get.
     The default is 0 (only errors).
     Maximum is 4
  */
  setDebugMessageLevel(2);                        //just for debugging - you can remove this without breaking the code
  ArduinoCloud.printDebugInfo();

}

void loop() {
  ArduinoCloud.update();

  if (startButtonPressed) {
    captureDeliveryAgentImage();
    startButtonPressed = false;
  }
  else {
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_30, 1); // send ESP32 to deep sleep until GPIO pin 30 connected to the start button goes high
  }
}

void initializeServo() {
  servoMotor.attach(SERVO_PIN);
  servoMotor.write(0);
}

void initializeLCD() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
}

void displayMessageOnLCD(const String& message) {
  lcd.clear();
  lcd.print(message);
}

void startButtonInterrupt() {
  startButtonPressed = true;
}

void captureDeliveryAgentImage() {
  displayMessageOnLCD("Capturing image...");

  // Deprecated function - HuskyLens automatically keeps requesting frames, a separate request need not be made
  // Capture image from Husky Lens camera
  //  HuskyLens.request();
  while (!HuskyLens.available());

  // Process the recognized delivery agent
  processRecognizedDeliveryAgent(HuskyLens.read());
}

void processRecognizedDeliveryAgent(HUSKYLENSResult deliveryAgent) {
  if (deliveryAgent.ID == 0) {
    // Send image to the user for verification
    displayMessageOnLCD("Sending image to user...");
    savePictureToSDCard();                              // save picture to the SD Card
    lcd_prompt = "Unknown delivery guy waiting. Message Y to approve";
    sendSMSToUser(lcd_prompt);                          // alert user on the Arduino Cloud Dashboard and via SMS
    delay(1000);
    //sendImageToUser(HuskyLens.readPicture());
    checkUserResponse();                                // wait for the user to reply either on the dashboard chat or through SMS
  } else {
    // Delivery agent recognized
    displayMessageOnLCD("Delivery agent: ID" + deliveryAgent.ID);
    actuateServoMotor();
  }
}

void actuateServoMotor() {
  displayMessageOnLCD("Opening the box...");
  servoMotor.write(90); // Adjust the angle as per your setup
  delay(5000); // Adjust the delay as per your setup
  servoMotor.write(0);

  // Deprecated - Only used for debugging
  // Send SMS to the user to control servo actuation
  //sendSMSToUser("Please enter Y to keep the box open or any other character to close the box.");
}

void sendSMSToUser(const String& message) {
  // Use IFTTT or other services to send SMS to the user
  // Implement your code here to send the SMS using the preferred service
  // You can use HTTP requests or libraries like SIM800L to send the SMS

  // Example using IFTTT SMS service:
  // Define your IFTTT webhook URL with the appropriate event name and key
  String url = "https://maker.ifttt.com/trigger/{event_name}/with/key/{your_ifttt_key}";

  // Replace {event_name} with the event name in your IFTTT applet
  // Replace {your_ifttt_key} with your IFTTT webhook key

  // Create the body of the HTTP request
  String body = "value1=" + message;

  // Send the HTTP POST request to trigger the IFTTT applet
  // You can use libraries like ESP8266HTTPClient or ArduinoHttpClient for the HTTP request
  // Below is an example using the built-in Arduino functions:
  WiFiClient client;
  if (client.connect("maker.ifttt.com", 80)) {
    client.println("POST " + url + " HTTP/1.1");
    client.println("Host: maker.ifttt.com");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(body.length());
    client.println();
    client.println(body);
  }
  
  // Wait for the server's response
  while (client.connected()) {
    if (client.available()) {
      String line = client.readStringUntil('\r');
      // Process the response if needed
    }
  }

  // Disconnect from the server
  client.stop();
}
void checkUserResponse() {
  // Check for user response via SMS using IFTTT or other services
  // Implement your code here to receive the user response

  // Example using IFTTT SMS service:
  // Define your IFTTT webhook URL with the appropriate event name and key
  String url = "https://maker.ifttt.com/trigger/{event_name}/with/key/{your_ifttt_key}";

  // Replace {event_name} with the event name in your IFTTT applet
  // Replace {your_ifttt_key} with your IFTTT webhook key

  // Create the body of the HTTP request
  String body = "";

  // Send the HTTP POST request to trigger the IFTTT applet and receive the response
  // You can use libraries like ESP8266HTTPClient or ArduinoHttpClient for the HTTP request
  // Below is an example using the built-in Arduino functions:
  WiFiClient client;
  if (client.connect("maker.ifttt.com", 80)) {
    client.println("POST " + url + " HTTP/1.1");
    client.println("Host: maker.ifttt.com");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(body.length());
    client.println();
    client.println(body);
  }

  // Wait for the server's response
  String response = "";
  while (client.connected()) {
    if (client.available()) {
      response += client.readStringUntil('\r');
    }
  }

  // Disconnect from the server
  client.stop();

  // Handle the user response
  handleUserResponse(response);
}

void handleUserResponse(const String& response) {
  // Extract the user response from the received data
  // Implement your code here to extract the response

  // Example: Extracting the user response from IFTTT SMS service
  if ((response.indexOf("\"Body\":\"Y\"") != -1) || lcd_prompt.startsWith('Y')) {
    // User response is "Y", actuate the servo motor
    actuateServoMotor();
  } else {
    // User response is not "Y", do not actuate the servo motor
    displayMessageOnLCD("User did not approve transaction! Call on +91983*******");
  }
}

/*
  Since LcdPrompt is READ_WRITE variable, onLcdPromptChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onLcdPromptChange()  {
  // Add your code here to act upon LcdPrompt change
  displayMessageOnLCD(lcd_prompt);                  //display whatever message user wants to convey to the delivery guy like a confidential OTP
  delay(2000);
  lcd_prompt = "";                                  //flush text buffer on Arduino Cloud chat
}

/*
  Since UserServoActuate is READ_WRITE variable, onUserServoActuateChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onUserServoActuateChange()  {
  // Add your code here to act upon UserServoActuate change
  while(user_servo_actuate){
    actuateServoMotor();
    delay(3000);
  }
}

arduino_secrets.h

C Header File
#define SECRET_SSID ""
#define SECRET_OPTIONAL_PASS ""
#define SECRET_DEVICE_KEY ""

sketch.json

JSON
{
  "cpu": {
    "fqbn": "esp32:esp32:firebeetle32",
    "name": "FireBeetle-ESP32",
    "type": "serial"
  },
  "secrets": [
    {
      "name": "SECRET_DEVICE_KEY",
      "value": ""
    },
    {
      "name": "SECRET_OPTIONAL_PASS",
      "value": ""
    },
    {
      "name": "SECRET_SSID",
      "value": ""
    }
  ],
  "included_libs": []
}

thingProperties.h

C Header File
// Code generated by Arduino IoT Cloud, DO NOT EDIT.

#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>

const char DEVICE_LOGIN_NAME[]  = "49272426-03a3-4506-619b-9ff9eb980eb3";

const char SSID[]               = SECRET_SSID;    // Network SSID (name)
const char PASS[]               = SECRET_OPTIONAL_PASS;    // Network password (use for WPA, or use as key for WEP)
const char DEVICE_KEY[]  = SECRET_DEVICE_KEY;    // Secret device password

void onLcdPromptChange();
void onIsBotAwakeChange();
void onIsDeliveryGuyKnownChange();
void onIsLidOpenChange();
void onUserServoActuateChange();

String lcd_prompt;
bool is_bot_awake;
bool is_delivery_guy_known;
bool is_lid_open;
bool user_servo_actuate;

void initProperties(){

  ArduinoCloud.setBoardId(DEVICE_LOGIN_NAME);
  ArduinoCloud.setSecretDeviceKey(DEVICE_KEY);
  ArduinoCloud.addProperty(lcd_prompt, READWRITE, ON_CHANGE, onLcdPromptChange);
  ArduinoCloud.addProperty(is_bot_awake, READWRITE, ON_CHANGE, onIsBotAwakeChange);
  ArduinoCloud.addProperty(is_delivery_guy_known, READWRITE, ON_CHANGE, onIsDeliveryGuyKnownChange);
  ArduinoCloud.addProperty(is_lid_open, READWRITE, ON_CHANGE, onIsLidOpenChange);
  ArduinoCloud.addProperty(user_servo_actuate, READWRITE, ON_CHANGE, onUserServoActuateChange);

}

WiFiConnectionHandler ArduinoIoTPreferredConnection(SSID, PASS);

Credits

Sujata

Sujata

5 projects • 3 followers
FPGA developer based in India worked on image processing based edge applications in healthcare and security. Die-hard IoTian home automator

Comments