For this update, fortunately and opposed to the experience in the last few weeks, I have not suffered that much and the project development has run without any major hiccups. A nice surprise
as I have been able to finalize the HW, SW and config for the last two nodes of DomPi! These are the Control Panel and the Garden node.
Let´s review the project status and jump into the details.
Previous Posts
Project Status
Control Panel
I knew I had to make something visually very attractive to catch my wife´s attention
When I got the Raspberry Pi LCD 7" Touchscreen I knew it´d be a game changer and my wife would be at least half as happy as I am with this project! - We are not yet there... but hope to reach this point very soon!!
The Control Panel sits at the entrance of the apartment and has two main functions:
- It displays the status of DomPi: light status, is the Presence Emulator on or off, what´s the weather and pollution like, is the car in the garage, what´s the temperature at home in all of the rooms, is the alarm active, etc
- It also allows human interaction: activate/deactivate the alarm or the Presence Emulator, allows to turn on/off light by light or all of them at once, etc
As the Control Panel will be in a very visible place, it has to be a "nice thing" rather than a plastic box or any other case like with the rest of the nodes. The design of the LCD is quite slim and should be ok at least for the first... months? I´ll let you know if I get complaints from the rest of the "users" at home!
Hardware
The HW architecture for this first development is quite straight forward: the Raspberry Pi B+, the LCD and the Wifi dongle, all of them come with The Kit of the Challenge. Really cool components that have been as easy to install as "plug-and-play".
Control Panel. Raspberry Pi set-up
First step has been to install NOOBS into a SD card I had at home. To do so, I just followed the instructions from the RaspberryPi webpage here and downloaded the latest OS version from here. It all went fine, with no call outs at all, including the first boot when the RaspberryPi gets auto configured. Once it finished booting and I was on the graphical interface I modified the RPI password - you never want to have the default password in a system like a RPI that can expose your network to the Internet if hacked... After that, I changed the name of the RPI to "controlpi" - to do so I went to Menu->Preferences->Raspberry pi Configuration and changed it there both the hostname and the password.
Next step has been to move the OS from the SD card to a USB drive. I just followed the same steps as I described in PiIoT - DomPi 07: Setting up the Command Center (2) These steps still work
In the Control Panel case, I also had to use /dev/sda7 as the place where the file /boot/cmdline.txt had to point at for booting on the USB. No call outs, no delays, again!
Control Panel. LCD 7" Touchscreen installation
Now it comes the fun and new part for me, to install the LCD! I was looking forward to it since the box came but didn´t have time till now, plus was concerned it´d be more challenging. So I started by following the instructions from Element14 here. All went really well!. Besides this page, more people in the Challenge have used it and I think it is worth to have a look at this video from rhavourd
nice! I found the same comment as Rick´s that after installing the keyboard app, it did not appear in the menu. I just follow Rick´s solution:
After installing matchbox-keyboard, I still did not have a menu option for it. If that is the case for you, simply go into Menu->Preferences->Main Menu Editor->Applications->Accessories. Enable the keyboard by clicking its' "Show" option.
And it worked out. Thanks rhavourd!
Another comment, to plug in the DSI ribbon cable, the white one, I had some difficulties with the connector and didn´t want to damage it. I just carefully used a screwdriver to unlock the connector and then lock it with the cable inside. You can see a picture of this and the final result here:
![]() | ![]() |
Control Panel. Wifi dongle installation - WiPi
The last step for the HW set-up and configuration was to install the dongle, the WiPi from the challenge kit. This really was "plug and play" for my surprise. I connected it to the USB and when I started the RPI, the Wifi configuration was already accessible at the upper right corner in the network icon. I had just to click on it and enter my home Wifi credentials. I had some previous experience trying to configure a WiFi dongle and was concerned about how much time this one could take. Nice surprise! You can see a pic after the next paragraph.
Control Panel. Final test with OpenHAB
As a final test, I want to display the DomPi status on the Control Panel screen. Firstly, I make sure that the OpenHAB server from the Post 9 is running and then I launch the Epiphany browser on the Control Panel and point it at the url: http://myCommandCenterIPaddress:8080/openhab.app and after crossing my fingers... Here we are! The page served by the openHAB app in my Command Center is displaying on the Control Panel and I can actuate on the lights and read the sensors! Phew 
![]() | ![]() |
Note that I have not installed the VNC server as I don´t plan to use it. Re the SSH keys as per my post 6, I do believe it is good to deploy them and plan to do it in the short term - I defer it right now as I won´t expose this RPI to the Internet and have already changed the pi password.
Control Panel. Launch browser on boot
This is the final step. I want the Control Panel to display the DomPi openHAB page whenever it is booted up. I could do this by creating a shortcut on the desktop and double clicking it whenever I power it up but... I thought of doing this automatically. To do so, I want to launch the Epiphany browser pointing at the previously shown url: http://myCommandCenterIPaddress:8080/openhab.app
I will install the matchbox-window-manager to allow me launch Epiphany in full screen mode:
sudo apt-get install -y matchbox-window-manager
The browser requires a /.config folder to store the cookies, etc. I had it already and did not precise to create it. Besides that, I have created a file that will be executed at boot time. I created this under /home/pi by:
sudo nano ./cpPi_bootEpiphany
and pasted these lines:
#!/bin/sh xset -dpms # disable DPMS (Energy Star) features. # xset s off # disable screen saber - I have commented out this line as I do want to have the screen to go off after inactivity # xset s noblank # don't blank the video device - I have commented out this line as I do want to have the screen to go off after inactivity matchbox-window-manager -use_titlebar no & WEBKIT_DISABLE_TBS=1 epiphany-browser -a --profile /home/pi/.config http://commandcenter_IPAddress:8080/openhab.app
I just replaced the CommandCenterIPaddress by the right address
Finally, I added this line to the /etc/rc.local file putting them before the exit 0 line:
sudo xinit ./home/pi/cpPi_bootEpiphany &
Control Panel. Future developments
For future developments to the Control Panel I will install the Sense Hat of the kit - not sure if there will be HW issues with the LCD - and a RFID card reader. The card reader is a nice feature, however, now having a Touchscreen at the entrance of the apartment, the usage of the card is less "interesting" as you can always leverage the screen.
Yet another future development will be to improve the visual impact of the Control Panel display. The openHAB web page is not bad, but can be highly improved using the REST API of openHAB to make it "nicer" 
Garden node
For the node in the garden, I am replicating the same HW architecture and configuration as for the kids room in the post PiIoT - DomPi 05: Ready for use Living Room and parents and kids´ bedrooms. There is just a couple of comments. I changed the "this_node" id to reflect the garden (number 4). Also, I have removed the PIR from the HW and forced it to 0 in the sketch. I want to test if a PIR makes sense or if there is a better sensor for my needs...
So far, the node includes: the temperature, humidity and luminosity sensors, and the RF24. In the future it will also include a motion sensor, a rain detector (drop count) and a soil moisture sensor. Regarding the power, I have a plug in the terrace and I am plugging it directly to it. To protect it from the rain, snow and sun I will put it into a case IP44 that I have ordered. I will make 2 small holes in the lower part for the temperature and humidity sensors. For the luminosity sensor, I will try to make something fore fancy like making a hole and close it with a transparent plastic so that the light comes in but not the water. Hope to have a clearer idea once I have the case with me.
And now the Arduino code:
#include <RF24Network.h>
#include <RF24.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <DHT.h>
#include <Defs_y_Clases.h>
/*
*
* Node for the Garden node
* At this point in time, it includes:
* Temperature
* Humidity
* Luminosity
* RF24
*
* To be developed:
* Motion/Intrusion - Always sends 0
* Rain detection
* Soil moisture
*
*/
const bool debug = true; //If true, enables debug dump via Serial port
// Pin for the LED
int ledPin = 13;
// Pin for the switch
#define PIN_SWITCH_GARDEN 5
// Pin for the PIR
#define PIN_PIR_GARDEN 2
// Data wire is plugged into port 3 on the Arduino
#define ONE_WIRE_BUS 3
// The DHT data line is connected to pin 4 on the Arduino
#define DHTPIN 4
#define DHTTYPE DHT11 // Leave as is if you're using the DHT22. Change if not. // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302) //#define DHTTYPE DHT21 // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
//NOTE: in line below I need to modify the address if I use a different temp sensor
DeviceAddress insideThermometer = {0x28, 0xFF, 0x5B, 0xED, 0x10, 0x16, 0x04, 0xBC};
//Temp address of the sensor: 28FF5BED101604BC // arrays to hold device address
// Photocell variable
byte photocellPin = A3;
// Radio with CE & CSN connected to pins 9 & 10
RF24 radio(9, 10);
RF24Network network(radio);
// Constants that identify this node and the node to send data to
const uint16_t this_node = 4;
const uint16_t parent_node = 0;
// Time between packets (in ms)
unsigned long interval = 60000; // every x/1000 sec
// The below objects are type Temporizador (timer). They replace the need of using the delay()
// This allows the script to run and do other tasks while waiting for the time to pass
Temporizador tempo_tx(interval, true); //timer for the RF transmisions, every 60s it will force sending an update to the master node
Temporizador tempo_tx_maxdelay(900000, false); //Maximum delay Id allow without having sent a message to the master node, 15 mins
Temporizador tempo_watchdog(3600000, false); //Watchdog, if no update in 1h, activates watchdog
// Variables for the sensors
float h, t; //humedad y temperatura
int l; //luminosidad
bool is_motionPIR = false; //Stores current status of the PIR motion sensor
bool is_motionPIR_prev=false; //Stores prev status of the PIR motion sensor,
//if different than current, then forces to send a message:new movement detected
int status_switch = 0; //States if the switch on the board was pushed
bool force_send_msg = false; //Fuerzo a enviar el msg independientemente del estado
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(void)
{
if (debug) Serial.begin(9600);
// Initialize all radio related modules
SPI.begin();
radio.begin();
delay(50);
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(50);
radio.setChannel(108); //Set channel over the WIFI channels
delay(50);
radio.setDataRate(RF24_250KBPS); //Decrease speed and improve range. Other values: RF24_1MBPS y RF24_2MBPS
delay(50);
network.begin(90, this_node);
// Initialize the DHT library
dht.begin();
//Get oneWire devices on bus
sensors.begin();
sensors.setResolution(insideThermometer, 12);
// Configure LED pin
pinMode(ledPin, OUTPUT);
//Config pin for the switch
pinMode(PIN_SWITCH_GARDEN, INPUT_PULLUP);
//Config PIR
pinMode(PIN_PIR_GARDEN, INPUT);
digitalWrite(ledPin, LOW);
if (debug) {
Serial.print("Starting Node Garden. Node number: ");
Serial.println(this_node);
}
status_switch = digitalRead(PIN_SWITCH_GARDEN); //read the switch status
}
void loop() {
// Update network data
network.update();
//Receive RF Data
while (network.available()) {
receive_data();
}
if (tempo_tx_maxdelay.is_Time()) {
//If we enter here, means that tmax has already elapsed and we are to force data transmission
force_send_msg = true;
}
if (switch_just_pushed()) {
//If the switch is just pushed, we force sending the RF data
force_send_msg = true;
}
if (change_inPIRsensor()){
//If there is change in PIR, forces the update to the node
force_send_msg = true;
}
//Get and send the sensor data. This is done only if the timer is over or we force RF data
if (tempo_tx.is_Time() || force_send_msg) {
tempo_tx_maxdelay.reiniciar_t0(); //Reinitialize the timer
read_sensors_data();
send_sensors_data();
force_send_msg = false;
}
check_watchdog();
}
void receive_data(){
RF24NetworkHeader header;
message_action message_rx;
network.peek(header);
if (header.type == '2') {
tempo_watchdog.reiniciar_t0(); //message received, it means there is communication
// with the master, reinitiates the watchdog timer
network.read(header, &message_rx, sizeof(message_rx));
if (debug) {
Serial.print("Data received from node ");
Serial.println(header.from_node);
}
unsigned char cmd = message_rx.cmd;
unsigned char info = message_rx.info;
if (debug) {
Serial.print("Command: "); Serial.println(cmd);
}
switch (cmd) {
case MODIFICAR_T_SLEEP:
interval = message_rx.info * 1000;
send_cmd_per_RF(ACK, cmd);
break;
case FORCE_SEND_MSG:
force_send_msg = true;
send_cmd_per_RF(ACK, cmd);
break;
default:
//Do nothing
break;
}
} else {
// This is not a type we recognize
network.read(header, &message_rx, sizeof(message_rx));
if (debug) {
Serial.print("Unknown message received from node ");
Serial.println(header.from_node);
}
}
}
void read_sensors_data() {
sensors.requestTemperatures();
h = dht.readHumidity();
t = sensors.getTempC(insideThermometer);
//Sensor for PIR is read already when loop calls function change_inPIRsensor
//no need to re-read it here
// Read photocell and constrains data within a range and then maps it to range 0% - 100%
l = analogRead(photocellPin);
l = constrain(l, 70, 850);
l = map(l, 70, 850, 0, 100);
}
void send_sensors_data(){
header.type = '1'; // Headers will always be type 1 for this node
// Only send values if any of them are different enough from the last time we sent:
// 0.5 degree temp difference, 1% humdity or light difference, or different motion state
float t1 = t*100; //multiplies by 100 to get read of float and transmit only int16
int16_t t_tx = (int16_t) t1;
if (abs(t_tx - message_tx.temperature) > 30 || //sends data if there are significant changes in the sensors measurements
abs(h - message_tx.humidity) > 1.0 ||
abs(l - message_tx.light) > 5.0 ||
force_send_msg) {
// Construct the message we'll send
message_tx = (message_1){ t_tx, (unsigned char) h, (unsigned char)l, is_motionPIR, 0 }; //codigo original: {f, h, p, m, d}
// Writing the message to the network means sending it
if (network.write(header, &message_tx, sizeof(message_tx))) {
tempo_watchdog.reiniciar_t0(); //reinitiates the watchdog timer
if (debug) Serial.print("Message sent\n");
} else {
if (debug) Serial.print("Could not send message\n");
}
if (debug) {
Serial.print("Temp_tx: "); Serial.println((message_tx.temperature));
Serial.print("Temp_detected: "); Serial.println((t));
Serial.print("Hum_tx: "); Serial.println(message_tx.humidity);
Serial.print("Hum_detected: "); Serial.println((h));
Serial.print("Luminosity: "); Serial.println(message_tx.light);
Serial.print("Motion PIR: "); Serial.println(message_tx.motion);
}
}
}
void send_cmd_per_RF(unsigned char cmd, unsigned char info) {
//Sends via RF the command and info
//This is the way to update the master of the light status, ACK, etc
header.type = '2';
message_action message_x_RF;
message_x_RF = (message_action){ cmd, info };
// Writing the message to the network means sending it
if (network.write(header, &message_x_RF, sizeof(message_x_RF))) {
if (debug) Serial.print("Message sent RF\n");
//There is communication with the master -> reinitiate the watchdog timer
tempo_watchdog.reiniciar_t0(); //reinitiates the watchdog timer
} else {
if (debug) Serial.print("Could not send message RF\n");
}
}
bool switch_just_pushed() {
int v = digitalRead(PIN_SWITCH_GARDEN);
bool r=false;
if (v==LOW) {
status_switch=LOW;
digitalWrite(ledPin, LOW);
}
else {
if (status_switch==LOW) {
//if low, then it is the first time we pushed the button
//this means we have detected a raising signal
status_switch=HIGH;
r=true;
digitalWrite(ledPin, HIGH);
}
}
return r;
}
bool change_inPIRsensor() {
//True if there is a change in the PIR sensor
bool b;
// Removed following line until right sensor is implemented
// is_motionPIR = (digitalRead(PIN_PIR_GARDEN)==HIGH); //updates current state of the PIR
is_motionPIR = 0; //Temporary forced to 0
b = (is_motionPIR!=is_motionPIR_prev); //if current != previous state -> change
is_motionPIR_prev = is_motionPIR;
return b;
}
void check_watchdog() {
//Controls the watchdog. Checks that there has been some communication with the
//central node in the last 1h, either receiving a message from the center
//or sending a message successfully to the center
if (tempo_watchdog.is_Time()) {
//At this point in time, this does nothing special, just print error via Serial
//Improvement: to deactivate the automation and force lights to off, etc
if (debug) Serial.println("Alarm!!! Watchdog timer. No successfull communication with the center");
tempo_tx_maxdelay.reiniciar_t0();
}
}
Nodes´ Dashboard
I added the Control Panel node for the first time in this post - it would have hindered the readability before...
More lines coming into green!







Top Comments