complete programs - transmitter
// ESP32 test of HC-12 wireless module - transmit structure as a HEX binary string
#define nodeID 2 // <<< set up required node ID
// test structure
struct __attribute__((packed)) Struct1 {
byte StructureID; // identifies the structure type
byte NodeID; // ID of transmitting node
int16_t seq; // sequence number
int32_t x;
float y;
char z[10];
byte crc;
};
Struct1 struct1 = { 1, nodeID, 0, 1, 4.5, "hello", 0 };
#define RXD1 16
#define TXD1 17
#define HC12 Serial1
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("\nESP32 test of HC-12 wireless module - transmit structure as a HEX string");
HC12.begin(9600, SERIAL_8N1, RXD1, TXD1);
}
void loop() {
Serial.print("Transmitting ");
struct1.seq++; // increment packet sequence number
struct1.x += 1; // and test data
struct1.y += 1.5;
struct1.z[4]++;
struct1.crc = CRC((byte *)&struct1); // calculate CRC
// convert each structure byte into 2 hex digits
char text[sizeof(struct1) * 2 + 2] = { 0 };
for (int i = 0; i < sizeof(struct1); i++) {
sprintf(&text[i * 2], "%02x", ((byte *)&struct1)[i]);
}
Serial.println(text); // display the transmitted string
HC12.println(text); // transmit the string
Serial.print(" StructureID ");
Serial.print(struct1.StructureID);
Serial.print(" Node ");
Serial.print(nodeID);
Serial.print(" seq number ");
Serial.print(struct1.seq);
Serial.print(" x = ");
Serial.print(struct1.x);
Serial.print(" y = ");
Serial.print(struct1.y);
Serial.print(" z = ");
Serial.print(struct1.z);
Serial.print(" crc = 0x");
Serial.println(struct1.crc, HEX);
delay(2000);
// display any acknowledgement received
while (HC12.available()) { // If HC-12 has data
Serial.write(HC12.read()); // Send the data to Serial monitor
}
}
// simple checksum - replace with CRC8
byte CRC(byte *s) {
byte crc = 0;
for (int i = 0; i < sizeof(Struct1) - 1; i++) crc += s[i];
return crc;
}
receiver
// ESP32 test of HC-12 wireless module - receive structure as a HEX binary string
#define nodeID 2 // <<< set up required node ID
// test structure
struct __attribute__((packed)) Struct1 {
byte StructureID; // identifies the structure type
byte NodeID; // ID of transmitting node
int16_t seq; // sequence number
int32_t x;
float y;
char z[10];
byte crc;
} struct1;
#define RXD1 16
#define TXD1 17
#define HC12 Serial1
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("\nESP32 test of HC-12 wireless module - receive structure as a HEX string");
HC12.begin(9600, SERIAL_8N1, RXD1, TXD1);
}
void loop() {
static int16_t node1seq = 0, node2seq = 0, seqErrors = 0, crcErrors = 0;
char text[sizeof(struct1)*2+2]={0}; // Set buffer to size of expected message
if (HC12.available() == 0) return; // if no HC-12 data return
int length=HC12.readBytesUntil('\n', text, sizeof(struct1)*2+2); // read string to newline
Serial.printf("received %s\n", text);
// check correct number of bytes received - if not discard
if(length != sizeof(struct1)*2+1) {
Serial.printf("ERROR - number of bytes received %d incorrect !!\n", length);
while(Serial.available()) Serial.read(); // flush input buffer
return;
}
// convert 2 hex values into a byte
for(int i=0;i<sizeof(struct1);i++) {
sscanf(&text[i*2],"%02x",&((byte*)&struct1)[i]);
}
// Message received display data
Serial.print("Received ");
Serial.print(strlen(text));
Serial.print("bytes StructID ");
Serial.print(struct1.StructureID);
Serial.print(" Node ");
Serial.print(struct1.NodeID);
Serial.print(" seq ");
Serial.print(struct1.seq);
Serial.print(" x = ");
Serial.print(struct1.x);
Serial.print(" y = ");
Serial.print(struct1.y);
Serial.print(" z = ");
Serial.print(struct1.z);
Serial.print(" crc = 0x");
Serial.print(struct1.crc, HEX);
if (struct1.NodeID == 1) {
if (struct1.seq != node1seq) {
Serial.print("\n seq number error expected ");
Serial.print(node1seq);
node1seq = struct1.seq;
++seqErrors;
}
node1seq++;
}
if (struct1.NodeID == 2) {
if (struct1.seq != node2seq) {
Serial.print("\n seq number error expected ");
Serial.print(node2seq);
++seqErrors;
node2seq = struct1.seq;
}
node2seq++;
}
// check CRC - note does not work if transmitting floats
byte crc = CRC((byte*)&struct1);
//crc++; // uncomment to display crc error message
if (crc != struct1.crc) {
Serial.print("\n crc error calculated 0x");
Serial.print(crc, HEX);
crcErrors++;
}
Serial.print(" crc errors ");
Serial.print(crcErrors);
Serial.print(" seq errors ");
Serial.println(seqErrors);
HC12.printf("received seq %d OK\n", struct1.seq);
}
// simple checksum - replace with CRC8
byte CRC(byte* s) {
byte crc = 0;
for (int i = 0; i < sizeof(Struct1) - 1; i++) crc += s[i];
return crc;
}
running on an ESP32 transmitter serial output
ESP32 test of HC-12 wireless module - transmit structure as a HEX string
Transmitting 01020100020000000000c04068656c6c7000000000001b
StructureID 1 Node 2 seq number 1 x = 2 y = 6.00 z = hellp crc = 0x1B
Transmitting 01020200030000000000f04068656c6c7100000000004e
StructureID 1 Node 2 seq number 2 x = 3 y = 7.50 z = hellq crc = 0x4E
Transmitting 01020300040000000000104168656c6c72000000000072
StructureID 1 Node 2 seq number 3 x = 4 y = 9.00 z = hellr crc = 0x72
received seq 3 OK
Transmitting 01020400050000000000284168656c6c7300000000008d
StructureID 1 Node 2 seq number 4 x = 5 y = 10.50 z = hells crc = 0x8D
received seq 4 OK
Transmitting 01020500060000000000404168656c6c740000000000a8
StructureID 1 Node 2 seq number 5 x = 6 y = 12.00 z = hellt crc = 0xA8
received seq 5 OK
Transmitting 01020600070000000000584168656c6c750000000000c3
StructureID 1 Node 2 seq number 6 x = 7 y = 13.50 z = hellu crc = 0xC3
received seq 6 OK
Transmitting 01020700080000000000704168656c6c760000000000de
StructureID 1 Node 2 seq number 7 x = 8 y = 15.00 z = hellv crc = 0xDE
received seq 7 OK
Transmitting 01020800090000000000844168656c6c770000000000f5
StructureID 1 Node 2 seq number 8 x = 9 y = 16.50 z = hellw crc = 0xF5
receiver serial output
ESP32 test of HC-12 wireless module - receive structure as a HEX string
received �56c6c7100000000004e
ERROR - number of bytes received 21 incorrect !!
received 01020300040000000000104168656c6c72000000000072
Received 47bytes StructID 1 Node 2 seq 3 x = 4 y = 9.00 z = hellr crc = 0x72
seq number error expected 0 crc errors 0 seq errors 1
received 01020400050000000000284168656c6c7300000000008d
Received 47bytes StructID 1 Node 2 seq 4 x = 5 y = 10.50 z = hells crc = 0x8D crc errors 0 seq errors 1
received 01020500060000000000404168656c6c740000000000a8
Received 47bytes StructID 1 Node 2 seq 5 x = 6 y = 12.00 z = hellt crc = 0xA8 crc errors 0 seq errors 1
received 01020600070000000000584168656c6c750000000000c3
Received 47bytes StructID 1 Node 2 seq 6 x = 7 y = 13.50 z = hellu crc = 0xC3 crc errors 0 seq errors 1
received 01020700080000000000704168656c6c760000000000de
Received 47bytes StructID 1 Node 2 seq 7 x = 8 y = 15.00 z = hellv crc = 0xDE crc errors 0 seq errors 1
received 01020800090000000000844168656c6c770000000000f5
Received 47bytes StructID 1 Node 2 seq 8 x = 9 y = 16.50 z = hellw crc = 0xF5 crc errors 0 seq errors 1
received 010209000a0000000000904168656c6c78000000000004
Received 47bytes StructID 1 Node 2 seq 9 x = 10 y = 18.00 z = hellx crc = 0x4 crc errors 0 seq errors 1
received 01020a000b00000000009c4168656c6c79000000000013
Received 47bytes StructID 1 Node 2 seq 10 x = 11 y = 19.50 z = helly crc = 0x13 crc errors 0 seq errors 1
received 01020b000c0000000000a84168656c6c7a000000000022
Received 47bytes StructID 1 Node 2 seq 11 x = 12 y = 21.00 z = hellz crc = 0x22 crc errors 0 seq errors 1
received 01020c000d0000000000b44168656c6c7b000000000031
Received 47bytes StructID 1 Node 2 seq 12 x = 13 y = 22.50 z = hell{ crc = 0x31 crc errors 0 seq errors 1
initially received string of incorrect length - probably received end of last packet on startup
and got a sequence number error until seq was synchronised
there are several error checks
- check length of received hex string is sizeof(struct1)*2 +1 - in receiver output above the first line is discarded as it is only part of the transmitted text
- each packet is sequence numbered - at start of receive data the sequence number is invalid - it then synchronises
- a CRC check is performed on received data