Long Range, 1.8km, Arduino to Arduino Wireless Communication With the HC-12.

213,341

1,045

178

Introduction: Long Range, 1.8km, Arduino to Arduino Wireless Communication With the HC-12.

About: I like to make stuff in my free time. Especially programming, cooking, electronics etc. Lately I'm making tutorials about stuff I made the last few years.

In this instructable you will learn how to communicate between Arduinos over a long distance up to 1.8km in open air.

The HC-12 is a wireless serial port communication module that is very useful, extremely powerful and easy to use.

First you will learn how to make a wireless instant messenger with the least effort possible.

Then we will move on to light up an LED with a push button and then you will learn a few useful string functions and operations for serial communication.

The last part of the instructable is not necessary but you will learn how to use the HC-12 module like a pro.

In this part you will learn how to enter the modules setup mode to change the baud rate, transmission distance and so on.

And finally you will learn how to connect an external SMA antenna.

Follow the rest of this instructable to find out how easy it is to become a pro in wireless serial communication.

Step 1: Parts List

  • 2 x Arduino (got my Arduino clones for 3 dollar here)
  • 2 x HC-12 modules (got mine here )
  • Wires
  • Breadboard.
  • 10 k resistor
  • push button
  • Exercise files here

Step 2: Wiring and Setup

First we have to solder the spring antennas to both of the HC-12 chips.

I also soldered some pins on the HC-12 module to make it easy to use on a breadboard.

We will use 2 Arduinos with a HC-12 module connected to each of them as you can see in the image.

For both Arduinos we connect pin 2 to TX and pin 3 to RX. Ground to ground and VCC to 5v.

At one Arduino we will add a push button as you can see in the image.

To work with 2 Arduinos on 1 computer, we have to open 2 instances of the Arduino IDE. This means that we have to open the Arduino software 2 times. This is not the same as “file → New”

Save the one with the push button connected as “HC-12 sender” and the other as “HC-12 receiver”.

Make sure that the right ports are selected for each of the Arduinos.

Step 3: Instant Wireless Messenger, Toggle Button, Momentary Button and a Few Useful Functions

Wireless Messenger

We will start by making an instant wireless messenger.

Copy the content from the file “HC-12 messenger send/receive.txt” in the ZIP archive and paste it to each of the Arduino instances. The code is the same for both Arduinos.

After uploading the code, open the serial monitor for both instances.

Now start typing in both serial monitors to start a chat.

Even your Arduinos are connected to the same computer, the communication is wireless.

Toggle Button

A toggle button is used often in electronics. The principle is very simple. You press a button once to turn on the LED and press the same button again to turn of the LED.

Copy and paste the content of the “HC-12 Toggle Button Send.txt” to the “HC-12 sender” instance and the the “HC-12 Toggle Button Receive.txt” to the “HC-12 receiver” instance and upload.

When you push the button, you should see the LED light up. When you push the button again, the LED turns off.

A few validators like timing and button code are used in order to make sure this example works perfect.

Momentary Button

A momentary button is pretty straightforward. While pushing the button, the LED lights up. When releasing the button, the LED turns off.

Copy and paste the content of the “HC-12 Momentary Button Send.txt” to the “HC-12 sender” instance and the the “HC-12 Momentary Button Receive.txt” to the “HC-12 receiver” instance and upload.

Some useful functions and operators

There are a few useful functions and operators that come in handy when you want to convert or spit a string and convert it to a decimal and so on.

Look at the file “HC-12 Useful Functions and Operators Send.txt” and “ HC-12 Useful Functions and Operators Receive.txt”.

The send sketch sends the string “test123” on button press.

The receive sketch reads the string, split it and convert it to an integer.

Step 4: Advanced Setup. Changing the HC-12 Settings With AT Commands

You can easily skip this section as it will cover some advanced chip settings. However I will cover the basics so you will be able to change the module's baud rate, transmission power, channels and working modes.

A full manual can be found in the ZIP archive under the name HC-12 User Manual.pdf

Connect the HC-12 as shown in the image and connect the Arduino to your computer.

Copy and paste the contents of the file named “HC-12 AT Commander.txt” from the ZIP archive and upload to your Arduino.

Open the serial monitor and type “AT”. If the module returns “OK”, the command mode is working.

Changing the baud rate

Type “AT+Bxxxx”.

The baud rate can be set to 1200bps, 2400bps,

4800bps, 9600bps, 19,200bps, 38,400bps, 57,600bps, or 115,200bps. The default

value is 9600bps.

Example: type “AT+B4800”. The module returns “OK+B4800”.

Changing the communication channel

Type “AT+Cxxx”.

The value can be a number from 001 to 127.

Every number is a 400KHz step. The working frequency of channel 100 is 473.0MHz.

Example: type “AT+C021”. The module returns “OK+C021”.

The module is now set to a working frequency of 441.4MHx

Note that both sending and receiving modules need to have the same frequency to communicate.

Changing the working mode of the module.

This can be FU1, FU2, FU4 or FU4 (FU4 at a baud rate of 1200 sets the chip to transmit up to 1800 meter in open air). See documentation for a full explanation.

Example: Type “AT+FU4”. The module returns “OK+FU4”.

Obtain all parameters from the module.

Type “AT+RX”.

The module should return something like this:

“OK+FU3

OK+B9600

OK+C001

OK+RP:+20dBm”.

More settings can be found in the “HC-12 User Manual.pdf” in the ZIP archive.

Step 5: Spring Antenna or SMA Antenna

The HC-12 modules come standard with a spring antenna. However you can connect an SMA antenna to the board.

There are whole books written about antennas and how they work. I don't want to go to deep into this subject.

The only thing to remember for now is that electronic circuitry can interfere with an antenna and therefore the HC-12 has a IPEX RF socket so you can separate the antenna from the board. This can help for better reception and transmission.

What you need is a IPEX to SMA extension cord and an SMA antenna.

I got my extension here and the antenna here.(check for male and female).

Make sure when you order that the male and female connections match.

You can push the cord on the IPEX connector and solder it on. On the other site of the cord you can screw on the SMA antenna.

Step 6: Final Note:

In this instructable you have learned how to use the HC-12 for long distance communications between Arduinos. You have learned how to make an instant messenger, a toggle button, a momentary button, how to use some string operators and functions, how to change the HC-12 settings and how to use a different antenna.

The making of this instructable took about 100 hours of research, editing, testing, writing and so on.

If this instructable was helpful for you, please click the favorite button and subscribe.

See you in the next instructable.

Other instructables you might like:

$2 Arduino. The ATMEGA328 as a stand-alone. Easy, cheap and very small. A complete guide.

How to fix bad Chinese Arduino clones

Facebook: https://www.facebook.com/OfficialTomHeylen

Donate to help me keep doing this work: https://www.paypal.me/TomHeylen/2usd

Share

    Recommendations

    • Fix It! Contest

      Fix It! Contest
    • Creative Misuse Contest

      Creative Misuse Contest
    • Metalworking Contest

      Metalworking Contest

    178 Discussions

    I want to transmit a temperature across and got a temperature sensor. How can I transmit it, would it be possible?

    20180517_093347.jpg
    1 more answer
    0
    None
    MSJ23

    Question 8 weeks ago

    Do HC-12 can communicate between more then two arduino's ?

    hey i have done all things as per suggested and all works fine

    BUT after testing i'm only getting 3 meter of transmission range at 9600bps

    Kindly provide solution to increase range

    my email id is singhanki990@gmail.com

    0
    None
    MidhunL

    Question 3 months ago

    how many channels could i transmit using hc 12 modules????

    could i replace nrf mudules...

    could i replace them with hc 12???

    Tom, nice job with the video. I am new to the HC-12 and it was very helpful.

    is it possible to make 1 hc12+arduino as a transmitter to send data to 4 set of hc-12+arduino as receiver together at same time.? waiting for you answer, thanx.

    1 reply

    Same Question...You got any Solution Bro???

    Nice, useful article. Just wondering usual weather changes like rain, sun, high humidity would affect this com media?

    0
    None
    KuongS

    5 months ago

    Hi! Tom I try to modify your exercise code momentary button send and received by add more button at sender and more LEDs at receiver then I face the problem on receiver.

    when I press button UP (arduino pin7) at sender side then led at receiver side ON.

    when I press button DW (arduino pin 8) at sender side then led at receiver side flash On/off.

    //////code sender.

    //HC-12 Momentary Button Send

    //Autor Tom Heylen tomtomheylen.com

    #include <SoftwareSerial.h>

    SoftwareSerial mySerial(2, 3); //RX, TX

    //int T = 5;

    int UP = 7;

    int DW = 8;

    int FW = 9;

    int RV = 10;

    int RFW = 11;

    int LFW = 12;

    boolean onOff = 0;

    void setup() {

    //pinMode(T,INPUT);

    pinMode(UP, INPUT);

    pinMode(DW, INPUT);

    pinMode(FW, INPUT);

    pinMode(RV, INPUT);

    pinMode(RFW, INPUT);

    pinMode(LFW, INPUT);

    mySerial.begin(9600);

    }

    void loop() {

    //int button_T_State = digitalRead(T);

    int button_UP_State = digitalRead(UP);

    int button_DW_State = digitalRead(DW);

    int button_FW_State = digitalRead(FW);

    int button_RV_State = digitalRead(RV);

    int button_RFW_State = digitalRead(RFW);

    int button_LFW_State = digitalRead(LFW);

    // if(button_T_State == 1){//if button is down

    // mySerial.println(1111);//send unique code to the receiver to turn on. In this case 1111

    // onOff = 1;//set boolean to 1

    // }

    // if(button_UP_State == 0 && onOff == 1){//Verifier to send off signal once

    // mySerial.println(0000);//send unique code to the receiver to turn off. In this case 0000

    // onOff = 0;

    // }

    if(button_UP_State == 1){//if button is down

    mySerial.println(2222);//send unique code to the receiver to turn on. In this case 1111

    onOff = 1;//set boolean to 1

    }

    if(button_UP_State == 0 && onOff == 1){//Verifier to send off signal once

    mySerial.println(0000);//send unique code to the receiver to turn off. In this case 0000

    onOff = 0;

    }

    if(button_DW_State == 1){//if button is down

    mySerial.println(3333);//send unique code to the receiver to turn on. In this case 1111

    onOff = 2;//set boolean to 1

    }

    if(button_DW_State == 0 && onOff == 2){//Verifier to send off signal once

    mySerial.println(0000);//send unique code to the receiver to turn off. In this case 0000

    onOff = 0;

    }

    if(button_FW_State == 1){//if button is down

    mySerial.println(4444);//send unique code to the receiver to turn on. In this case 1111

    onOff = 3;//set boolean to 1

    }

    if(button_FW_State == 0 && onOff == 3){//Verifier to send off signal once

    mySerial.println(0000);//send unique code to the receiver to turn off. In this case 0000

    onOff = 0;

    }

    if(button_RV_State == 1){//if button is down

    mySerial.println(5555);//send unique code to the receiver to turn on. In this case 1111

    onOff = 4;//set boolean to 1

    }

    if(button_RV_State == 0 && onOff == 4){//Verifier to send off signal once

    mySerial.println(0000);//send unique code to the receiver to turn off. In this case 0000

    onOff = 0;

    }

    if(button_RFW_State == 1){//if button is down

    mySerial.println(6666);//send unique code to the receiver to turn on. In this case 1111

    onOff = 5;//set boolean to 1

    }

    if(button_RFW_State == 0 && onOff == 5){//Verifier to send off signal once

    mySerial.println(0000);//send unique code to the receiver to turn off. In this case 0000

    onOff = 0;

    }

    if(button_LFW_State == 1){//if button is down

    mySerial.println(7777);//send unique code to the receiver to turn on. In this case 1111

    onOff = 6;//set boolean to 1

    }

    if(button_LFW_State == 0 && onOff == 6){//Verifier to send off signal once

    mySerial.println(0000);//send unique code to the receiver to turn off. In this case 0000

    onOff = 0;

    }

    delay(20);//delay little for better serial communication

    }

    ///////////////////////////////////////////Receiver

    //HC-12 Momentary Button Receive

    //Autor Tom Heylen tomtomheylen.com

    #include <SoftwareSerial.h>

    SoftwareSerial mySerial(2, 3); // RX, TX

    //int T =5;

    int M_UP = 7;

    int M_DW = 8;

    int M_FW = 9;

    int M_RV = 10;

    int M_RFW = 11;

    int M_LFW = 12;

    int signBeep= 6;

    unsigned long last = millis();//set timer

    void setup() {

    mySerial.begin(9600);

    //pinMode(T, OUTPUT);

    pinMode(M_UP, OUTPUT);

    pinMode(M_DW, OUTPUT);

    pinMode(M_FW, OUTPUT);

    pinMode(M_RV, OUTPUT);

    pinMode(M_RFW, OUTPUT);

    pinMode(M_LFW, OUTPUT);

    pinMode(signBeep,OUTPUT);

    Serial.begin(9600);

    }

    void loop() {

    // boolean M_UP_State = digitalRead(M_UP);//check if the M_UP is turned on or off. Returns 1 or 0

    // boolean M_DW_State = digitalRead(M_DW);//check if the M_DW is turned on or off. Returns 1 or 0

    // boolean M_FW_State = digitalRead(M_FW);//check if the M_FW is turned on or off. Returns 1 or 0

    // boolean M_RV_State = digitalRead(M_RV);//check if the M_RV is turned on or off. Returns 1 or 0

    // boolean M_RFW_State = digitalRead(M_RFW);//check if the M_RFW is turned on or off. Returns 1 or 0

    // boolean M_LFW_State = digitalRead(M_LFW);//check if the M_LFW is turned on or off. Returns 1 or 0

    if(mySerial.available() > 1){

    int input = mySerial.parseInt();//read serial input and convert to integer (-32,768 to 32,767)

    Serial.println(input);

    // if(input == 1111){//if LED is off and button code is ok

    // digitalWrite(T,HIGH);

    // }

    // if(input == 0000){//if LED is on and button code is ok

    // digitalWrite(T, LOW);

    // }

    if(input == 2222){//if LED is off and button code is ok

    digitalWrite(M_UP, HIGH);

    }

    if(input == 0000){//if LED is on and button code is ok

    digitalWrite(M_UP, LOW);

    }

    if(input == 3333){//if LED is off and button code is ok

    digitalWrite(M_DW, HIGH);

    }

    if(input == 0000){//if LED is on and button code is ok

    digitalWrite(M_DW, LOW);

    }

    if(input == 4444){//if LED is off and button code is ok

    digitalWrite(M_FW, HIGH);

    }

    if(input == 0000){//if LED is on and button code is ok

    digitalWrite(M_FW, LOW);

    }

    if(input == 5555){//if LED is off and button code is ok

    digitalWrite(M_RV, HIGH);

    }

    if(input == 0000){//if LED is on and button code is ok

    digitalWrite(M_RV, LOW);

    }

    if(input == 6666){//if LED is off and button code is ok

    digitalWrite(M_RFW, HIGH);

    }

    if(input == 0000){//if LED is on and button code is ok

    digitalWrite(M_RFW, LOW);

    }

    if(input == 7777){//if LED is off and button code is ok

    digitalWrite(M_LFW, HIGH);

    }

    if(input == 0000){//if LED is on and button code is ok

    digitalWrite(M_LFW, LOW);

    }

    }

    mySerial.flush();//clear the serial buffer for unwanted inputs

    delay(10);//delay little for better serial communication

    }

    please kindly help.

    Capture.PNG
    0
    None
    cwinst

    2 years ago

    Nice Tutorial !

    Bought two uno and HC-12 from Banggood...all programs worked well in Default mode (FU3) ...but would not work in long range mode (FU4)...Anyone else tried this ?

    Curt

    1 reply

    Hi
    Just change the mySerial.begin(9600) to mySerial.begin(1200) and it works

    hi sir, my hc-12 module not respond to AT cmd mode, i have 3 modules no one will work?

    2 replies

    Make sure the HC-12 pin labelled "Set" is grounded at the time you send AT commands. See Tom's Step 4 above, in this very detailed tutorial ;)

    Did all that coul not get it to work??????? Please help

    0
    None
    AnmarS

    7 months ago

    good

    Dag Tom,

    Prachtige instructable, ik heb hem ondertussen uitgeprobeert en het werkt prima.

    Het is de bedoeling dat ik de send en receive uitvoering van de momentary button bouw voor een overdracht over 1,3Km , ik heb gelezen om deze afstand te kunnen overbruggen dat de baudrate maximum 1200bps mag zijn en dat ik de module in FU4 mode moet programeren. Volgens de datasheet die je hebt bijgedaan staat er te lezen dat ik de delaytijd in de sketches ook moet aanpassen van 25 ms naar 1000ms of heb ik het mis ?

    Best groeten

    Alex Jacobs

    If you are using an Arduino Mega note that software serial doesn't work for all pins. 10 and 11 seem to work though. Also, I found that for my HC12 I had to flip the TX and RX pins for both the sending and receiving device. Aka SoftwareSerial HC12(10, 11); //TX, RX

    Any idea on the latency? and other important parameters?

    Also HC-12 has a specified range of 1Km, is it because of your choice of antenna that you achieved this?

    I'm trying to make a quad, any tips with this chip?

    1 reply

    Unfortunalty this is not so easy. In fact the HC-12 has a range of 1.8km in very specific conditions and a the lower speed. At 9600 Bauds, you can achieve 500m, at 115200 no more than 100m....