Why I Chose the Project: I chose to build the smart IoT mailbox to address situations where accessing the mailbox is inconvenient, whether due to distance or simply the desire to avoid unnecessary trips.
Purpose: The purpose of developing the smart IoT mailbox is to enhance convenience by providing remote access to mailbox notifications and contents, thereby reducing the need for physical trips to check the mailbox.
Insights and Data Utilization: The basic concept revolves around the detection of mail insertion into a mailbox and subsequently notifying the user through easily accessible devices. By doing this we are enabling timely and convenient alerts to be relayed to users via commonly used communication platforms and devices.
SetupComputer (MacOS) Setup for Programming the Raspberry Pi Pico W
Chosen IDE: Thonny
How the Code is Uploaded: Using Thonny IDE to write and upload code to the Raspberry Pi Pico W.
Computer Setup:
Install Thonny IDE:
- Download and install Thonny IDE from the official website.
- Install Thonny IDE: Download and install Thonny IDE from the official website.
Install Python:
- macOS usually comes with Python pre-installed. However, ensure you have Python 3 installed. You can download it from the official Python website.
- Make sure Python is added to your PATH.
- Install Python: macOS usually comes with Python pre-installed. However, ensure you have Python 3 installed. You can download it from the official Python website.Make sure Python is added to your PATH.
Flash MicroPython Firmware onto the Raspberry Pi Pico W:
- Download the MicroPython firmware (.uf2 file) from the official Raspberry Pi website.
- Connect the Pico W to your computer while holding the BOOTSEL button.
- Drag and drop the downloaded.uf2 file into the RPI-RP2 drive that appears.
- Flash MicroPython Firmware onto the Raspberry Pi Pico W:Download the MicroPython firmware (.uf2 file) from the official Raspberry Pi website.Connect the Pico W to your computer while holding the BOOTSEL button.Drag and drop the downloaded.uf2 file into the RPI-RP2 drive that appears.
Set Up Thonny for Pico W Development:
- Open Thonny IDE.
- Go to
Tools
->Options
(on macOS, it might be underThonny
->Preferences
). - Select
Interpreter
and set it to MicroPython (Generic) or Raspberry Pi Pico (depending on Thonny's options). - Ensure the correct serial port is selected in the bottom-right corner (usually
/dev/cu.usbmodem*
on macOS). - Set Up Thonny for Pico W Development:Open Thonny IDE.Go to
Tools
->Options
(on macOS, it might be underThonny
->Preferences
).SelectInterpreter
and set it to MicroPython (Generic) or Raspberry Pi Pico (depending on Thonny's options).Ensure the correct serial port is selected in the bottom-right corner (usually/dev/cu.usbmodem*
on macOS).
Connect the Raspberry Pi Pico W:
- Connect your Raspberry Pi Pico W to your computer via USB.
- Connect the Raspberry Pi Pico W:Connect your Raspberry Pi Pico W to your computer via USB.
Writing and Uploading Code:
- In Thonny IDE, create a new file (
File
->New
orCmd+N
). - Write your MicroPython code in the editor.
- Click on the
Run
button to execute the code on the Raspberry Pi Pico W.
This is how every mentioned component was put together.
Code explained:Importing Libraries
import machine
import time
import network
import urequests as requests
import ujson as json
import os
from BlynkLib import Blynk
These lines import the necessary libraries:
- machine
: For controlling the hardware pins.
- time
: For time-related functions.
- network
: For Wi-Fi connectivity.
- urequests
: For making HTTP requests.
- ujson
: For handling JSON data.
- os
: For file operations.
- BlynkLib
: For interfacing with the Blynk platform.
Defining Constant
SSID = '***'
PASSWORD = '***'
TELEGRAM_BOT_TOKEN = '***'
TELEGRAM_CHAT_ID = '***'
BLYNK_AUTH = '***'
RED_LED_PIN = 16
GREEN_LED_PIN = 17
BUTTON_PIN = 18
IR_SENSOR_PIN = 1
DEBOUNCE_DELAY = 0.05
MEASUREMENT_INTERVAL = 0.05
COOLDOWN_PERIOD = 1
DATA_FILE = 'mail_log.json'
These constants store various settings:
- Wi-Fi credentials (SSID
, PASSWORD
).
- Telegram bot details (TELEGRAM_BOT_TOKEN
, TELEGRAM_CHAT_ID
).
- Blynk authentication token (BLYNK_AUTH
).
- GPIO pin numbers for LEDs, button, and IR sensor.
- Timing settings for debounce delay, measurement interval, and cooldown period.
- Filename for storing mail logs (DATA_FILE
).
Connecting to Wi-Fi
def connect_wifi(ssid, password):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
max_attempts = 10
attempt = 0
while not wlan.isconnected() and attempt < max_attempts:
attempt += 1
print('Attempting to connect to Wi-Fi...')
time.sleep(1)
if wlan.isconnected():
print('Connected to Wi-Fi')
return True
else:
print('Failed to connect to Wi-Fi')
return False
if not connect_wifi(SSID, PASSWORD):
raise RuntimeError("Failed to connect to Wi-Fi")
This function connect_wifi
tries to connect to the specified Wi-Fi network. It makes several attempts (up to 10) and prints the connection status. If the connection is successful, it returns True
; otherwise, it returns False
and raises an error.
Initializing Pins
red_led = machine.Pin(RED_LED_PIN, machine.Pin.OUT)
green_led = machine.Pin(GREEN_LED_PIN, machine.Pin.OUT)
button = machine.Pin(BUTTON_PIN, machine.Pin.IN, machine.Pin.PULL_UP)
ir_sensor = machine.Pin(IR_SENSOR_PIN, machine.Pin.IN)
These lines initialize the GPIO pins:
- red_led
and `green_led` are configured as output pins to control the LEDs.
- button
is configured as an input pin with an internal pull-up resistor.
- ir_sensor
is configured as an input pin to read the IR sensor value.
Initializing Blynk
blynk = Blynk(BLYNK_AUTH)
This line initializes the Blynk library with the provided authentication token.
Sending Messages to Telegram
def send_to_telegram(message):
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
headers = {'Content-Type': 'application/json'}
payload = {
'chat_id': TELEGRAM_CHAT_ID,
'text': message
}
try:
response = requests.post(url, headers=headers, data=json.dumps(payload))
if response.status_code == 200:
print('Message sent to Telegram successfully')
else:
print(f'Failed to send message to Telegram. Status code: {response.status_code}')
except Exception as e:
print(f'Exception while sending message to Telegram: {e}')
This function send_to_telegram
sends a message to the specified Telegram chat. It constructs a URL with the bot token and prepares the message payload. It then makes a POST request to the Telegram API and prints whether the message was sent successfully or if there was an error.
Handling JSON Files
def init_json():
if not DATA_FILE in os.listdir():
with open(DATA_FILE, 'w') as f:
json.dump([], f)
def log_to_json(timestamp):
with open(DATA_FILE, 'r+') as f:
data = json.load(f)
data.append(timestamp)
f.seek(0)
json.dump(data, f)
def retrieve_data():
if DATA_FILE in os.listdir():
with open(DATA_FILE, 'r') as f:
data = json.load(f)
return data
else:
return []
These functions handle the JSON file:
- init_json
checks if the JSON file exists, and if not, creates it with an empty list.
- log_to_json
adds a new timestamp to the JSON log.
- retrieve_data
reads and returns the data from the JSON file.
Initializing the JSON File
init_json()
This line calls the init_json
function to ensure the JSON file is ready for use.
Variables for Mail Detection
previous_mail_status = False
last_mail_time = 0
mail_count = 0
These variables keep track of the mail detection status:
- previous_mail_status
: The previous state of mail detection (True if mail was detected).
- last_mail_time
: The last time mail was detected.
- mail_count
: The count of detected mails.
Updating LED Status
def update_leds(mail_detected):
if mail_detected:
red_led.value(0) # Turn off red LED
green_led.value(1) # Turn on green LED
else:
red_led.value(1) # Turn on red LED
green_led.value(0) # Turn off green LED
This function update_leds
updates the LED status based on whether mail is detected:
- If mail is detected, the green LED is turned on and the red LED is turned off.
- If no mail is detected, the red LED is turned on and the green LED is turned off.
Getting Mail Status with Debouncing
def get_mail_status():
mail_detected = ir_sensor.value() == 0 # Initial read
time.sleep(DEBOUNCE_DELAY) # Wait for debounce delay
return mail_detected and (ir_sensor.value() == 0) # Confirm detection
This function get_mail_status
checks the IR sensor value to determine if mail is detected. It reads the sensor value, waits for a short debounce delay, and confirms the detection by reading the sensor value again.
Resetting the Mail Counter
def reset_mail_count(pin):
global mail_count
mail_count = 0
blynk.virtual_write(4, mail_count) # Update mail count on Blynk (V4)
print("Mail counter reset.")
button.irq(trigger=machine.Pin.IRQ_RISING, handler=reset_mail_count)
This function reset_mail_count
resets the mail counter to zero when the button is pressed. An interrupt is attached to the button to call this function when the button is released.
Getting Current Time from API
def get_current_time():
try:
response = requests.get('http://worldtimeapi.org/api/ip')
if response.status_code == 200:
data = response.json()
return data['datetime']
else:
print('Failed to get time from API')
return None
except Exception as e:
print('Exception while getting time:', e)
return None
This function get_current_time
fetches the current time from an online API. It makes a GET request to the World Time API and returns the current datetime if successful. If there's an error, it returns None
.
Logging Mail Detection
def log_mail():
global mail_count
timestamp = get_current_time()
if timestamp:
print(f"Mail detected at {timestamp}")
send_to_telegram(f"Mail detected at {timestamp}")
log_to_json(timestamp)
mail_count += 1
blynk.virtual_write(4, mail_count) # Update mail count on Blynk (V4)
blynk.virtual_write(3, f"New mail detected: {mail_count} at {timestamp}") # Use virtual pin to indicate new mail (V3)
This function log_mail
logs the detection of mail:
- It fetches the current timestamp.
- Sends a notification to Telegram.
- Logs the timestamp to the JSON file.
- Increments the mail count and updates it on Blynk.
Sending Mail Count to Blynk
def send_mail_count():
blynk.virtual_write(5, mail_count) # Update mail count on Blynk (V5)
print(f"Mail count sent to Blynk: {mail_count}")
This function send_mail_count
periodically sends the current mail count to Blynk.
Main Loop
while True:
try:
blynk.run() # Run Blynk to keep connection alive
mail_detected = get_mail_status() # Get mail status from IR sensor
current_time = time.time()
if mail_detected and not previous_mail_status:
print(f"Mail detected at {current_time}")
if current_time - last_mail_time >= COOLDOWN_PERIOD:
log_mail()
last_mail_time = current_time
else:
print(f"Cooldown period active. Time since last mail: {current_time - last_mail_time} seconds")
update_leds(mail_detected)
previous_mail_status = mail_detected
# Send mail count to Blynk every minute
if int(current_time) % 60 == 0:
send_mail_count()
time.sleep(MEASUREMENT_INTERVAL)
except Exception as e:
print('Exception in main loop:', e)
time.sleep(1) # Delay before retrying
This is the main loop of the program:
- It keeps the Blynk connection alive by calling blynk.run
.
- It checks the IR sensor to detect mail.
- If mail is detected and the cooldown period has passed, it logs the mail.
- It updates the LED status based on the mail detection.
- It sends the mail count to Blynk every minute.
- It includes error handling to catch and print exceptions, with a delay before retrying.
In summary, this code continuously monitors an IR sensor to detect mail, logs the detections, sends notifications via Telegram, and updates a dashboard on Blynk. LEDs provide a visual indication of mail status, and a button allows the user to reset the mail count. The program also handles Wi-Fi connectivity and timing functions.
A library (blynklib) that needs to be installed on the microcontroller can be found here:
https://pypi.org/project/blynklib/
Whole Code:Provided at the end as an attachment.
Data Visualisation (Blynk IoT)Blynk IoT is an Internet of Things (IoT) platform designed to connect and manage devices, visualize data, and control hardware remotely. It allows developers and makers to quickly build IoT applications by providing an easy-to-use mobile app and a cloud service. With Blynk, one can:
1. Control Hardware Remotely: Blynk supports a wide range of hardware platforms like Arduino, Raspberry Pi, and ESP8266/ESP32.
2. Display Sensor Data: Sensor data can be visualized in real-time on a smartphone or web dashboard.
3. Automate Tasks: Automation rules can be created to trigger actions based on sensor readings or time schedules.
4. Manage Devices: Multiple devices can be monitored and controlled from a single interface.
How It Is Used in the Project
In the project, Blynk IoT is used to remotely monitor and manage the mail detection system on the Raspberry Pi Pico W. Here is a breakdown of how Blynk is integrated into the project:
1. Initialization:
- Blynk is initialized with a unique authentication token, which links the device to the Blynk account:
BLYNK_AUTH = '***'
blynk = BlynkLib.Blynk(BLYNK_AUTH)
2. Mail Count Display:
- The mail count is updated on the Blynk app. When new mail is detected, the count is incremented and sent to the Blynk server to be displayed on the app:
def log_mail():
global mail_count
timestamp = get_current_time()
if timestamp:
mail_count += 1
print(f"Mail Count: {mail_count}, Time: {timestamp}")
blynk.virtual_write(4, mail_count) # Update mail count on Blynk (V4)
blynk.virtual_write(3, f"New mail detected: {mail_count} at {timestamp}") # Notify on Blynk (V3)
- `blynk.virtual_write(4, mail_count)`: Sends the mail count to Virtual Pin 4 on the Blynk app.
- `blynk.virtual_write(3, f"New mail detected: {mail_count} at {timestamp}")`: Sends a notification with the mail count and timestamp to Virtual Pin 3 on the Blynk app.
3. Mail Counter Reset:
- When the reset button is pressed, the mail count is reset, and this new count is sent to the Blynk app:
def reset_mail_count(pin):
global mail_count
mail_count = 0
blynk.virtual_write(4, mail_count) # Update mail count on Blynk (V4)
print("Mail counter reset.")
4. Running Blynk:
- In the main loop, the Blynk process is continuously run to keep the connection alive and handle any updates:
while True:
blynk.run() # Run Blynk to keep connection alive
Summary
Blynk IoT is used to monitor and control the mail detection system remotely. By integrating Blynk with the Raspberry Pi Pico W, it is possible to:
- Monitor Mail Status: View the number of mails detected and the time they were detected on a smartphone or web dashboard.
- Reset the Mail Counter: Reset the count remotely using the Blynk app.
- Receive Notifications: Get real-time notifications about new mail detected with timestamps.
Notifications via Telegram in this application are important for informing users about detected mail events in real-time. The integration with Telegram is done through a function send_to_telegram()
that constructs an API request to the Telegram bot. This function utilizes the requests
library to send a POST
request with JSON
payload containing the chat ID (TELEGRAM_CHAT_ID
) and the message to be sent. Here's a simplified example of how notifications are sent:
def send_to_telegram(message):
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
headers = {'Content-Type': 'application/json'}
payload = {
'chat_id': TELEGRAM_CHAT_ID,
'text': message
}
try:
response = requests.post(url, headers=headers, data=json.dumps(payload))
if response.status_code == 200:
print('Message sent to Telegram successfully')
else:
print(f'Failed to send message to Telegram. Status code: {response.status_code}')
except Exception as e:
print(f'Exception while sending message to Telegram: {e}')
In the main application loop, when mail is detected (mail_detected
is True
), a notification is triggered with the current timestamp via send_to_telegram()
. This ensures that users are promptly notified of each mail event. This integration of Telegram notifications enhances user convenience by delivering immediate updates wherever they are, ensuring timely response to incoming mail.
Data storage in this application is handled through both Blynk's capabilities and local file storage. Blynk allows for integration and visualization of data from connected devices. Variables such as mail_count
are updated and displayed on Blynk dashboards using virtual pins (blynk.virtual_write()
). For instance, send_mail_count()
sends the current mail count to Blynk's virtual pin V5 periodically. This enables users to monitor mail activity remotely via the Blynk app or web dashboard. Additionally, local data storage utilizes a JSON file (mail_log.json
) where timestamps of detected mail events are logged (log_to_json(timestamp)
). This local storage acts as a historical record of mail detections, providing backup data and enabling future analysis or reporting. By utilizing both Blynk's cloud-based capabilities and local file storage, the application ensures robust data management, combining real-time monitoring with persistent storage for comprehensive usage insights and reliability.
The data is transmitted to the internet using HTTP requests and the MQTT protocol via Wi-Fi. The package format for HTTP requests, such as sending notifications to Telegram, includes JSON payloads containing the message details. For the Blynk platform, data is sent using Blynk’s virtual write method, which encapsulates the data in a format recognized by the Blynk server.
Steps to transmit data:
1. Wi-Fi Connection: The device connects to a Wi-Fi network using the SSID and password provided.
def connect_wifi(ssid, password):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
max_attempts = 10
attempt = 0
while not wlan.isconnected() and attempt < max_attempts:
attempt += 1
print('Attempting to connect to Wi-Fi...')
time.sleep(1)
if wlan.isconnected():
print('Connected to Wi-Fi')
return True
else:
print('Failed to connect to Wi-Fi')
return False
2. Sending Data to Telegram:
def send_to_telegram(message):
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
headers = {'Content-Type': 'application/json'}
payload = {
'chat_id': TELEGRAM_CHAT_ID,
'text': message
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
3. Updating Blynk:
blynk.virtual_write(4, mail_count) # Update mail count on Blynk (V4)
blynk.virtual_write(3, f"New mail detected: {mail_count} at {timestamp}") # Use virtual pin to indicate new mail (V3)
- Data is sent every time mail is detected, with a cooldown period of 1 second between detections to avoid repeated triggers.
- Additionally, the mail count is sent to Blynk every minute.
Wireless and Transport Protocols:
- Wireless Protocol: Wi-Fi is used for its ubiquity and ease of integration with IoT devices.
- Transport Protocols:
- HTTP: Used for sending messages to Telegram.
- MQTT: Used for communicating with the Blynk server.
Design Choices:
- Wi-Fi: Chosen for its wide availability and sufficient range for typical mailbox installations.
- HTTP and MQTT:
- HTTP provides a straightforward way to integrate with web services like Telegram.
- MQTT is lightweight and efficient for IoT applications, making it suitable for updating Blynk dashboards.
- Impact on Range and Battery Consumption: Wi-Fi ensures reliable connectivity within a typical home range, but it consumes more power compared to protocols like LoRa. The choice balances ease of use and power consumption, considering the device's likely access to a stable power source.
Dashboard Construction:
The dashboard is built using the Blynk platform, providing a user-friendly interface to display mail counts and notifications.
- Data Presentation:
- Mail Count: Displayed on a virtual pin (V4).
- New Mail Notification: Displayed on a virtual pin (V3).
- Database and Data Preservation:
- Data Storage: Data is logged locally in a JSON file (`mail_log.json`).
- Data Preservation Duration: Data in the JSON file is preserved as long as the file exists, providing a historical log of mail detections.
- Visual Example:
- Blynk Dashboard:
- Telegram notifications:
Data Automation and Triggers:
- Data Logging: Every mail detection is logged with a timestamp.
- Triggers: The system automatically sends updates to Telegram and Blynk upon detecting new mail.
Choice of Database:
- JSON File: Chosen for its simplicity and ease of use with MicroPython. It provides a lightweight solution for logging events without requiring a more complex database setup.
Final Results:
- The smart IoT mailbox successfully detects mail, logs events, and sends notifications to users via Telegram and Blynk.
Key Achievements:
- Reliable mail detection with IR sensor.
- Real-time notifications via Telegram.
- Convenient mail count display on Blynk dashboard.
Reflections and Improvements:
- Project Success: The project met its primary objectives of providing timely and convenient mail notifications.
Potential Improvements:
- Battery Optimisation: Explore lower-power wireless protocols like LoRa for battery-operated versions.
- Enhanced Range: Implement signal amplification or mesh networking to extend the Wi-Fi range.
- Additional Features: Add more sensors for security purposes (e.g., camera for mail theft detection).
Visual Presentation:
Comments