Nowadays home automation is a trending topic among electronic enthusiasts and even the mass population. People are busy with their life challenges, so an electronic device should take care of the home instead! The majority of such devices need internet or Wi-Fi for connectivity or they don’t offer a user-friendly GUI, but I decided to design a standalone wireless monitoring/controlling unit that can be adjusted using a graphical and touch-controlled LCD display.The device consists of a panelboard and a mainboard that communicate using 315MHz (or 433MHz) ASK transceivers. The panel side is equipped with a high-quality 4.3” capacitive-touch Nextion Display. The user can monitor the live temperature values and define the action threshold (to activate/deactivate the heater or cooler), humidity (to activate/deactivate the humidifier or dehumidifier), and ambient light (to turn ON/OFF the lights). The mainboard is equipped with 4 Relays to activate/deactivate the aforementioned loads.To design the schematic and PCB, I used Altium Designer 23. The fast component search engine (octopart) allowed me to quickly consider components’ information and also generate the BOM. To get high-quality fabricated boards, I sent the Gerber files to PCBWay. I used the Arduino IDE to write the MCU code, so it is pretty easy to follow and understand. Designing a GUI using the Nextion tools was a pleasant experience that I will certainly follow for similar projects in the future. So let’s get started :-)SpecificationsConnectivity: Wireless ASK, 315MHz (or 433MHz)Parameters: Temperature, Humidity, Ambient LightWireless Coverage: 100 to 200m (with Antennas)Display: 4.3” Graphical, Capacitive-TouchInput Voltage: 7.5 to 9V-DC (power adaptor connector)Download the Gerber, Order the PCB or a Fully Assembled Board [Panel]Download the Gerber, Order the PCB or a Fully Assembled Board [Mainboard]Circuit AnalysisFigure 1 shows the schematic diagram of the panelboard. Figure 2 also shows the schematic diagram of the mainboard. I used Altium Designer to draw these two circuits.Figure 1Schematic diagram of the panelboardFigure 2Schematic diagram of the mainboard1. MainboardThe mainboard circuit consists of 5 main parts: the power supply, ASK transceivers, Sensors, Microcontroller, and Relay drivers.1-1: Power SupplyCON-1 is an input jack to connect an adaptor or a power supply to the board. The best input voltage is around 8V; however, you can use 9V adaptors as well. The current rating of the adaptor should be 1A, but the market is full of fake adaptors with unrealistic ratings, so make sure that it can deliver at least around 400mA continuously. FB1, C17, and C18 are used to reduce the input noise and spikes. REG2 is the famous 7805 regulator [1] to power the Relays. D1 is a bidirectional SMBJ5CA diode [2] to remove possible voltage spikes. C19 and C20 are used to reduce the output noise. R3, C14, and C15 build a low-pass RC filter to reduce the noise to REG1. REG1 is the SOT-89 78L05 regulator [3]. It supplies the IC1 and the ASK RF modules. C16 reduces the output noise of REG1.1-2: ASK TransceiversRE and TR represent the ASK receiver and transmitter modules. The frequency of the modules could be 315MHz or 433MHz, but the frequency of all modules (both the panelboard and the mainboard) must be identical. Figure 3 shows a picture of these ASK modules. C1, C2, C3, and C4 are decoupling capacitors for the module supplies.Figure 3ASK Transmitter and Receiver modules1-3: SensorsI used the SHTC3 module (SENS2) and the TEMT6000 module (SENS1) to measure the temperature, humidity, and ambient light intensity. SHTC3 module uses the I2C protocol to communicate with the microcontroller, however, the module itself has already implemented all necessary pull-up resistors, a 3.3V regulator, and decoupling capacitors inside the box. C7 and C8 are decoupling capacitors for the TEMT6000 supply. Figure 4 shows a picture of these modules.Figure 4TEMT6000 and SHTC3 modules1-4: MicrocontrollerThe heart of the circuit is the IC1 (ATMega328 microcontroller) [4], the same chip as the Arduino Nano. I used a 16MHz crystal for the clock source. C9 ... C13 are decoupling capacitors. The ISP is a 5-pin male pin header to connect an ISP programmer (such as the USBasp or similar) to burn the HEX file into the chip. R1 is a 10K pull-up resistor for the Reset pin, to avoid unwanted triggering of the Reset (active-low).1-5: Relay DriversThe Relay driver circuitry is identical for all 4 Relays, so I only explain one of them. Q1 is the Si2302 N-Channel Mosfet [5]. R6 is a pull-down resistor to prevent unwanted Gate triggering of Q1. D2 is a protecting diode against reverse currents of the Relay’s coil. C21 capacitor helps dampen the Relay’s coil ON/OFF spikes. D4 is a 0805 RED led to indicate the ON/OFF state of the Relay [6].2. PanelboardThere is a high similarity between the circuit of the panelboard and the mainboard, the main difference is the Nextion display connector. The Nextion display uses the UART or Serial interface. C16 and C17 are decoupling capacitors.3. PCB LayoutFigure 5 shows the PCB layout of the design. Both are two-layers PCB boards and the majority of the components are SMD. As well as the schematic, I also used Altium Designer [7] to draw the PCB layout. Figure 6 shows the assembly drawings.Figure 5PCB layout of the wireless home automation device (Altium)Figure 6Assembly drawings4. CodeI used the Arduino IDE to write the code for both the panelboard and the mainboard microcontrollers. Below is the code of the mainboard.#include "Adafruit_SHTC3.h"
#include <RH_ASK.h>
#include <SPI.h>
#include <TaskScheduler.h>
void t1Callback();
void t2Callback();
void t3Callback();
Scheduler runner;
Task t1(30, TASK_FOREVER, &t1Callback);
Task t2(500, TASK_FOREVER, &t2Callback);
Task t3(10, TASK_FOREVER, &t3Callback);
Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();
#define heaterSW 12
#define coolerSW 8
#define humidSW 7
#define lightSW 5
#define lightSensor A7
int tempValue = 0, lightValue = 50, counter = 0;
sensors_event_t humidity, temp;
RH_ASK rf_driver(2000, 2, 15);
void setup() {
shtc3.begin();
rf_driver.init();
runner.init();
runner.addTask(t1);
runner.addTask(t2);
runner.addTask(t3);
t1.enable();
t2.enable();
t3.enable();
pinMode(heaterSW, OUTPUT);
pinMode(coolerSW, OUTPUT);
pinMode(humidSW, OUTPUT);
pinMode(lightSW, OUTPUT);
pinMode(lightSensor, INPUT);
digitalWrite(heaterSW, LOW);
digitalWrite(coolerSW, LOW);
digitalWrite(humidSW, LOW);
digitalWrite(lightSW, LOW);
}
void loop() {
runner.execute();
}
void t1Callback() {
//--------------------------Data Collection---------------------
tempValue = map(analogRead(lightSensor), 0, 1023, 0, 99) + tempValue;
counter ++;
if (counter == 5)
{
lightValue = tempValue / 5;
counter = 0;
tempValue = 0;
shtc3.getEvent(&humidity, &temp);
}
}
void t2Callback() {
//-------------------Transmitter--------------------------------
static char trBuffer[20];
sprintf(trBuffer, "P:%d:%d:%d#", int(round(temp.temperature)), int(round(humidity.relative_humidity)), lightValue);
rf_driver.send((uint8_t *)trBuffer, strlen(trBuffer));
rf_driver.waitPacketSent();
}
void t3Callback() {
//--------------------Receiver----------------------------------
char buf[12];
uint8_t buflen = sizeof(buf);
if (rf_driver.recv(buf, &buflen))
{
buf[buflen - 1] = 0;
if (buf[0] == 'M')
{
if (buf[2] == 'W' && buf[3] == '1') {
digitalWrite(coolerSW, LOW);
digitalWrite(heaterSW, HIGH);
}
if (buf[2] == 'W' && buf[3] == '0') digitalWrite(heaterSW, LOW);
if (buf[2] == 'C' && buf[3] == '1') {
digitalWrite(heaterSW, LOW);
digitalWrite(coolerSW, HIGH);
}
if (buf[2] == 'C' && buf[3] == '0') digitalWrite(coolerSW, LOW);
if (buf[6] == '1') digitalWrite(humidSW, HIGH);
if (buf[6] == '0') digitalWrite(humidSW, LOW);
if (buf[9] == '1') digitalWrite(lightSW, HIGH);
if (buf[9] == '0') digitalWrite(lightSW, LOW);
}
}
}
You must install several external libraries to be able to modify and re-compile the code if you like. The first one is the Adafruit SHTC3 library [8], the second is the RadioHead Packet Radio library [9], the third is the TaskScheduler library [10], and the last one is the Easy Nextion library [11]. I have provided the complied HEX file for the panelboard [12] and the mainboard [13] as well. Below is the code for the panelboard.#include <RH_ASK.h>
#include <SPI.h>
#include "EasyNextionLibrary.h"
#include <TaskScheduler.h>
void t1Callback();
void t2Callback();
void t3Callback();
Scheduler runner;
Task t1(10, TASK_FOREVER, &t1Callback);
Task t2(10, TASK_FOREVER, &t2Callback);
EasyNex myNex(Serial);
RH_ASK rf_driver(2000, 15, 14);
char temp[2];
char buf[20];
char controlMessage[11];
int tempSet = 25, humidSet = 30, lightSet = 50;
char highTempTol = 1, lowTempTol = 1, highHumidTol = 2, highLightTol = 5;
bool heater = true, cooler = false, dataReceived = false;;
void setup() {
rf_driver.init();
myNex.begin(9600);
runner.init();
runner.addTask(t1);
runner.addTask(t2);
t1.enable();
t2.enable();
controlMessage[0] = 'M';
controlMessage[1] = ':';
controlMessage[4] = ':';
controlMessage[5] = 'H';
controlMessage[7] = ':';
controlMessage[8] = 'L';
controlMessage[10] = '#';
}
void loop() {
runner.execute();
}
void t1Callback() {
myNex.NextionListen();
}
void t2Callback() {
//---------------------------Data Reception--------------
uint8_t buflen = sizeof(buf);
if (rf_driver.recv(buf, &buflen))
{
buf[buflen - 1] = 0;
if (buf[0] == 'P')
{
temp[0] = buf[2];
temp[1] = buf[3];
myNex.writeNum("temp.val", atoi(temp));
temp[0] = buf[5];
temp[1] = buf[6];
myNex.writeNum("humid.val", atoi(temp));
temp[0] = buf[8];
temp[1] = buf[9];
myNex.writeNum("light.val", atoi(temp));
//-------------------------------Heater--------------------
temp[0] = buf[2];
temp[1] = buf[3];
if ((tempSet > atoi(temp)) && heater)
{
controlMessage[2] = 'W';
controlMessage[3] = '1';
}
if ((tempSet <= (atoi(temp) - highTempTol)) && heater)
{
controlMessage[2] = 'W';
controlMessage[3] = '0';
}
//-------------------------------Cooler--------------------
if ((tempSet < atoi(temp)) && cooler)
{
controlMessage[2] = 'C';
controlMessage[3] = '1';
}
if ((tempSet >= (atoi(temp) + lowTempTol)) && cooler)
{
controlMessage[2] = 'C';
controlMessage[3] = '0';
}
//----------------------------Humidifier-------------------
temp[0] = buf[5];
temp[1] = buf[6];
if ((humidSet > atoi(temp)))
{
controlMessage[6] = '1';
}
if ((humidSet <= (atoi(temp) - highHumidTol)))
{
controlMessage[6] = '0';
}
//----------------------------Light-------------------
temp[0] = buf[8];
temp[1] = buf[9];
if ((lightSet > atoi(temp)))
{
controlMessage[9] = '1';
}
if ((lightSet <= (atoi(temp) - highLightTol)))
{
controlMessage[9] = '0';
}
//------------------------------Delay--------------------------
for (int i = 0; i < 1000; i++);
//------------------------Transmit-----------------------------
rf_driver.send((uint8_t *)controlMessage, strlen(controlMessage));
rf_driver.waitPacketSent();
}
}
}
void trigger0() {
tempSet--;
}
void trigger1() {
tempSet++;
}
void trigger2() {
humidSet--;
}
void trigger3() {
humidSet++;
}
void trigger4() {
lightSet--;
}
void trigger5() {
lightSet++;
}
void trigger6() {
if (myNex.readNumber("state.val") == 0) {
heater = true;
cooler = false;
}
if (myNex.readNumber("state.val") == 1) {
heater = false;
cooler = true;
}
}
4. Fuse BitsAs I mentioned earlier, you should use an external AVR ISP programmer (such as the cheap USBasp [14], official Atmel programmer, or whatever similar) to program the microcontroller of both the panelboard and the mainboard. That’s why I have provided an ISP interface for the boards. To compile the code, you should select Arduino Nano in the “board” selection menu. To generate the HEX file, you can press Ctrl + Alt + S.Also, don’t forget to program the fuse bits. You should program the clock source to use an external high-frequency crystal oscillator (above 8MHz) and CKDIV8 should not be programmed (the clock should NOT be divided by 8). As a result, the fuse bits should be as follows: HIGH: 0xFF, Low: 0xFF, EXTENDED: 0xFF.5. Nextion DisplayAs it is clear in the YouTube video, I used a 4.3” Nextion HMI Display, Intelligent Series (Model: NX4827P043-011C-Y) [15]. The TFT file is available for download [16]. You must copy-paste this file into a MicroSD card and upgrade the Flash memory of your Nextion Display. There are many tutorials about this, so I skip this step. Figure 7 shows a picture of this display.Figure 74.3” Nextion HMI Display, Intelligent Series6. Assembly and TestFigure 8 shows the assembled PCB boards and the Nextion display. The smallest component package size is 0805, you shouldn’t have any problem in soldering the components, however, if you have some difficulties to purchase the components or there is no time for hand soldering, you can order the boards assembled. The GUI is user-friendly and easy to use, please watch the YouTube video completely to learn the adjustments.Figure 8A view of the assembled and operation of the boards and display7. Shielded Cable for TEMT6000 SensorIf you run the board in a noisy environment or if the sensor is more than 1 meter away from your board, I recommend you use a shielded cable to connect the TEMP6000 sensor to the board. Your shielded cable should have 3 inner wires and one outer shield. To follow the EMC rules, the shield is connected to the Ground at the mainboard side, but the shield should not be connected anywhere at the sensor side. If you also connect the shield to the Ground near the sensor, it creates a ground loop. Figure 9 shows this type of connection.Figure 9TEMT6000 shielded wire connection7. References[1]: L7805: https://octopart.com/l7805cp-stmicroelectronics-526753?r=sp[2]: SMBJ5CA: https://octopart.com/rnd+smbj5ca-rnd+components-103950670?r=sp[3]: 78L05: https://octopart.com/ua78l05cpk-texas+instruments-525289?r=sp[4]: ATMega328: https://octopart.com/atmega328pb-anr-microchip-77760227?r=sp[5]: Si2302: https://octopart.com/si2302cds-t1-e3-vishay-44452855?r=sp[6]: LM1-5D: https://octopart.com/lm1-5d-rayex-53719411?r=sp[7]: Altium Designer: https://www.altium.com/yt/myvanitar[8]: Adafruit SHTC3: https://github.com/adafruit/Adafruit_SHTC3[9]: RadioHead Packet Radio: http://www.airspayce.com/mikem/arduino/RadioHead/[10]: TaskScheduler: https://github.com/arkhipenko/TaskScheduler[11]: Easy Nextion: https://github.com/Seithan/EasyNextionLibrary[12]: HEX file (PanelBoard): https://drive.google.com/file/d/1AEGvovvZIZ5yNiNJHPkdy8_8rUAmK4ac/view?usp=share_link[13]: HEX file (MainBoard): https://drive.google.com/file/d/1LuS8Jv6xVSV1e6sairXMlE9ONt7EgDSN/view?usp=share_link[14]: USBasp Programmer: https://www.fischl.de/usbasp/[15]: Nextion Display: https://bit.ly/3dY30gw[16]: Nextion TFT File: https://drive.google.com/file/d/1NWkGv4OHpM4tbhi14wY2tCHhkZT-QGWA/view?usp=share_link