SIT210 Project
This project is designed to create a smart alarm to help users get into the habit of getting up early for a morning run. The system monitors and triggers the alarm based on a pre-set lux value to ensure that it is not so dark when the alarm is triggers that the user will not be able to see well or be seen my local traffic. By triggering based on light rather than time, the system will maximise the users free time in the morning by waking them up at an optimal time each day.
Supplies
This project will require the following hardware:
- Particle Argon (used for light monitoring device)
- Raspberry Pi (RPi) used to sound an alarm and act as a MQTT broker
- 1 LED
- 1 Buzzer
- GY-30/GY-302 ambient light sensor
- Jumper leads
- x2 Breadboards (mini or regular sized)
- Switch (button) for RPi
- Power supplies for RPi and Argon
Step 1: Setting Up the Argon and Light Sensor
To begin with, you may need to solder the pins for your light sensor in place. This may be unnecessary for some sensors, but if you have separate pins and sensor like in the image above solder the pins so that the smallest amount possible is protruding from one side to allow maximum length on the other side of your sensor.
The following is a GitHub link to the code used for this solution. It is fully commented to better assist your understanding: https://github.com/AaronNorwood/SIT210-Project-218...
Feel free to use that code for this project, it should work straight away!
- Wire the Argon per the guide above
- Alter the Argon code from the GitHub repo above to use the IP address of your RPi
- This ip address can be obtained by running the following command in a terminal on your Rpi: hostname -l
- Flash the Argon code to your Argon using the Particle IDE
- Review console in Particle IDE for verification if desired
Step 2: Setting Up the RPi
- Install Mosquitto to run MQTT broker on RPi
- Open a terminal and type the following commands:
-
sudo apt-get update
-
sudo apt-get upgrade
-
sudo apt-get install mosquitto mosquitto-clients
-
To test mosquito installation:
-
Open two terminals
-
In the first type:
-
mosquitto_sub -t “test”
-
In the second type:
-
mosquitto_pub -t “test” -m “Hello World!”
-
You should see “Hello World!” print in the first terminal
-
- Open a terminal and type the following commands:
-
Update the Python script from the GitHub repo above with the IP address of your RPi
-
Run the Python script, I used Thronny but a terminal will of course suffice
Step 3: Running the System
- Ensure the Argon is powered on and data is being transmitted, you should see the lux value being printed out to the Particle console
- Ensure the RPi is powered on and receiving data from the Argon, as long as the Argon is transmitting you should see the lux value from the Argon being printed out by the Python script if everything is working properly
- The Argon will transmit lux data to the RPi every two seconds
- If the lux is 10 or more, it will trigger the alarm lighting the LED and sounding the buzzer
- This threshold can be altered by updating the value of the "morning lux" variable in the Python script
- Press the button on the RPi breadboard to disable to alarm
- Press again to re-enable the alarm
- Cover the GY-30 sensor to prevent it triggering the alarm too early if desired for testing purposes
Understanding the System and Code
Communication:
Communication in this system is handled by Mosquitto which runs an MQTT broker on the RPi. MQTT stands for MQ (previously message queuing) Telemetry Transport and is a popular, easy to use method for communicating between Internet of Things devices. MQTT was used for this project not only for it's ease of use but because it is completely device agonistic; facilitating communication between devices regardless of what those devices may be. Indeed, the MQTT broker we use here does not even know that we are using an Argon and an RPi, it simply acts as a relay (broker) to receive and pass on messages. This means that this system can be easily adapted to use different devices, not just the ones used here.
Argon code:
This code makes use of the MQTT library to handle the heavy-lifting for the MQTT communication and the BH1750lib library to read data from the lux sensor.
The way the Argon receives information is handled by the callback function (starting line 21), to alter this logic this function can be changed. This callback function is passed to the MQTT client (the server acting as a broker; our RPi in this case) when it is initialised (line 9) and is called each time the client is looped (lines 56 & 81) in the main loop. The Argon listens only to data published with the topic heading "data/reset" (line 42) and will read any message sent to this topic. For this program, the only messages sent are "reset" and "start" (see Python code).
The Argon transmits data in the main loop (line 79) by publishing lux values to the "data/lux" topic which is received by the RPi.
The final nuances to understand include the calls to check if the if the client is connected (line 77) and to loop the client (line 81).The check to see if the client is connected ensures that we don't transmit data if the broker is unavailable (since the data would have nowhere to go) and the client.loop ensures the client is repeatedly run.
The GY-30 lux sensor is initialised declared before the setup function to be globally accessible (line 18), started in setup (line 34) and then is read from every loop to update the reading (line 74).
Python Code:
For this script, we make use of the paho.mqtt.client library to perform the heavy-lifting for the communication, the RPi.GPIO library to handle interactions with our LED and buzzer and finally the gpiozero library to control the button.
We begin be configuring the board to use the GPIO pin numbering,declare initial variables to store information and ensure the LED and buzzer don't start prematurely by setting them to low voltage (lines 7-30).
The main body of the script (lines 104-117) begin by setting up the MQTT broker, attaching the callback functions we've defined to the client and starting to listen to the Argon (line 113). The client.loop_start() call ensures this is done constantly.
Our on_connect function we connect with the MQTT server running on the RPi, print out a success/failure message and begin subscribing to the channel the Argon will publish to. Note: we don't connect directly to the Argon, only to the broker.
The on_message function listens for messages from the Argon and acts on them where necessary printing to values for verification purposes. This function calls out alarm function if the lux value it receives is high enough. The msg.topic ensures we only check messages to the channel our Argon is publishing to and the msg.payload accesses the raw data being sent. In this function we convert the lux to an integer for easier comparison.
The on_publish function has no custom logic, only the logic from the paho.mqtt library you can uncomment the print call if you're having problems to ensure that data is being transmitted. This function is called every time the RPi sends data to the Argon.
Finally, the trigger_alarm function handles not only firing the alarm but allowing the user to stop the alarm and reset it if needed. This function configures a new instance of the MQTT function since it create it's own loop which disconnects it from the client.loop thread created in the main body of the program; without this new instance of the client, it cannot be accessed here. After setting it up again, the function simply sounds the alarm until the use stops it and transmits the stop request to the Argon. In order to prevent the alarm triggering immediately again after being restarted, the global lux value is reset to 0 and the function sleeps for 5 seconds to give the Argon time to transmit a new lux reading to the RPi because otherwise it would access the old message with a high lux value.