Movement detection and RF comms are the last two components for the minimum setup of a node in DomPi. The RF comms allows each of the remote nodes (Arduino based) to send and receive data from the Command Center (Raspberry Pi 3 based). The movement detection enables the project to build up three additional features: the alarm, determine presence at home and automatic lights. I will start with the easier component, the movement detection, but first, let me share the features I will be developing in this post:
Movement detection - PIR sensor
This component shall help the Command Center (CC) to deliver the three features mentioned above, meaning that the remote notes will just update the CC on the status - is motion detected or not - and it will be the CC who decides what action to trigger. The "intelligence" will reside in the CC. Let´s see the details of the hardware and software pieces.
Hardware and wiring
The sensor I will leverage for detecting movement at home, in the garden or garage is the HC-SR501, a passive infrared sensor. It works at +5V source and at +3.3V TTL. I have connected the Data pin of it (see picture below) to the pin 2 of the Arduino Nano. The sensor allows some configuration via hardware:
- sensing distance: with the potentiometer T2 you can adjust the distance from 3 to 7 meters (10 to 23 ft). I will set up all of the PIRs at its maximum distance,
- trigger approach: you can select the repetitive triggering (the output remains high while it detects presence in its range) or the non-repetitive (after some seconds the output goes to low and starts scanning again). This can be selected via the jumpers L(non-repetitive) and H (repetitive). I will set up all of the PIRs to the non-repetitive position. There is no special reason for this, but the main usage of the PIRs at the beginning will be for the alarm and with the non-repetitive it will be easier to avoid false positives - in the end I doubt that a burglar would stand up not moving for minutes and minutes at home... If however, I get a false positive - f.e. a bad initial reading of the PIR, etc - the output will go down after x secs allowing the CC to interpret this as a false alarm.
- time delay adjust: you can adjust the seconds it waits before forcing a low output, between 5s and 300s. I´m adjusting it almost to the minimum, around 5-10s delay
An important note is that this sensor as a broad sensing angle, 110º, making it a good fit for DomPi where I want to control rooms and corridors, but maybe not that suitable if you pretend to control a narrower space. An interesting note on the PIR is that as a passive sensor "that measures infrared (IR) light radiating from objects in its field of view. (...) the temperature (...) in the sensor's field of view will rise from room temperature to body temperature. The sensor converts the resulting change in the incoming infrared radiation into a change in the output voltage, and this triggers the detection", source Wikipedia.
Software
There are two main alternatives to detect movement: with interrupts and by periodically polling the sensor. I did start with the interrupts, and attached an interrupt to be called each time there was a change in the PIR status (from nothing detected to something detected and the other way round). Below is part of the code that would allow the first approach. With the Arduino Nano you can attach interrupts to the pins 2 and 3 - in my case the PIR is in the pin 2.
#define PIR_PIN_LIVING 2 int PIRstatus=0; ... pinMode(PIR_PIN_LIVING, INPUT); attachInterrupt(digitalPinToInterrupt(PIR_PIN_LIVING), processPIRchange, CHANGE); ... void processPIRchange() { PIRstatus = digitalRead(PIR_PIN_LIVING); }
After several testing and a couple of hours invested I realized that the interrupts where not working properly. It did detect me correctly but the rest of the code was not working properly. Right now I have several components in the living room node that I use for testing: the PIR component, the RF light control, the environment measurement, the IR receiver (see posts 2 and 3) and the RF 2.4Ghz piece. My feeling is that some other library may be using the interrupts and it is not getting well along with my PIR. The responsiveness of the node went down dramatically making it not fit for purpose... So I decided to avoid interrupts and go to the second best option, polling the sensor periodically. For the DomPi project, in terms of usability, it won´t change anything, the main loop is fast enough to read the PIR quickly and detect any movement in time.
Let me share with you the complete code in the next post, hopefully some minor issues will be sorted out!
RF 2.4GHz comms - the NRF24L01
This is a key component of the DomPi. Since there will be five remote nodes (living room, two in the bedrooms, garden and garage), the best solution is to connect them with the Command Center via wireless - I don´t see myself making holes to reach the garage in my building of flats... I could use some Wifi dongle for the nodes, but the solution would not be that light nor cheap. Potentially, a RF 433Mhz transmitter and receiver per node could make the trick. I finally opted for a NRF24L01, it is a transceiver (transmits and receives with the same circuitry) and there are very nice libraries allowing a sort of RF network.
Hardware and wiring
The first thing to note is that there are some known problems with powering this chip directly from Arduinos such as the Nano or Mega that I pretend to use in DomPi. Since the power of these is limited to 50mA, it may not deliver the enough current to support the NRF24L01. There are a couple of workarounds to solve it: use an independent power unit, set two capacitors (10uF and 0.1uF) between its Vcc and Gnd or insert a base module between the Arduino and the NRF24L01 to power it up. To avoid further delays in the project, I will start by using the base module (see pic below). The good news is that the NRF24L01 seems to work ok with the Raspberry Pi.
NRF24 Module |
Base Module for the NRF24 |
NRF24 connected to the base modlue |
Pictures: NRF24_1, Base_module, NRF24+Base_module
The wiring is not much complex but some care is needed. There are 8 pins in the base, one of them, the IRQ, is not required for the DomPi project. For the other 7, we have Gnd and Vcc, which should go to +5V, note that if you don´t use the base module then you have to connect the NRF24 to +3.3V or it can be damaged. The 5 remaining allow a SPI communication with the Arduino, the downsize of it is that 3 pins are fixed and you need to connect them to the right pins in the Arduino. These are the MISO, MOSI and the SCK that in the Nano case they should connect to 12, 11 and 13 respectively. I foresee some difficulties when working on the Garage node as the TFT base will connect to these pins and it will be difficult to physically access them. The last 2 pins, CE and CSN, can be selected via software when calling to the object. In my case I left them at: 7 and 8 respectively. I found this page very helpful while setting up the module.
Software
To use the NRF24L01 besides the Arduino SPI.h library, I am leveraging the library written by TMRh20. The great thing about this library, besides the support and forums you can get, is that I can use it on the Arduinos as well as on the Raspberry Pi, so... it is a great fit to the DomPi! As usual, to use the C++ library in Arduino, you just need to import the .zip file via de Arduino IDE (menu Sketch->Include Library->Add zip library), alternatively you can just paste the uncompressed file into the Arduino->libraries folder and next time you start the IDE, there it will be.
A bit below I have included part of the Arduino code related to this component. It follows the examples included in the library: I use two objects, the RF24 to set up the radio functions, and the RF24Network which enables a network based on the radio object. There are two interesting points on the code, you need to set the id for the parent_node - to which the node will talk to - and also the id of this node. For the DomPi I have reserved the following ids:
- 0 for the Command Center, RPI 3
- 1 for the kids´ bedroom
- 2 for the parents´ bedroom
- 3 for the living room
- 4 for the garden
- 5 for the garage
The second point is lines 13 to 27. They define the message structure that will be sent to the master or received from it. Since these are the remote nodes, they will send the temperature, humidity, luminosity, motion status and another char more for future expansion. On the other hand, the remote nodes will receive from the CC a command - determines what needs to be done like "turn on light" - and an info char - with additional information like the number of the light to execute the command on. With each loop, we update the network and if there is a package received from the Command Center it calls the function receive_data() to process it.
#include <RF24Network.h> #include <RF24.h> #include <SPI.h> // Radio with CE & CSN connected to pins 7 & 8 RF24 radio(7, 8); RF24Network network(radio); // Constants that identify this node and the node to send data to const uint16_t this_node = 3; const uint16_t parent_node = 0; struct message_1 { // Structure of our message to send int16_t temperature; //Temperature is sent as int16: I multiply by 100 the float value of the sensor and send it //this way I avoid transmitting floats over RF unsigned char humidity; unsigned char light; unsigned char motion; unsigned char dooropen; }; message_1 message_tx; struct message_action { // Structure of our message to receive unsigned char cmd; unsigned char info; }; message_action message_rx; RF24NetworkHeader header(parent_node); // The network header initialized for this node void setup() { // Initialize all radio related modules SPI.begin(); radio.begin(); delay(5); radio.setPALevel(RF24_PA_MAX); //This can lead to issues as per https://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo //use this radio.setPALevel(RF24_PA_LOW); if there are issues delay(5); radio.setChannel(108); //Set channel over the WIFI channels delay(5); radio.setDataRate(RF24_250KBPS); //Decrease speed and improve range. Other values: RF24_1MBPS y RF24_2MBPS delay(5); network.begin(90, this_node); } void loop() { // Update network data network.update(); //Receive RF Data while (network.available()) { receive_data(); } //Additional Code for IR, sensore measurement, etc }
There also three important notes.
- Line 39 sets the wireless channel to the 108. This module operates in 2.4Ghz that is the same band as the IEEE 802.11, the standard Wifi at home besides the 5Ghz band. By selecting the 108 channel, we should be out of the wifi band hence having less interference.
- Line 36 sets the emitting power to the maximum that the NRF24L01 can provide. Although this looks like the right thing to do, due to the power issues mentioned before, the standard recommendation is to set it to the minimum power. In my case, with the base module it seems to be ok with the max power.
- Line 41 sets the transmission speed to the lowest one allowed. The first reason is that we are transmitting just a few bits, below 100 bits including any headers. Additionally, the project does not require responses to the microsec. The second reason is the Shannon theorem. There is a lot of maths and of communications theory, but the summary is that the higher the speed, the "cleaner" the environment has to be (signal to noise,SNR, ratio). In general, the further both nodes will be, the "dirtier" the environment is (lower SNR) and therefore the maximum speed will decrease. If we force a higher speed than the maximum, we lose information and the nodes won´t communicate with each other. By selecting the minimum speed possible we can achieve longer distances or "dirtier" environment. Since I want to communicate with the garage, the SNR will be quite low, so it makes sense to decrease the speed. PS: This is also the reason why it takes long time to transmit data and pictures from the spaceships that visit the planets (like Pluto recently), the SNR is so low that according to the Shannon theorem the speed needs to be really low - sorry for the digression
All in all, I am testing the communications with a second Arduino and after some fine tuning, it is working quite well. I´m curious to check whether I can communicate with the garage!
Hope to be able to share the complete code of the living room in the next post!
Nodes´ Dashboard
After this week, most of the basic components of the living room node are finished and several of them will be easily replicable in all the remote nodes, so hope to see more greens coming in shortly!
Any comments, suggestions or ideas are more than welcome!