We often want to read sensors data to monitor various values such as temperature, humidity, gas concentration, luminosity and etc.
However, there are cases where the use of wired systems for reading these sensors becomes impracticable due to the distance between the measurement point and the sensor reading system or the difficulty in carrying out the installation of the cabling necessary to carry out the installation of the sensor.
In these cases remote reading is an alternative to be used, there are several radio transceivers that can be used, such as HC 12, NRF24L01, Lora module, among others.
In this article, we will learn how to create a PCBGOGO Printed Circuit Board and use the HC 12 radio transceiver/module with an Arduino Nano with a DHT 11 temperature and humidity sensor that will be the sensor and an HC 12 with the Arduino Uno that will be the base.
The sensor performs the temperature and humidity measurement and sends these measurements to the base.
The sensor also has two LEDs that can be accessed after pressing one of the buttons on the base.
At the base is an Arduino Uno with an LCD display to display the data measured with the sensor.
Therefore, through this article you will learn:
- Perform the circuit assembly on the protoboard
- Understand the functioning of the HC 12 module
- Perform the communication of the Arduino Nano / Arduino Nano with the HC 12 module
- Read the humidity and temperature sensor
- Remote activation
- Creation of a simple communication protocol for sending the values of the measurement performed.
- Develop the PCBGOGO Printed Circuit Board to construct the project
Now, we will start the complete presentation of the development of the Remote Device Control project using the HC 12 module and the PCBGOGO Printed Circuit Board.
Developing the Project Remote Reading of Temperature and humidity using the HC12 ModuleAs previously mentioned, the project consists of creating a system for remote monitoring of two quantities: temperature and humidity and remote actuation of actuators.
The HC 12 module is a radio transceiver and its operating frequency is 433.4 MHz to 473 MHz.
It is possible to connect two types of antennas in this module, a helical antenna that comes with the module or another antenna to be connected to the UFL connector.
These modules usually come with some factory settings, so that we can communicate 2 HC 12 modules with an Arduino Uno, Nano we need to adjust some parameters like communication speed, communication channel, operation mode using AT commands.
To configure the module, the set pin must be connected to the GND as shown in figure 1 for the module to enter configuration mode.
It is recommended to supply the HC 12 module with an external source with 5 V, as it has some serial USB converters that do not supply enough current to supply the module.
The GND of the serial USB converter must be connected with the GND of the power supply.
As previously mentioned, the project consists of creating a system for remote monitoring of two quantities: temperature and humidity and remote actuation of actuators.
The HC 12 module is a radio transceiver and its operating frequency is 433.4 MHz to 473 MHz.
It is possible to connect two types of antennas in this module, a helical antenna that comes with the module or another antenna to be connected to the UFL connector.
These modules usually come with some factory settings, so that we can communicate 2 HC 12 modules with an Arduino Uno, Nano we need to adjust some parameters like communication speed, communication channel, operation mode using AT commands.
To configure the module, the set pin must be connected to the GND as shown in figure 1 for the module to enter configuration mode.
It is recommended to supply the HC 12 module with an external source with 5 V, as it has some serial USB converters that do not supply enough current to supply the module.
The GND of the serial USB converter must be connected with the GND of the power supply.
To configure the module, the set pin must be connected to the GND as shown in figure 1. This process allows the module to enter configuration mode.
It is recommended to supply the HC 12 module with an external 5V source, as it has some USB-SERIAL converters that do not provide enough current to supply the module.
To improve the design, we will create a PCBGOGO Printed Circuit Board to ensure adequate power for the HC12.
The GND of the USB-SERIAL converter must be connected to the GND of the power supply.
Now, let's configure the HC 12 module. You can download the schematic in PCBGOGO Download Link.
Table 1 shows the main commands used to configure the module using AT commands.
The FU1 and FU2 modes have a low power consumption than the FU3 mode, so the FU1 and FU2 modes are modes to be used in applications that use batteries.
The FU1 mode operates with an electrical working current without transmitting 3.6 mA data.
The FU2 mode, on the other hand, operates with a working current of 80uA without transmitting data and supports only the speeds 1200 bps, 2400 bps, 4800 bps.
The operating modes are not compatible with each other, so the two modules must be configured in the same operating mode, whether FU1, FU2, FU3.
Before we start configuring the module, we must download the Termite software available at the link: Download Termite Software
After making the connections with the HC 12 module and the serial USB converter, open the Termite Software.
Configuring the HC 12 module with Termite software.
After opening the Termite software, we must click on Settings to make some settings according to figure 3.
After making the settings in the Termite software, click Ok and then COM3 to connect the USB - serial converter with the HC 12 module to the serial port that is connected.
Wait to connect the port with the Termite software and we type in the command bar the command AT
If all goes well, OK will appear as in figure 4
After this initial test we will configure the HC 12 module with the following parameters:
- Velocidad de comunicación serial: 9600 bps
- Canal de comunicação 5
- Potencia de transmisión de 11 dBm
- Modo de operación FU3
After performing the configuration for the first module, we repeat the steps to configure the second module.
After configuring both modules, we can connect to the Arduino as shown in figure 8 for the base and figure 9 for the sensor.
The Arduino Uno will be the base that will perform the reading of two buttons and when the button B0 is pressed, a command will be sent to light the red led and when the button B1 is pressed the blue led will be lit.
To turn off the LEDs just press B0 or B1 to turn off the respective led.
In addition to reading the buttons and sending commands to the sensor, the base will receive the values of the measurements made by the sensor and will display these values on an I2C display.
In Arduino Uno, we will have the B0 button connected to digital pin 2 of Arduino Uno and the B1 button connected to digital pin 3 of Arduino Uno. You can download the schematic in PCBGOGO Download Link.
Both buttons are activated at a low logic level when the buttons are pressed.
The LCD display used has I2C communication because using this communication we save pins from the microcontroller used since the I2C communication uses only 4 wires to communicate with the VCC, GND, SDA, and SCL microcontroller.
- VCC will be connected at 5 V
- GND in GND
- SDA on pin A4 of Arduino Uno
- SCL on pin A5 of Arduino Uno
Now, let's go to the list of components needed to assemble the base module circuit
- 01 Protoboard
- 01 Arduino Uno
- 02 Buttons (Touch key)
- 02 10 KΩ resistors
- 10 Jumpers
- 01 HC 12 module + helical antenna
- 16 x 2 I2C LCD display
The Tx pin of the HC 12 module is connected to the digital pin 8 of the Arduino and the RX pin of the HC 12 module is connected to the digital pin 7 of the Arduino Uno.
We will use a library called Serial software to configure these pins 7 and 8 as serial communication pins, that is, we will emulate serial communication by software.
The HC 12 connection on the Arduino Nano that will be the sensor is the same as the base circuit, the difference will be the presence of the LEDs on digital pins 4 and 3 and the presence of the DHT 22/DHT 11 sensor.
For the DHT 11 sensor to work, it is necessary to place a pull-up resistor between the data pin and the VCC supply according to the circuit in figure 9. Download the schematic in PCBGOGO Download Link.
After assembling the base and sensor circuits, we will program them.
#include <SoftwareSerial.h> // Inclui a biblioteca Software Serial
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd (0x27,2,1,0,4,5,6,7,3,POSITIVE);
SoftwareSerial HC12(8,7); // 8 RX vai ligado no Tx do modulo HC 12, 7 TX vai ligado no RX do módulo
#define B0 2
#define B1 3
float temp = 0;
int umi =0;
byte RX[4];
unsigned long interval =0;
void setup()
{
pinMode(B0,INPUT);
pinMode(B1,INPUT);
Serial.begin(9600);
HC12.begin(9600);
lcd.begin(16,2);
}
void loop()
{
if(!digitalRead(B0))
{
// Serial.println("B0 pressionado ");
// Serial.print('1');
HC12.print('1');
while(digitalRead(B0)==0);
}
if(!digitalRead(B1))
{
HC12.print('2');
while(digitalRead(B1)==0);
}
if(millis() - interval >=3000)
{
interval = millis();
lcd.clear();
for(int i=0; i<4;i++)
{
RX[i]=0;
}
while(HC12.available()>0)
{
for(int i=0; i<4;i++)
{
RX[i] =HC12.read();
}
}
temp =((RX[0]*256) +RX[1])/100.0;
umi = ((RX[2]*256)+RX[3])/100;
if(temp<0 ||temp >100 || umi<0)
{
Serial.print("Erro de leitura no sensor ");
lcd.setCursor(0,0);
lcd.print("TEMP: ");
lcd.setCursor(6,0);
lcd.print("-");
lcd.setCursor(12,0);
lcd.setCursor(0,1);
lcd.print("UMID : ");
lcd.setCursor(6,1);
lcd.print("-");
}
else
{
Serial.print("Temperatura : ");
Serial.print( temp );
Serial.println(" *C");
Serial.print("Umidade : ");
Serial.print( umi );
Serial.println(" %");
lcd.setCursor(0,0);
lcd.print("TEMP: ");
lcd.setCursor(6,0);
lcd.print(temp);
lcd.setCursor(12,0);
lcd.print("*C");
lcd.setCursor(0,1);
lcd.print("UMID : ");
lcd.setCursor(7,1);
lcd.print(umi);
lcd.setCursor(12,1);
lcd.print("%");
}
}
}
First, we included the serial software library to be able to use any digital pin as a TX or RX pin to be used as a data transmitter.
#include <SoftwareSerial.h> // Inclui a biblioteca Software Serial
We create an object with the pins that will perform serial communication.
SoftwareSerial HC12(8,7); // 8 RX vai ligado no Tx do modulo HC 12, 7 TX vai ligado no RX do módulo
We name pins 2 B0 and 3 B1 using define.
#define B0 2
#define B1 3
We declare the variables temp and umi that will read the information received by the base in the vector of type byte RX [4].
float temp =0;
int umi =0;
byte RX[4];
unsigned long interval =0; // variavel responsável por armazenar o tempo do Millis.
We include the Wire library, which is the library responsible for carrying out I2C communication between the microcontroller and an I2C device.
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd (0x27,2,1,0,4,5,6,7,3,POSITIVE);
Creates the LCD object with the address and pinout and black light.
In the void setup function, pins 2 and 3 are configured as inputs, configure the serial communication speed of the USB, and of the serial communication with the HC12 module and initiates communication with the LCD display.
void setup()
{
pinMode(B0,INPUT);
pinMode(B1,INPUT);
Serial.begin(9600);
HC12.begin(9600);
lcd.begin(16,2);
}
After making the settings in the void setup function, go to the void loop function, which is where the logic of our program is.
if(!digitalRead(B0))
{
// Serial.println("B0 pressionado ");
// Serial.print('1');
HC12.print('1');
while(digitalRead(B0)==0);
}
if(!digitalRead(B1))
{
HC12.print('2');
while(digitalRead(B1)==0);
}
if(millis() - interval >=3000)
{
interval = millis();
lcd.clear();
for(int i=0; i<4;i++)
{
RX[i]=0;
while(HC12.available()>0)
{
for(int i=0; i<4;i++)
{
RX[i] =HC12.read();
}
}
temp =((RX[0]*256) +RX[1])/100.0;
umi = ((RX[2]*256)+RX[3])/100;
if(temp<0 ||temp >100 || umi<0)
{
Serial.print("Erro de leitura no sensor ");
lcd.setCursor(0,0);
lcd.print("TEMP: ");
lcd.setCursor(6,0);
lcd.print("-");
lcd.setCursor(12,0);
lcd.setCursor(0,1);
lcd.print("UMID : ");
lcd.setCursor(6,1);
lcd.print("-");
}
else
{
Serial.print("Temperatura : ");
Serial.print( temp );
Serial.println(" *C");
Serial.print("Umidade : ");
Serial.print( umi );
Serial.println(" %");
lcd.setCursor(0,0);
lcd.print("TEMP: ");
lcd.setCursor(6,0);
lcd.print(temp);
lcd.setCursor(12,0);
lcd.print("*C");
lcd.setCursor(0,1);
lcd.print("UMID : ");
lcd.setCursor(7,1);
lcd.print(umi);
lcd.setCursor(12,1);
lcd.print("%");
}
}
}
In the void loop function, we read the buttons using digitalRead and if the B0 button is pressed, it will send the value 1 to the HC 12 module. Then, the HC12 module will transmit this information to the receiver HC 12 over the air via through electromagnetic waves.
The base will also receive the values measured by the sensor every 3 seconds.
For pressed B1, the value 2 will be sent to the HC 12 module and the HC 12 module will transmit this information to the receiving HC 12 through the air through electromagnetic waves.
To turn off the respective led, just press the B0 button again to turn off the red led and B1 to turn off the blue led.
Every 3 seconds we receive the measurements taken by the sensor.
if(millis() - interval >=3000)
{
interval = millis();
lcd.clear();
for(int i=0; i<4;i++)
{
RX[i]=0;
}
while(HC12.available()>0)
{
for(int i=0; i<4;i++)
{
RX[i] =HC12.read();
}
}
}
While I am receiving data through the HC12 module I store these values in the RX vector up to position 4.
After receiving this data, it is necessary to convert these values to the correct measured value.
For this, we use the equation below:
temp =((RX[0]*256) +RX[1])/100.0;
To convert the humidity, position 2 of the vector is multiplied by 256 (1 byte) and added to position 3 of the RX vector, after adding, divide the value by 100.
umi = ((RX [2] * 256) + RX [3]) / 100;
After performing this conversion, we have the temperature and humidity values.
That done we check if the values are incorrect using an if condition.
if(temp<0 ||temp >100 || umi<0)
{
Serial.print("Erro de leitura no sensor ");
lcd.setCursor(0,0);
lcd.print("TEMP: ");
lcd.setCursor(6,0);
lcd.print("-");
lcd.setCursor(12,0);
lcd.setCursor(0,1);
lcd.print("UMID : ");
lcd.setCursor(6,1);
lcd.print("-");
}
//Se estiverem corretos escrevemos os valores no display lcd.
else
{
Serial.print("Temperatura : ");
Serial.print( temp );
Serial.println(" *C");
Serial.print("Umidade : ");
Serial.print( umi );
Serial.println(" %");
lcd.setCursor(0,0);
lcd.print("TEMP: ");
lcd.setCursor(6,0);
lcd.print(temp);
lcd.setCursor(12,0);
lcd.print("*C");
lcd.setCursor(0,1);
lcd.print("UMID : ");
lcd.setCursor(7,1);
lcd.print(umi);
lcd.setCursor(12,1);
lcd.print("%");
}
After programming the base, go to the sensor code.
#include <SoftwareSerial.h> // Inclui a biblioteca Software Serial
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN,DHTTYPE);
SoftwareSerial HC12(8,7); // 8 RX vai ligado no Tx do modulo HC 12, 7 TX vai ligado no RX do módulo
#define red 4
#define blue 3
char comando = 0;
unsigned t_anterior =0,t1=0,t_atual=0;
float temp =0;
int t=0,umidade =0,u=0;;
byte TX[4];
void setup()
{
pinMode(red,OUTPUT);
pinMode(blue,OUTPUT);
Serial.begin(9600);
HC12.begin(9600);
Serial.println("Receptor");
digitalWrite(blue,1);
delay(300);
digitalWrite(blue,0);
delay(300);
dht.begin();
}
void loop()
{
if((millis() - t_anterior)>=3000)
{
t_anterior = millis();
temp = dht.readTemperature();
umidade = dht.readHumidity();
}
while(HC12.available()>0)
{
comando = HC12.read();
//Serial.println(comando);
switch(comando)
{
case '1' : digitalWrite(red,!digitalRead(red));
break;
case '2': digitalWrite(blue,!digitalRead(blue));
break;
}
if(isnan(temp) || isnan(umidade))
{
Serial.println("Erro na leitura do sensor ");
}
else
{
t= (int)(temp*100);
u=(int)(umidade*100);
TX[0] = t/256;
TX[1] =t%256;
TX[2] = u/256;
TX[3] = u%256;
for(int i=0; i<4; i++)
{
HC12.write(TX[i]);
}
Serial.print("Temperatura :" );
Serial.print(temp );
Serial.println(" *C");
Serial.print("Umidade :" );
Serial.print( umidade );
Serial.println(" %");
}
}
}
The first task to be done in the receiver's code is to include the serial software library to be able to use pins 7 and 8 of the Arduino Nano to perform serial communication.
In the code block below, we define the objects, libraries, and pin definitions with names to be used throughout the code.
#include <SoftwareSerial.h> // Inclui a biblioteca Software Serial
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN,DHTTYPE);
SoftwareSerial HC12(8,7); // 8 RX vai ligado no Tx do modulo HC 12, 7 TX vai ligado no RX do módulo
After that, we made the declaration of all the variables of the project, as presented below.
char comando = 0;
unsigned t_anterior =0,t1=0,t_atual=0;
float temp =0;
int t=0,umidade =0,u=0;;
byte TX[4];
After that, we have the void setup function to perform the settings of pins 4 and 3 as an output, the serial communication speed of the HC 12 module, and the USB port.
Finally, we start the communication with the DHT 11 sensor and flash the blue LED when we turn on the receiver.
void setup()
{
pinMode(red,OUTPUT);
pinMode(blue,OUTPUT);
Serial.begin(9600);
HC12.begin(9600);
Serial.println("Receptor");
digitalWrite(blue,1);
delay(300);
digitalWrite(blue,0);
delay(300);
dht.begin();
}
Now, let's go to the void loop function, which is where our program logic is.
void loop()
{
if((millis() - t_anterior)>=3000)
{
t_anterior = millis();
temp = dht.readTemperature();
umidade = dht.readHumidity();
}
while(HC12.available()>0)
{
comando = HC12.read();
//Serial.println(comando);
switch(comando)
{
case '1' : digitalWrite(red,!digitalRead(red));
break;
case '2': digitalWrite(blue,!digitalRead(blue));
break;
}
if(isnan(temp) || isnan(umidade))
{
Serial.println("Erro na leitura do sensor ");
}
else
{
t= (int)(temp*100);
u=(int)(umidade*100);
TX[0] = t/256;
TX[1] =t%256;
TX[2] = u/256;
TX[3] = u%256;
for(int i=0; i<4; i++)
{
HC12.write(TX[i]);
}
Serial.print("Temperatura :" );
Serial.print(temp );
Serial.println(" *C");
Serial.print("Umidade :" );
Serial.print( umidade );
Serial.println(" %");
}
}
}
First, we check if 3 s has passed and then we read the DHT 11 sensor.
if((millis() - t_anterior)>=3000)
{
t_anterior = millis();
temp = dht.readTemperature();
umidade = dht.readHumidity();
}
This DHT sensor has a response time of 2 seconds, so we have to time it before reading to obtain more stable values.
The millis function is used, as we do not prevent the microcontroller from carrying out other actions while waiting for 3 s to read the sensor.
To read the DHT 11 sensor, we use the functions below to read temperature and humidity.
dht.readTemperature();
dht.readHumidity();
After taking the readings, we check if there is any information received via serial.
while(HC12.available()>0)
{
comando = HC12.read();
//Serial.println(comando);
switch(comando)
{
case '1' : digitalWrite(red,!digitalRead(red));
break;
case '2': digitalWrite(blue,!digitalRead(blue));
break;
}
We store the information received in the command variable and check if the information received is 1 or 2 and turn on the corresponding led.
After checking if we received any information via the serial, we check if the measurement of the DHT 11 sensor is correct.
If it is not correct, we display the message that the sensor reading failed.
if(isnan(temp) || isnan(umidade))
{
Serial.println("Erro na leitura do sensor ");
}
If the sensor was read correctly, we have to perform some conversions on this information before sending it via serial communication using the HC 12 module.
else
{
t= (int)(temp*100);
u=(int)(umidade*100);
TX[0] = t/256;
TX[1] =t%256;
TX[2] = u/256;
TX[3] = u%256;
for(int i=0; i<4; i++)
{
HC12.write(TX[i]);
}
Serial.print("Temperatura :" );
Serial.print(temp );
Serial.println(" *C");
Serial.print("Umidade :" );
Serial.print( umidade );
Serial.println(" %");
}
}
First, we convert the temperature value to the indoor type and multiply that value by 100 and store the value in variable t.
t = (int) (temp * 100);
For humidity we perform the same procedure to convert humidity to the entire type
u = (int) (humidity * 100);
An integer type has two bytes and to transmit this information we have to divide it into two bytes.
The most significant part of the temperature will be stored at position 0 of the TX vector and the least significant part will be stored at position 1 of the vector.
TX [0] = t / 256;
TX [1] = t% 256;
For humidity, we perform the same conversion procedure
TX [2] = u / 256;
TX [3] = u% 256;
The most significant part of the moisture is saved at position 2 of the TX vector and the least significant part is saved at position 3 of the TX vector.
To transmit temperature and humidity measurements, we use the Serial.write command in the HC 12.write case.
for(int i=0; i<4; i++)
{
HC12.write(TX[i]);
}
First, we put the TX vector inside a repeat command so that the vector can be traversed and so all the values inside the vector can be sent using the HC12.write command.
With the command HC12.write the measurement values are sent to the base.
These are the codes used to program Arduinos.
In figure 10 we have the physical assembly of the base circuit.
Finally, we have reached the end of the project and now, we want to present printed circuit board modules for you to assemble your project.
PCBGOGO Printed Circuit BoardFor this project, we developed two PCBGOGO printed circuit boards for you to build your system at home.
You can access the download link and download the assembly files and schematics. To purchase, visit the PCBGOGO website, purchase a $50 coupon, and purchase your PCB.
Below is presented the two PCB's in 3D View.
ASDF
Comments