Firmware
In this chapter you will find information about the firmware that runs on our PCB's. You can find the program in the following Github repository: https://github.com/Projectwerk2-2018/Firmware
Last updated
In this chapter you will find information about the firmware that runs on our PCB's. You can find the program in the following Github repository: https://github.com/Projectwerk2-2018/Firmware
Last updated
We started from a project which already had LoRaWAN functionallity in it. The repository can be found here: https://github.com/janjongboom/mbed-os-example-lorawan-minimal
On the image below you see the UML-diagram of our firmware solution.
The PIRSensor class includes the code to get a value from the actual PIR sensor. The PIRSensor class exists of 6 methods, they will be explained one by one.
This is the constructor of our PIRSensor class, here needed everything is initialized. As you can see, we make use of interrupts to detect is there is movement or not. First of all we make sure the interrupt makes use of a pulldown, this must be done otherwise the interrupt won't work as expected. Then we make two methods that wil be linked to an interrupt, one method wil be activated when there is an positive interrupt and the other one when there is an negative interrupt. then we initialize the variable "state" to zero.
This method is activated when the program starts. This method resets every variable and starts a timer, that we will use to get timestamps.
This method is activated just before we want to send the data with one of the transceivers. Here the timer is stopped and with the if-statement the last "delta" is added to the right time, lowtime or hightime.
This method is part of the interrupts. If there is a positive interrupt, this method will be activated. In this method we put STATE to high and we add the "delta" to lowtime because that was the previous time period.
This method does the same as the method "positive_edge_detected" but it works on the negative interrupt and add the delta to the hightime variable.
This is to only getter from the PIRSensor class. this method returns the variable percentage, This percentage represents the high time in relation to the total time.
The code in this method appeared al lot in the code Before we had this method, so we made a private method get_delta and when we needed to read the time, we just have to use this method. This makes our code al lot more DRY.
The TemperatureHumidity class includes the code to get a value from the actual temperature/ humidity sensor. Because the temperature and humidity sensor are in the same package we have chosen to make one class, namely TemperatureHumidity. the class si7013 is a library that we can use to get values from the sensors.
This method is the constructor of this class, here we make use of the default constructor. The constructor makes it possible to use I2C.
The code here is very similar to the one used to test the SI7013 alone (see Hardware Disign/Prototype/Testing temerature and humidity sensor/code operation)
Check if the sensor is active and responding.
Perform measurement
We call upon the get_humidity/ get_temperature methods to get the last measured relative humidity/ temperature data. Because the measured value is converted to mili-percent / mili-°C in the library the stored values need to be converted again to % / °C.
This method is a getters that returns the temperature variable. This method makes us of the private method "read_values", who reads tha values from the sensor.
This method is a getters that returns the humidity variable. This method makes us of the private method "read_values", who reads tha values from the sensor.
As you can see, we made two constructors. The first constructor is the default constructor and set the three values to zero. The second constructor expects three arguments, these arguments will be initialized in the constructor.
This method returns a double temperature.
This method returns a int motion.
This method returns a double humidity.
The purpose of the EnvironmentSensorBoard is to send data to a transceiver. The idea is that you can chose a transceiver (LoRa- or terminaltransceiver) to which data will be sent.
This class has three methods.
Due to circumstances, we did not end up using this method. The function was put it into comment.
The sensor data byte serializer
puts the sensor data into a format that will be sent via LoRaWAN. You can see the format we've chosen here:
And here you can see the code we've made to realize this conversion:
As explained int the 'EnvironmentBoard' section, we want to chose between different transceivers, to which data will be sent. We have made several transceivers, which can be found bellow.
Due to circumstances, we did not make a separate LoRa transceiver class. In stead, all functionallity can be found in the main class.
The main function has a number of tasks:
Store the status of a call to LoRaWAN protocol,
Initialize LoRaWAN stack,
Prepare application callbacks,
Set number of retries in case of CONFIRMED messages,
Enable adaptive data rate,
Make your event queue dispatching events forever.
In the code below you will find the send_message
function. The tx_buffer
variable needs to be filled with 'serialized' data, which comes from the serializer class. This can be seen in lines 6 - 11.
Note that a board was made in top of the program.
We pass nullptr
as argument, this is because we did not end up moving the LoRaWAN functionallity to a separate class.
The program has a receive_message
function, but is not used.
This function has a lot of code, you can find it in our github repository (linked at the top of this page).
Sensor
Size
Datatype
Description
Temperature
2 bytes
int
Send an integer from the PCB
Humidity
1 byte
int
value between 0 and 100 (in %)
Movement
2 byte
int
Amount of movements in a certain timeframe