Arduino radio hc-12: Difference between revisions

From wikiluntti
 
(34 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Introduction ==
== Introduction ==
Idea: The protocols are usually based on transmitting characters. Thus, easiest method is to transfer csv as strings and then cast the type to floats in the receiving program. If using cansat, also the time stamp is extremely important. We try to use Linux as a receiving machine.
UART (Universal Asynchronous Receiver-Transmitter) communication. Serial communication is expecting (a pointer to) a string.


LoRa, hc12, hc-12
LoRa, hc12, hc-12
Line 6: Line 11:
* Transmitting power is from -1dBm (0.79mW) to 20dBm (100mW). A half-duplex 20 dBm (100 mW) transmitter
* Transmitting power is from -1dBm (0.79mW) to 20dBm (100mW). A half-duplex 20 dBm (100 mW) transmitter
* Receiving sensitivity is from -117dBm (0.019pW) to -100dBm (10pW)
* Receiving sensitivity is from -117dBm (0.019pW) to -100dBm (10pW)
* Supply Voltage: 3.2V to 5.5V


Connect a 22 µF to 1 mF reservoir capacitor in parallel with the HC-12 "Gnd" and "Vcc" pins.
Connect a 22 µF to 1 mF reservoir capacitor in parallel with the HC-12 "Gnd" and "Vcc" pins.
Datasheet: https://statics3.seeedstudio.com/assets/file/bazaar/product/HC-12_english_datasheets.pdf


== Terminal program ==
== Terminal program ==
Line 128: Line 137:


== Transmit and Receive floating point numbers ==
== Transmit and Receive floating point numbers ==
The protocols transmit characters, only. Thus, if needed to transmit floating point number or any other types, it need to be casted to characters first. It might be beneficial, if only a small amount of data need to be transmitted. Eg. a char is 8 bits, and so numbers from 0-255 can be submitted using one character or "two hexadecimals"; <code>FF = 11111111 = 255 </code>. Thus, the numbers need to be scaled.


https://forum.arduino.cc/t/transferring-float-data-via-hc12/515156/8
https://forum.arduino.cc/t/transferring-float-data-via-hc12/515156/8
Line 152: Line 163:
Version 2.
Version 2.
<syntaxhighlight lang="C">
<syntaxhighlight lang="C">
//TRANSMITTER CODE
#include <SoftwareSerial.h>
#include <SoftwareSerial.h>
SoftwareSerial HC12(11, 10); // RX, TX
//using 'union'to store a float and a uint8_t array of the same size as a float in the same memory location
//using 'union'to store a float and a uint8_t array of the same size as a float in the same memory location
union{
union{
Line 160: Line 172:
} f_tx;
} f_tx;
//
//
SoftwareSerial HC12(11, 10); // RX, TX


void setup() {
void setup() {
Line 185: Line 195:
</syntaxhighlight>
</syntaxhighlight>


Receive floating point number
<syntaxhighlight lang="C">
<syntaxhighlight lang="C">
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 10); // RX, TX
//using 'union'to store a float and a uint8_t array of the same size as a float in the same memory location
union {
  float num;
  uint8_t bytes[sizeof(float)];
} f_rx;
uint8_t i, r_float;


void setup() {
  Serial.begin(9600);
  mySerial.begin (9600);
}
void loop() {
  byte data;
  if (mySerial.available()) {
  //read data from RX buffer
    data = mySerial.read();
  //check of data if data is a float start byte (determined be flag r_float AND data = sizeof(float))
    if (data == sizeof(float) && r_float == 0) {
      f_rx.num = 0.0; //reset rx float variable
      r_float = 1; //set flag
      i = 0; //reset byte counter
    }
//flag was set ie receiving data is part of a float
    else if (r_float == 1) {
      //if byte counter is less than sizeof(float), add data to array
  if (i < sizeof(float)) {
        f_rx.bytes[i] = data;
        ++i;
      }
  //all float bytes received print out
      else {
        Serial.print("f_rx.num =      ");
        Serial.println(f_rx.num, DEC);
        r_float = 0;
      }
    }
//float start byte not received. therefore just print out received data
else {
      Serial.println(data, DEC);
    }
  }
}
</syntaxhighlight>
</syntaxhighlight>


Line 193: Line 249:
== Receive Rx ==
== Receive Rx ==


== USB - TTL (Serial) interface ==
=== 6-pin FT232RL ===
With 1 m cable.
* Black:  GND
* Blue: CTS
* Red: VCC
* Green: TXD
* White: RXD
* Yellow: RTS
=== 6-pin CP2102 bipolaarne RS232 RS485 ===
===  5-pin PL2303HX ===
The cheapest TTL converter.
=== DFRobot v2.0 (CP210x) ===
TTL chip:  Silicon Laboratories CP210x. Needs dedicate drivers which are now distributed with 2.6 series kernels, and should be compiled and part of the default installation for most modern Linux distributions.
Pins
* GND
* 5V
* RTS - Request to Send. No need to connect.
* TXD -> to RXD
* RXD -> to TXD
* NC - not connected. No need to connect.
* NC - not connected. No need to connect.
'''Linux''':
* <code>minicom</code>. Get the port <code>sudo dmesg | grep tty</code> and use minicom:
**<code>sudo minicom -b 9600 -o -D /dev/ttyUSB0</code>. Use <code>Ctrl+A+n</code> (x2) to get the timestamp to every line, or directly from the command line
** <code>sudo minicom -b 9600 -o -D /dev/ttyUSB0 -O timestamp=extended</code>.
** <code>sudo minicom -b 9600 -o -D /dev/ttyUSB0 -O timestamp=extended -C capturefile.log</code> to log the data. Appends to the end of the file.
* <code>tio -b 9600 /dev/ttyUSB0</code>
Minicom short tutoria
* Ctrl+A+x: exit
* Ctrl+A+n: timestamp
* Ctrl+A+L: Log the output
== Antenna ==
IPEX20279-001E-03 / (Hirose) U.FI (U.FL) connector.
Helical antenna.
Design software
* https://3g-aerial.biz/en/online-calculations/antenna-calculations/dl6wu-yagi-uda-antenna-online-calculator
DIY Yagi
* https://www.instructables.com/DIY-Yagi-Antenna-for-LoRa/ and https://www.youtube.com/watch?v=gA5SCXw_E1Q
* https://www.slideshare.net/slideshow/yagi-antenna-design-and-433mhz-antenna-design-examplepdf/253836272
* Not a yagi https://www.instructables.com/433-MHz-Coil-loaded-antenna/


== References ==
== References ==

Latest revision as of 17:05, 17 December 2025

Introduction

Idea: The protocols are usually based on transmitting characters. Thus, easiest method is to transfer csv as strings and then cast the type to floats in the receiving program. If using cansat, also the time stamp is extremely important. We try to use Linux as a receiving machine.


UART (Universal Asynchronous Receiver-Transmitter) communication. Serial communication is expecting (a pointer to) a string.

LoRa, hc12, hc-12

  • Frequency band is from 433.4 MHz to 473.0 MHz
  • 100 channels with a stepping of 400 KHz between each channel
  • Transmitting power is from -1dBm (0.79mW) to 20dBm (100mW). A half-duplex 20 dBm (100 mW) transmitter
  • Receiving sensitivity is from -117dBm (0.019pW) to -100dBm (10pW)
  • Supply Voltage: 3.2V to 5.5V

Connect a 22 µF to 1 mF reservoir capacitor in parallel with the HC-12 "Gnd" and "Vcc" pins.


Datasheet: https://statics3.seeedstudio.com/assets/file/bazaar/product/HC-12_english_datasheets.pdf

Terminal program

Terminal br@dy https://sites.google.com/site/terminalbpp/

PuTTY (on Windows):

Set

Pins:

  • Set pin of the module to Ground (set the pin to low logic level).
  • Vcc 3.3V and GND to GND
  • TXD -> 11
  • RXD -> 10

Note that the pins needs to be reversed: The TX pin in the HC-12 needs to be plugged to RX pin of the Arduino.

The syntax of the softaware serial is:

SoftwareSerial(rxPin, txPin, inverse_logic)

Code for setting AT commands:

#include <SoftwareSerial.h>
SoftwareSerial HC12(11, 10);      // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  Serial.begin(9600); 
  HC12.begin(9600); 
}

void loop() {
  while (HC12.available()) {        // If HC-12 has data
    Serial.write(HC12.read());      // Send the data to Serial monitor
  }
  while (Serial.available()) {      // If Serial monitor has data
    HC12.write(Serial.read());      // Send that data to HC-12
  }
}

AT commands. The most important commands are (remember to use capital letters)

  1. AT – test command. It will return OK if AT interface is enabled
  2. AT+Bxxxx – set serial port baud rate. For example, AT+B57600 set baud rate to 57600bps, AT+B9600. Available baud rates: 1200 bps, 2400 bps, 4800 bps, 9600 bps, 19200 bps, 38400 bps, 57600 bps, and 115200 bps. Default: 9600 bps.
  3. AT+Cxxx – set radio channel. Channels start from 001 at 433,4MHz. Each next channel adds 400kHz. Channel 100 is 473,0MHz. AT+C002 will set frequency to 433,8MHz. Two HC-12 devices that creates a wireless link have to operate on the same frequency
  4. AT+FUx – set device mode: FU1, FU2, FU3 or FU4. Two HC-12 devices that creates a wireless link have to use the same mode
  5. AT+Px – set device transmitting power. For example AT+P2 sets power to 2dBm (1.6mW)
    1. -1dBm (0.8mW)
    2. 2dBm (1.6mW)
    3. 5dBm (3.2mw)
    4. 8dBm (6.3mW)
    5. 11dBm (12mW)
    6. 14dBm (25mW)
    7. 17dBm (50mW)
    8. 20dBm (100mW)
  6. AT+RX – retrieve all parameters: mode, channel, baud rate, power
  7. AT+V – retrieve module version
  8. AT+DEFAULT – reset module parameters to default settings

Software Serial Commands

HC-12

  • print (turns number into a string and sends it)
  • write (Serial.write() sends one byte)
  • Serial.flush() function does not empty the input buffer. It is only relevant when the Arduino is sending data and its purpose is to block the Arduino until all outgoing the data has been sent.

Transmit and Receive text

Transmit numbers continuously as text with one sec in between:

#include <SoftwareSerial.h>
SoftwareSerial HC12(11, 10);      // HC-12 TX Pin, HC-12 RX Pin

int x = 100;
unsigned long previousMillis = 0; 
const long interval = 1000;  

void setup() { 
 HC12.begin(9600);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      x = x + 1;
      HC12.println(x);
  }
}

and receive it using

#include <SoftwareSerial.h>
SoftwareSerial HC12(11, 10);      // HC-12 TX Pin, HC-12 RX Pin

void setup() { 
 Serial.begin(9600);
 HC12.begin(9600);
}

void loop() {
  if(HC12.available()) {   
    String texto = HC12.readStringUntil('\n');
    Serial.println(texto);
  }
 }

(Source: https://community.appinventor.mit.edu/t/radio-frequency-hc-12-arduino-bluetooth-hc-06/60935/3)

Transmit and Receive floating point numbers

The protocols transmit characters, only. Thus, if needed to transmit floating point number or any other types, it need to be casted to characters first. It might be beneficial, if only a small amount of data need to be transmitted. Eg. a char is 8 bits, and so numbers from 0-255 can be submitted using one character or "two hexadecimals"; FF = 11111111 = 255 . Thus, the numbers need to be scaled.

https://forum.arduino.cc/t/transferring-float-data-via-hc12/515156/8

#include <SoftwareSerial.h>
SoftwareSerial HC12(11, 10);      // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  Serial.begin(9600);
  HC12.begin(9600);
}
void loop(){
  float x = 999.99;
  byte* ptr = (byte*) &x;

  for (int i = 0; i<4; i++)  { 
    HC12.println((int)ptr[i], HEX);
  }
  delay(1000);
}

Version 2.

#include <SoftwareSerial.h>
SoftwareSerial HC12(11, 10); // RX, TX

//using 'union'to store a float and a uint8_t array of the same size as a float in the same memory location
union{
  float num;
  uint8_t bytes[sizeof(float)];
} f_tx;
//

void setup() {
  Serial.begin(9600);
  HC12.begin (9600);
  f_tx.num=0.0; //initialiase float variable
}
void loop() {
  f_tx.num = f_tx.num + 1.2;
  
  //using size of float as start byte
  HC12.write(sizeof(float));  
  //set float bytes one by one using a 'for' loop. delay was commented out as optional
  for(uint8_t i=0; i<sizeof(float);++i){
	HC12.write(f_tx.bytes[i]);
	//delay(100);
  }
 
  //Serial.print("f_tx.num =      ");
  //Serial.println(f_tx.num,DEC);
  delay(100);
}

Receive floating point number

#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 10); // RX, TX
//using 'union'to store a float and a uint8_t array of the same size as a float in the same memory location
union {
  float num;
  uint8_t bytes[sizeof(float)];
} f_rx;

uint8_t i, r_float;

void setup() {
  Serial.begin(9600);
  mySerial.begin (9600);
}

void loop() {
  byte data;
  if (mySerial.available()) {
	  //read data from RX buffer
    data = mySerial.read();
	  //check of data if data is a float start byte (determined be flag r_float AND data = sizeof(float))
    if (data == sizeof(float) && r_float == 0) {
      f_rx.num = 0.0; //reset rx float variable
      r_float = 1; //set flag
      i = 0; //reset byte counter
    }
	//flag was set ie receiving data is part of a float
    else if (r_float == 1) { 
      //if byte counter is less than sizeof(float), add data to array
	  if (i < sizeof(float)) {
        f_rx.bytes[i] = data;
        ++i;
      }
	  //all float bytes received print out
      else {
        Serial.print("f_rx.num =      ");
        Serial.println(f_rx.num, DEC);
        r_float = 0;
      }
    }
	//float start byte not received. therefore just print out received data 
	else {
      Serial.println(data, DEC);
    }
  }
}

Transmit Tx

Receive Rx

USB - TTL (Serial) interface

6-pin FT232RL

With 1 m cable.

  • Black: GND
  • Blue: CTS
  • Red: VCC
  • Green: TXD
  • White: RXD
  • Yellow: RTS

6-pin CP2102 bipolaarne RS232 RS485

5-pin PL2303HX

The cheapest TTL converter.

DFRobot v2.0 (CP210x)

TTL chip: Silicon Laboratories CP210x. Needs dedicate drivers which are now distributed with 2.6 series kernels, and should be compiled and part of the default installation for most modern Linux distributions. Pins

  • GND
  • 5V
  • RTS - Request to Send. No need to connect.
  • TXD -> to RXD
  • RXD -> to TXD
  • NC - not connected. No need to connect.
  • NC - not connected. No need to connect.


Linux:

  • minicom. Get the port sudo dmesg | grep tty and use minicom:
    • sudo minicom -b 9600 -o -D /dev/ttyUSB0. Use Ctrl+A+n (x2) to get the timestamp to every line, or directly from the command line
    • sudo minicom -b 9600 -o -D /dev/ttyUSB0 -O timestamp=extended.
    • sudo minicom -b 9600 -o -D /dev/ttyUSB0 -O timestamp=extended -C capturefile.log to log the data. Appends to the end of the file.
  • tio -b 9600 /dev/ttyUSB0

Minicom short tutoria

  • Ctrl+A+x: exit
  • Ctrl+A+n: timestamp
  • Ctrl+A+L: Log the output

Antenna

IPEX20279-001E-03 / (Hirose) U.FI (U.FL) connector.

Helical antenna.

Design software

DIY Yagi

References

https://forum.arduino.cc/t/serial-input-basics-updated/382007/2

https://duckduckgo.com/?q=Serial.parseFloat()&ia=web