Skip to Content
This is the Beta version of our new Learning Paths approach. Please email feedback.

Overview

The Loading circuit will be placed at the Seller location where the order items are loaded on to the delivery vehicle. It will have an ultrasonic sensor that will detect the arrival of the vehicle and trigger the camera to take a picture of the vehicle number plate for the ANPR service. The ultrasonic sensor will also detect when the vehicle leaves after loading is complete and capture the departure time data. All data will be sent to the Database and the Smart Contract.

Components
ComponentPurpose
ESP32 Cam ModuleProcessor and to capture the vehicle number plate image
HSR04 Ultrasonic SensorTo detect the arrival and departure of a vehicle
LM2596 Buck converterTo convert voltages as required for the components
LEDsTo indicate various actions and states
Circuit Diagram

web3_loading_circuit

Connections

HSR04 Ultrasonic Sensor

ESP32 Cam Module PinHSR04 Pin
IO2Echo Pin
IO16Trig Pin
VCCVin
GNDGND

LEDs

ESP32 Cam Module PinVehicle Detector LED Pin
14Anode (+)
GNDCathod (-)
ESP32 Cam Module PinImage Capture Indicator LED Pin
15Anode (+)
GNDCathod (-)

2X18650 Power Supply with LM2596 Buck converter

18650 PinLM2596 Pin
+(ve)IN+
-(ve)IN-

ESP32 Cam module with LM2596 Buck converter

ESP32 Cam module PinLM2596 Pin
VCCOUT+
GNDOUT-
Code

This code sends data to the AWS IoT platform which requires certificates and keys. These need to be generated for each account and cannot be reused. Instructions for getting these will be made available to subscribers.

/* Project: WEB3.0 distributed app Loading location circuit Project Description: This sketch posts image clicked by camera to AWS upon detection of object by IR sensor This sketch sendS the arrival time to AWS via MQTT Author: STEMVentor Educonsulting This code is copyrighted. Please do not reuse or share for any purpose other than for learning with subscribed STEMVentor programs. This code is for educational purposes only and is not for production use. */ // LIBRARIES // all the libraries (5) needed to connect and publish to AWS MQTT:- // includes all the credentials like certificates , wifi passwords , IoT endpoint and thing name #include "Secrets.h" // enbales ESP32 to connect to wifi #include <WiFiClientSecure.h> // enbales ESP32 to connect to wifi #include <WiFi.h> // MQTT library which helps publishing and subscribing to topics #include <PubSubClient.h> // JSON library to format the message being published #include <ArduinoJson.h> // to get real time in UNIX format #include <NTPClient.h> // libraries required to use the ESP32 cam // to initialise the ESP32 cam #include <esp_camera.h> // TO DISABLE BROWNER PROBLEMS (when low volatge is supplied to the chip , the chip shuts down , to prevent this shut down we disbale browner probl) #include "soc/soc.h" #include "soc/rtc_cntl_reg.h" // library required to do a HTTP post #include <HTTPClient.h> // #include <WiFiUdp.h> not sure if required , will remove after testing // GLOBAL VARIABLES char Time[500]; // variable to store JSON message to be published via MQTT unsigned long int loggedTime; // variable to store real time value float distanceCm; // to store vehicle distance // define ultrasonic sensor speed in cm/uS #define SOUND_SPEED 0.034 // Device IDs // string IDs are for the HTTP headers , it is not taking int for some reason const String microcontroller_id = "1"; const String camera_id = "11"; const int microcontroller_id_int = 1; const int ultrasonic_sensor_id = 12; // boolean check variables bool timeSent = false; bool imageCapturedSent = false; bool imageRecognised = false; // PIN DEFINITION #define echoPin 2 #define trigPin 16 #define vehicleIndicatorLED 14 #define imageCapturedSentLED 15 #define onBoardLED 33 // defining camera pins #define PWDN_GPIO_NUM 32 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 0 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 21 #define Y4_GPIO_NUM 19 #define Y3_GPIO_NUM 18 #define Y2_GPIO_NUM 5 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 #define FLASH_GPIO_NUM 4 #define FLASH_GPIO_NUM 4 // ledPin refers to ESP32-CAM GPIO 4 (flashlight) // Define the topic to which the data should be published #define AWS_IOT_PUBLISH_TOPIC "com.stemventor/sensor_data" /* INITIALIZE OBJECTS * Libraries usually follow an object-oriented approach that requires * an instance of the class to call its methods. */ WiFiClientSecure net; // wifi client PubSubClient client(net); // MQTT client WiFiUDP ntpUDP; // UDP client NTPClient timeClient(ntpUDP, "id.pool.ntp.org"); // NTPC client // Setup functions // function to setup wifi void Wifi_setup() { WiFi.mode(WIFI_STA); // station mode , where the device connects to an external wifi network WiFi.begin(WIFI_SSID, WIFI_PASSWORD); // gets the ssid and password from the secrets.h file Serial.println("Connecting to Wi-Fi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } } // function to setup AWS void AWS_setup() { // Configure WiFiClientSecure to use the AWS IoT device credentials net.setCACert(AWS_CERT_CA); net.setCertificate(AWS_CERT_CRT); net.setPrivateKey(AWS_CERT_PRIVATE); // Connect to the MQTT broker on the AWS endpoint we defined earlier client.setServer(AWS_IOT_ENDPOINT, 8883); // Create a message handler // client.setCallback(messageHandler); Serial.println("Connecting to AWS IoT"); while (!client.connected()) { Serial.print("."); if (client.connect(THINGNAME)) { Serial.println("Connected to AWS IoT"); // subscribe over here } else { Serial.println("AWS IoT Connection Failed! Retrying..."); int errorCode = client.state(); Serial.print("Error code: "); Serial.println(errorCode); delay(1000); } } } // function to setup NTPC to get real time value void NTPC_setup() { timeClient.begin(); timeClient.setTimeOffset(0); } // function to setup camera (ESP32 Cam module OV2640) void Camera_setup() { pinMode(FLASH_GPIO_NUM, OUTPUT); // defining pinmode as output for the flash on board pinMode(33, OUTPUT); // defining pinmode as output for the LED on the esp32 cam board , this is being used an indication that the camera has been initialised properly // Turn-off the 'brownout detector' WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // OV2640 camera module camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.pixel_format = PIXFORMAT_JPEG; delay(500); config.frame_size = FRAMESIZE_SVGA; // this the resolution , you can change the value according to your need config.jpeg_quality = 15; // quality parameter config.fb_count = 1; // Camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); // ESP.restart(); } else { Serial.println("camera inint succesfull"); digitalWrite(33, LOW); // switch on the indication light on board , its a active low light. } } // function to setup ultrasonic sensor void HCSR04_setup() { // Define the pinmode pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output pinMode(echoPin, INPUT); // Sets the echoPin as an Input } // function to setup indicator LEDS void LEDSetup() { pinMode(vehicleIndicatorLED, OUTPUT); pinMode(onBoardLED, OUTPUT); pinMode(imageCapturedSentLED, OUTPUT); digitalWrite(vehicleIndicatorLED, LOW); digitalWrite(imageCapturedSentLED, LOW); digitalWrite(onBoardLED, LOW); } // loop fucntions // function to read value of ultrasonic sensor and store in global variable void readHCSR04() { digitalWrite(trigPin, LOW); delayMicroseconds(2); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Reads the echoPin, returns the ultrasonic sensor wave travel time in microseconds long duration = pulseIn(echoPin, HIGH); // Calculate the distance distanceCm = duration * SOUND_SPEED / 2; } // function to note down value of actual time when IR sensor detects object void logTime() { timeClient.update(); // Get current Unix timestamp loggedTime = timeClient.getEpochTime(); Serial.print("logged time : "); Serial.println(loggedTime); } // function to format the JSON message in the required structure void JSON_formatter() { JsonDocument doc; doc["timestamp"] = timeClient.getEpochTime(); delay(300); doc["microcontroller_id"] = microcontroller_id_int; JsonArray sensor_data = doc["sensor_data"].to<JsonArray>(); JsonObject sensor_data_0 = sensor_data.add<JsonObject>(); sensor_data_0["sensor_id"] = ultrasonic_sensor_id; JsonObject sensor_data_0_parameters = sensor_data_0["parameters"].to<JsonObject>(); sensor_data_0_parameters["time"] = loggedTime; doc.shrinkToFit(); // Serial.println(doc.overflowed()); //to check if the JSON is not more than the initialised JSON variable serializeJson(doc, Time); Serial.println(Time); } // function to publish the json to MQTT topic void publishMessage(char message[500]) { bool publish_check = false; // variable to indicate if MQTT publsih has happened succesfully or no int publish_counter = 0; // variable to store number of times MQTT publish has been tried while (publish_check == false) { if (!client.publish(AWS_IOT_PUBLISH_TOPIC, message)) { Serial.println("Failed to publish message 1"); Serial.println("Checking connection with AWS IoT..."); checkAWS(); delay(1000); if (publish_counter > 3) // if publish is not successfull for 3 times then restart the ESP. { Serial.println("Restarting the ESP"); ESP.restart(); } } else { Serial.println("Message published successfully"); publish_check = true; } publish_counter++; } } // function to click and send photo void Click_SendPhoto() { bool post_check = false; // variable to indicate if HTTP post has happened succesfully or no int post_counter = 0; // variable to store number of times HTTP post has been tried if (WiFi.status() == WL_CONNECTED) { digitalWrite(FLASH_GPIO_NUM, HIGH); // switch on flash delay(500); Serial.println("Taking picture..."); camera_fb_t *fb = NULL; // empty the variable esp_err_t res = ESP_OK; fb = esp_camera_fb_get(); // click photo , the photo gets stored as a pixel data buffer if (!fb) { Serial.println("Camera capture failed"); // return ESP_FAIL; } else { Serial.println("picture taken"); } digitalWrite(FLASH_GPIO_NUM, LOW); // swich of the flash light . also an indication that the photo clicking part is over HTTPClient http; // define a http client http.begin("https://gewomgsnm0.execute-api.ap-south-1.amazonaws.com/beta/"); // aws api link where the image will be posted http.setTimeout(20000); // increase or decrease timeout depending how strong the wifi connectivity is , its the time to establish a connection with the link http.addHeader("Content-Type", "image/jpg"); // header files http.addHeader("microcontrollerID", microcontroller_id); http.addHeader("sensor_id", camera_id); while (post_check == false) // keep on posting the image to the api till it receives and responds properly , this is done because sometimes the server is busy. { int httpCode = http.POST(fb->buf, fb->len); // post the buffer and its length ,"->" is the pointer post_counter++; if (httpCode == HTTP_CODE_OK) // once http code is 200 , which means post was successfull read and print the return which it got. { post_check = true; // successfully posted String payload = http.getString(); Serial.println(payload); // Create a StaticJsonDocument StaticJsonDocument<200> doc3; // Deserialize the JSON DeserializationError error = deserializeJson(doc3, payload); // Extract the value const char *value = doc3["sensor_data"][0]["parameters"][0]["value"]; Serial.print("Value: "); Serial.println(value); // Check if the value is "null" if (strcmp(value, "null") == 0) { Serial.println("The value is null"); imageRecognised = false; delay(5000); // wait for 5 seconds for the camera to stop lagging } else { Serial.println("The value is not null"); imageRecognised = true; } } else { Serial.print("HTTP post not succesful , code : "); Serial.println(httpCode); checkWIFI(); // check wifi if (post_counter > 3) { Serial.println("Restarting the ESP"); ESP.restart(); } else { Serial.println("retrying posting the photo. "); } } } http.end(); // end the connection esp_camera_fb_return(fb); // Release the frame buffer } } void checkWIFI() { if (WiFi.status() != WL_CONNECTED) { Serial.println("Wi-Fi not connected, reconnecting..."); Wifi_setup(); } } void checkAWS() { if (!client.connected()) { Serial.println("AWS IoT not connected, reconnecting..."); AWS_setup(); } } // Main setup function void setup() { Serial.begin(115200); LEDSetup(); Wifi_setup(); AWS_setup(); HCSR04_setup(); Camera_setup(); NTPC_setup(); Serial.println("All setup done!"); digitalWrite(onBoardLED, HIGH); } // Main loop function void loop() { // the conidtions have been applied such it first sends the time as soon it detects a vehicle and them clicks and sends the number plate image. // after thats done it checks if any load has been kept on the weighing scale and sends that once. // the code stops after all the 3 paramters have been sent once checkWIFI(); // check wifi at the start of every loop readHCSR04(); if (distanceCm < 25) // the value 25 can be changed after testing , this indicates a vehcile has been detected { digitalWrite(vehicleIndicatorLED, HIGH); if (timeSent == false) { logTime(); delay(300); JSON_formatter(); delay(1000); publishMessage(Time); timeSent = true; delay(5000); } if (imageCapturedSent == false && timeSent == true) { while (imageRecognised == false) // will resend image if there is null value returned { Click_SendPhoto(); } imageCapturedSent = true; digitalWrite(imageCapturedSentLED, HIGH); } // Monitor free heap memory Serial.print("Free heap: "); Serial.println(ESP.getFreeHeap()); // delay(10000); //kept for testing / debugging } else // this means no vehicle has been detected nearby or the vehicle has left { digitalWrite(vehicleIndicatorLED, LOW); digitalWrite(imageCapturedSentLED, LOW); timeSent = false; imageCapturedSent = false; imageRecognised = false; } }