1. Blog>
  2. Wireless Home Automation (Control and Monitoring) Using a Nextion HMI Display

Wireless Home Automation (Control and Monitoring) Using a Nextion HMI Display

by: Dec 30,2022 6359 Views 1 Comments Posted in Technology

By Hesam Moshiri, Anson Bao

Copyright: Attribution-NonCommercial-NoDerivs (CC BY-NC-ND)


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 :-)


Specifications

Connectivity: Wireless ASK, 315MHz (or 433MHz)

Parameters: Temperature, Humidity, Ambient Light

Wireless Coverage: 100 to 200m (with Antennas)

Display: 4.3” Graphical, Capacitive-Touch

Input 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 Analysis

Figure 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 1

Schematic diagram of the panelboard

Figure 2

Schematic diagram of the mainboard


1. Mainboard

The mainboard circuit consists of 5 main parts: the power supply, ASK transceivers, Sensors, Microcontroller, and Relay drivers.


1-1: Power Supply

CON-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 Transceivers

RE 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 3

ASK Transmitter and Receiver modules

1-3: Sensors

I 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 4

TEMT6000 and SHTC3 modules

1-4: Microcontroller

The 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 Drivers

The 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. Panelboard

There 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 Layout

Figure 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 5

PCB layout of the wireless home automation device (Altium)

Figure 6

Assembly drawings


4. Code

I used the Arduino IDE to write the code for both the panelboard and the mainboard microcontrollers. Below is the code of the mainboard.


Main code here:

#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.


Panel code here:

#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 Bits

As 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 Display

As 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 7

4.3” Nextion HMI Display, Intelligent Series


6. Assembly and Test

Figure 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 8

A view of the assembled and operation of the boards and display


7. Shielded Cable for TEMT6000 Sensor

If 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 9

TEMT6000 shielded wire connection


8. Bill of Materials

Figure 10 and figure 11 show the bill of materials for the project. The Octopart website is not just a fast search engine for electronic components but also a very nice tool to build any kind of BOM for free.

Figure 10

Bill of materials of the mainboard

Figure 11

Bill of materials of the panelboard


7. 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




Join us
Wanna be a dedicated PCBWay writer? We definately look forward to having you with us.
  • Comments(1)
You can only upload 1 files in total. Each file cannot exceed 2MB. Supports JPG, JPEG, GIF, PNG, BMP
0 / 10000
    Back to top