# IoT Project Tutorial: Intrusion Detection
**Name:** Ibrahim Iqbal
**Student ID**: si222my
## 2. Short Project Description
This project involves building a smart device using a Raspberry Pi Pico W, a sound sensor, and a light sensor to monitor environmental conditions. The device connects to a local Wi-Fi network and sends real-time sound and light level data to a local server.
**Estimated Project Time:** 8 Hours
## 3. Objective
**Why I chose this project:** This project was chosen with the primary goal of creating a simple, yet effective, intruder detection system. A significant aspect of this choice was the availability of various electronic components I had lying around. I aimed to utilize these existing parts, such as the sound sensor, and light sensor, and creatively adapt them to fit the specific requirements of an intrusion detection system.
**Purpose of the device:** The device serves as an intruder detector. By continuously monitoring sound and light levels, it aims to identify sudden changes that could indicate the presence of an unauthorized person or significant disturbance within a designated space.
**Expected insights from the data:** The collected data is expected to provide real-time insights into potential intrusions. Spikes in sound levels (e.g., footsteps, voices, breaking objects) or changes in light levels (e.g., lights being turned on/off, shadows from movement) can serve as indicators. This data could be used to trigger alerts, log events for later review, or even inform more complex security systems.
## 4. List of Material
Here is a list of the materials used in this project:
| **Component** | **Description** | **Where Purchased & Cost** |
| :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------- | :--------------------- |
| **Raspberry Pi Pico W** | This is the microcontroller board with built-in Wi-Fi capability, serving as the brain of the IoT device. It runs MicroPython code to read sensor data and communicate with the server. | AMAZON 200 SEK |
| **KY-037 High-Sensitivity Sound Detection Module** | This sensor detects sound levels in the environment. Its analog output (AO) provides a voltage proportional to the sound intensity. | AMAZON ~30 SEK |
| **LDR 5516 Photoresistor** | A light-dependent resistor whose resistance changes with the intensity of light. It's used in a voltage divider circuit to measure ambient light levels. | AMAZON ~20 SEK |
| **10K Resistor** | Used in conjunction with the LDR to form a voltage divider circuit, allowing the Raspberry Pi Pico W's ADC to read the light level as a voltage. | AMAZON ~10 SEK |
| **Multiple M-M Dupont Cables** | Used for connecting the various components (sensors, resistors) to the Raspberry Pi Pico W's GPIO pins. | AMAZON ~20 SEK |
## 5. Computer Setup
**Chosen IDE:** Thonny IDE
**Code Upload Workflow:** The primary workflow involved writing the MicroPython code directly in Thonny IDE and then pressing the "Play" button (Run current script) to execute and upload the code to the Raspberry Pi Pico W. Thonny handles the communication and flashing process seamlessly.
**Necessary Computer Setup Steps:**
* Installation of MicroPython firmware on the Raspberry Pi Pico W.
* Installation of Thonny IDE.
* Installation of the Rust toolchain (using `rustup`) for developing the backend server.
* Installation of SQLite development libraries on your operating system, which may be required for Rust's SQLite bindings to compile correctly.
* Any specific USB drivers for the Pico W if your operating system does not automatically recognize it.
## 6. Putting Everything Together
The electronic components are connected as follows:
* **KY-037 Sound Sensor:**
* VCC pin to 3.3V on Raspberry Pi Pico W.
* GND pin to GND on Raspberry Pi Pico W.
* AO (Analog Output) pin to GP26 (ADC0) on Raspberry Pi Pico W.
* **LDR 5516 Photoresistor and 10K Resistor (Voltage Divider):**
* One leg of the LDR to 3.3V on Raspberry Pi Pico W.
* The other leg of the LDR connected to one leg of the 10K resistor. This junction point is connected to GP28 (ADC2) on Raspberry Pi Pico W.
* The other leg of the 10K resistor to GND on Raspberry Pi Pico W.
* **Raspberry Pi Pico W LED:** The onboard LED is controlled by the code for status indication.
**Electrical Considerations:**
The KY-037 requires 3.3V to 5V, so we don't need to do anyhting more, we can just connect it directly.
The LDR is integrated into a voltage divider circuit with a 10K resistor. This configuration converts the LDR's varying resistance (due to light changes) into a measurable voltage that the Raspberry Pi Pico W's Analog-to-Digital Converter (ADC) can read. The LDR did not come with any documentation, so the optimal resistor value had to be determined through experimentation; the 10K resistor worked best, ensuring the output voltage range falls within the Pico W's 0-3.3V ADC input range, providing optimal sensitivity across expected light conditions and helping to limit current.
The voltage output ($V_{out}$) from a voltage divider is calculated using the formula:
$$V_{out} = V_{in} \times \frac{R_2}{R_1 + R_2}$$
Where:
* $V_{in}$ is the input voltage (3.3V from the Pico W).
* $R_1$ is the resistance of the LDR (which varies with light).
* $R_2$ is the fixed 10K Ohm resistor.
For example, if the LDR's resistance ($R_1$) is 50K Ohm (in low light) and $R_2$ is 10K Ohm:
$$V_{out} = 3.3V \times \frac{10000 \Omega}{50000 \Omega + 10000 \Omega} = 3.3V \times \frac{10000}{60000} = 3.3V \times \frac{1}{6} \approx 0.55V$$
If the LDR's resistance ($R_1$) is 1K Ohm (in bright light) and $R_2$ is 10K Ohm:
$$V_{out} = 3.3V \times \frac{10000 \Omega}{1000 \Omega + 10000 \Omega} = 3.3V \times \frac{10000}{11000} = 3.3V \times \frac{10}{11} \approx 3.00V$$
These examples illustrate how the output voltage changes significantly with the LDR's resistance, allowing the Pico W to detect varying light levels.
**Development vs. Production Setup:**
This setup is primarily for development and prototyping. It could be adapted for production by enclosing it in a cardboard box with a proper cutout for the LDR to allow light sensing, optimizing power consumption for battery operation, and deploying the Rust backend server on a cloud platform to ensure continuous availability and remote access.
## 7. Platform
The device communicates with a local server running on `192.168.10.174:3000`.
* **Platform Description and Functionality:** The backend server is implemented in **Rust** and uses **SQLite** for data storage. It also serves the frontend, which is a single HTML page. This server receives sensor data (sound and light levels) via HTTP POST requests from the Raspberry Pi Pico W, stores it in the SQLite database, and presents it through the served HTML page.
* **Reason for Platform Choice:** Choosing a local server implemented in Rust with SQLite offered significant flexibility and control over the entire application stack. This approach allowed for complete customization of both the backend logic and the frontend presentation without being constrained by the specific services or pricing models of cloud IoT platforms like AWS IoT Core or Adafruit IO. It provided a cost-effective solution for a personal project, as there are no recurring subscription fees or usage-based charges typically associated with cloud services. It also offered immediate feedback during development, simplifying debugging and iteration within a controlled environment.
* **Local or Cloud:** This platform is a local installation.
* **Paid or Free:** The Rust backend and SQLite database are open-source and free to use.
* **Scaling Alternatives:** If the project were to scale to monitor multiple rooms or locations, alternatives could include migrating to a cloud-based IoT platform for better scalability and remote management, using MQTT for more efficient data transmission, or implementing a message broker like Mosquitto locally. For a more dynamic and real-time web interface, especially when scaling, technologies like **Elixir LiveView** could be explored. For deployment, platforms like **Fly.io** offer a good solution for deploying Elixir applications globally, bringing the application closer to users and devices for lower latency, while still maintaining cost-effectiveness and ease of management.
## 8. The Code
The MicroPython code running on the Raspberry Pi Pico W handles Wi-Fi connection, sensor reading, and data transmission to the local server.
This MicroPython script is responsible for initializing the Raspberry Pi Pico W's network connection and continuously monitoring the sound and light sensors. It reads analog values from both the KY-037 sound sensor and the LDR. The `read_ldr_voltage` function converts the raw 16-bit ADC reading from the LDR into a more interpretable voltage value. The `connect_wifi` function handles establishing a Wi-Fi connection to the specified network, including a timeout for connection attempts and visual feedback via the onboard LED.
The core logic resides in the `should_post` function, which determines when sensor data should be transmitted to the server. Data is sent immediately if either the sound level or light level crosses a predefined threshold, indicating a significant event. Otherwise, data is sent periodically at a set interval (e.g., every 15 seconds) to ensure regular updates.
The `post_client_data` function then formats the sensor readings into a JSON payload and sends it to the local Rust server via an HTTP POST request. The `main` function orchestrates these operations, continuously looping to read sensors and decide when to post data, providing a robust monitoring system.
```
led = Pin("LED", Pin.OUT)
ldr = ADC(28) # GP28 is ADC2
def read_ldr_voltage():
"""Reads the photoresistor voltage from ADC pin GP27 and returns voltage in volts."""
reading = ldr.read_u16()
voltage = reading * 3.3 / 65535
return voltage
-----
def connect_wifi(ssid, password, timeout=10):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
start = time.time()
while not wlan.isconnected():
if time.time() - start > timeout:
print("❌ Failed to connect to Wi-Fi.")
return None
time.sleep(0.5)
return wlan
-----
def should_post(sound_value, light_value, last_post_time, sound_threshold, light_threshold, post_interval):
current_time = time.time()
# Post immediately if sound OR light exceeds threshold
if sound_value > sound_threshold or light_value > light_threshold:
return True, current_time
# Otherwise, post periodically every post_interval seconds
elif current_time - last_post_time >= post_interval:
return True, current_time
else:
return False, last_post_time
-----
# some part of main
last_post_time = 0
POST_INTERVAL = 15 # seconds
while True:
sound_value = sound_sensor_analog.read_u16()
light_value = read_ldr_voltage()
postable, last_post_time = should_post(
sound_value, light_value,
last_post_time,
SOUND_THRESHOLD, LIGHT_THRESHOLD,
POST_INTERVAL
)
print(f"Posting data. Sound level: {sound_value}, Light level: {light_value:.2f} V")
time.sleep(0.5)
if postable:
print(f"Posting data. Sound level: {sound_value}, Light level: {light_level:.2f} V")
post_client_data(sound_value, light_level)
```
## 9. Transmitting the Data / Connectivity
Data transmission from the Raspberry Pi Pico W to the local server is a multi-step process, ensuring sensor readings are captured and delivered for analysis.
**How Data is Transmitted:**
The data is transmitted using **HTTP POST requests** to a local server. This acts as a simple webhook mechanism where the Pico W sends a JSON payload containing the sensor readings to a specific endpoint on the server.
**Package Format:**
The data is packaged as a **JSON (JavaScript Object Notation) payload**. This is a lightweight and human-readable format, making it easy for both the Pico W to construct and the Rust backend to parse. The payload includes:
* `client_id`: A unique identifier for the Pico W device (e.g., "pico-001").
* `sound_level`: The raw analog reading from the sound sensor.
* `light_level`: The calculated voltage from the LDR sensor.
An example of the JSON payload sent would be:
```
{
"client_id": "pico-001",
"sound_level": 5432,
"light_level": 1.23
}
```
**Steps for Data Transmission to the End-Point:**
1. **Sensor Reading:** The device continuously reads the analog values from both the sound sensor and the LDR. The LDR reading is converted from a raw ADC value to a voltage.
2. **Wi-Fi Connection:** The device establishes a connection to the local Wi-Fi network using the provided SSID and password. This is the foundational step for any network communication.
3. **Decision to Post:** The device determines when data should be sent. Data is transmitted either immediately if a significant change in sound or light (exceeding predefined thresholds) is detected, or periodically every 15 seconds to ensure regular updates.
4. **Payload Construction:** If a post is triggered, a JSON payload is constructed with the client ID, sound level, and light level.
5. **HTTP POST Request:** This JSON payload is then sent to the local server's address with the `Content-Type` header set to `application/json`.
6. **Server Reception and Processing:** The Rust backend server receives this HTTP POST request, parses the JSON payload, and processes the data (e.g., saving it to the SQLite database).
**Wireless Protocol Choice (Wi-Fi):**
The project utilizes **Wi-Fi (IEEE 802.11b/g/n)** as the wireless communication protocol.
* **Device Range:** Wi-Fi offers a good range within a typical home or office environment, generally limited by the router's signal strength and physical obstructions like walls. It's well-suited for indoor monitoring applications where existing Wi-Fi infrastructure is readily available. However, its range is typically shorter than protocols like LoRa, making it less ideal for long-distance deployments without additional access points.
* **Battery Consumption:** Wi-Fi communication can be power-intensive, especially with frequent data transmissions. While the current setup is likely powered via USB, a battery-powered deployment would require significant power optimization techniques. This would involve putting the Pico W into deep sleep modes between readings, reducing the frequency of data polling, and optimizing the data transmission logic to only send data when absolutely necessary (e.g., only on significant threshold breaches, rather than periodic updates).
**Transport Protocol Choice (HTTP POST / Webhooks):**
HTTP POST requests are used as the transport protocol. This is a straightforward method for sending data to a server.
* **Simplicity:** It's relatively simple to implement on both the MicroPython device and the Rust backend.
* **Direct Communication:** It allows for direct communication from the device to the server.
* **Limitations:** While effective for this local setup, HTTP can be less efficient for very frequent, small data packets compared to protocols like MQTT, which are designed for lightweight messaging in IoT contexts. Indeed, an attempt was made to implement MQTT, but the necessary libraries did not function correctly on the Pico W, possibly due to the unofficial firmware being used. This led to the decision to proceed with HTTP POST requests. HTTP also inherently lacks built-in real-time push capabilities from the server to the device, relying on polling if two-way communication were needed.
## 10. Presenting the Data
* **Dashboard Visual Examples:**

* **Data Saving Frequency in Database:** Data is saved to the SQLite database every time it is received from the Raspberry Pi Pico W. This setup was tested and is capable of handling up to 10,000 saves concurrently.
* **Choice of Database:** SQLite
* **Automation/Triggers:** While not currently implemented, a key future enhancement would be to add an email notification system. This would allow the server to send an alert email to a predefined address whenever a significant event is detected (e.g., sound or light levels exceeding a set threshold), providing immediate notification of potential intrusions.
## 11. Finalizing the Design
**Final Project Results:**

**Final Thoughts and Reflections:**
**Successes:**
* Successfully created a functional intrusion detection system utilizing available electronic components.
* Successfully established Wi-Fi connectivity and reliable HTTP POST data transmission to a local server.
* Successfully implemented a basic data visualization on the frontend for real-time monitoring.
**Challenges Faced and How They Were Overcome:**
* **Broken Motion Sensor and Project Pivot:** The initial plan for the intrusion detection system involved a motion sensor. However, I broke the sensor. This necessitated a pivot in the project's approach, leading to the decision to utilize the available sound and light sensors as the primary detection mechanisms, adapting the system's logic to rely on these alternative inputs.
* **Subnet Mismatch:** Initially, the Pico W and the server were on the same Wi-Fi network but different subnets, preventing communication. This was resolved through patience and repeatedly cycling power to the devices until both acquired IP addresses on the same subnet.
* **Early Socket Termination:** The Raspberry Pi Pico W's software socket occasionally terminated prematurely without a clear reason, particularly when stopping and re-running the script from Thonny. This issue was consistently resolved by simply unplugging and replugging the power to the Pico W.
* **Firmware Flashing Issues:** The standard MicroPython firmware for the Pico W initially failed to flash correctly. This required searching for and utilizing an unofficial version of the firmware found on GitHub, which successfully enabled the device to run MicroPython.
* **MQTT Library Compatibility:** An attempt was made to use MQTT for data transmission, but the available MicroPython libraries for the Pico W proved challenging to implement correctly, leading to compatibility issues and preventing proper functionality. This led to the decision to revert to HTTP POST requests for reliable data transfer in this project.
**Areas for Improvement :** For future iterations, more robust error handling and power management would be crucial for a production-ready device. A more sophisticated data visualization on the frontend could provide richer insights. Furthermore, exploring alternative communication protocols like MQTT could offer benefits.