have a look at this which will transmit and receive a datagram containing a structure
struct __attribute__((packed)) Struct1 {
byte StructureID; // identifies the structure type
byte NodeID; // ID of transmitting node
int16_t seq; // sequence number
int32_t distance;
float voltage;
};
when transmitting binary data between programs which may be running on different processors one has to be careful with data sizes, e.g. on a Mega an int is 16 bits and on a ESP32 is 32bit - hence the use of predefined sizes int16_t (16 bit integer) and int32_t (32 bit integer)
mega code using ethernet shield
// UDP transmit/receive structure using Arduino Ethernet Shield
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#define nodeID 1 // <<< set up required node ID
struct __attribute__((packed)) Struct1 {
byte StructureID; // identifies the structure type
byte NodeID; // ID of transmitting node
int16_t seq; // sequence number
int32_t distance;
float voltage;
};
Struct1 struct1 = { 1, nodeID, 0, 25, 4.5 }, struct2;
#define UDP_TX_PACKET_MAX_SIZE 100 //increase UDP size
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC address update as required
IPAddress localIP(192, 168, 1, 177); // local static localIP address
IPAddress remoteIP(192, 168, 1, 176); // local static localIP address
unsigned int port = 999; // port to receive/transmit
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet
EthernetUDP Udp; // An EthernetUDP instance to let us send and receive packets over UDP
void setup() {
Serial.begin(115200);
Serial.println("\n\nUDP transmit/receive structure ");
// select static or dynamic IP initialization
//Ethernet.begin(mac, localIP); // static IP initialize Ethernet shield
if (Ethernet.begin(mac)) // dyname IP initialize Ethernet shield using DHCP
Serial.println("Configured Ethernet using DHCP OK");
else Serial.println("Failed to configure Ethernet using DHCP");
Serial.print("My localIP address: "); // print local localIP address:
Serial.println(Ethernet.localIP());
// Initializes the ethernet UDP library and network settings.
if (Udp.begin(port)) Serial.println("UDP begin() OK");
else Serial.println("UDP begin() failed!");
Serial.print("UDP_TX_PACKET_MAX_SIZE ");
Serial.println(UDP_TX_PACKET_MAX_SIZE);
}
void loop() {
// if datagram received read it
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.print("Received packet of size ");
Serial.print(packetSize); // datagram packet size
Serial.print(" From ");
remoteIP = Udp.remoteIP(); // from localIP
Serial.print(remoteIP);
Serial.print(", port "); // from port
Serial.println(Udp.remotePort());
// if packet is correct size read it and display contents
if (packetSize == sizeof(struct2)) {
Udp.read((unsigned char*)&struct2, sizeof(struct2)); //packetBuffer, UDP_TX_PACKET_MAX_SIZE);
Serial.print("Contents: ");
Serial.print(" StructureID ");
Serial.print(struct2.StructureID);
Serial.print(" from Node ");
Serial.print(struct2.NodeID);
Serial.print(" seq number ");
Serial.print(struct2.seq);
Serial.print(" distance 1 = ");
Serial.print(struct2.distance);
Serial.print(" voltage 1 = ");
Serial.println(struct2.voltage);
checkSeqNumber(struct2.NodeID, struct2.seq);
}
}
if (Serial.available()) { // if key hit transmit structure
while (Serial.available()) Serial.read();
Serial.print("Transmitting datagram to ");
displayIPaddress(remoteIP, port);
struct1.seq++; // increment packet sequence number
struct1.distance += 1; // setup test values
struct1.voltage += 1;
Serial.print(" Node ");
Serial.print(nodeID);
Serial.print(" seq number ");
Serial.print(struct1.seq);
Serial.print(" distance = ");
Serial.print(struct1.distance);
Serial.print(" voltage = ");
Serial.println(struct1.voltage);
Udp.beginPacket(remoteIP, port); // send to remote localIP and port 999
Udp.write((const uint8_t*)&struct1, sizeof(struct1));
Udp.endPacket();
}
delay(10);
}
// set transmit mode
void checkSeqNumber(int NodeID, int seq) {
static int seqNumbers[] = { 0, 0, 0, 0 }, seqErrors = 0;
if (NodeID >= sizeof(seqNumbers) / sizeof(int)) return;
if (seq != seqNumbers[NodeID]) { // check for sequence error!
Serial.print(" seq number error expected ");
Serial.print(seqNumbers[NodeID]);
Serial.print(" received ");
Serial.print(seq);
Serial.print(" seq errors ");
Serial.println(++seqErrors);
seqNumbers[NodeID] = seq;
}
seqNumbers[NodeID]++; // next sequence nunber expected
}
void displayIPaddress(const IPAddress address, unsigned int port) {
Serial.print(" IP ");
for (int i = 0; i < 4; i++) {
Serial.print(address[i], DEC);
if (i < 3) Serial.print(".");
}
Serial.print(" port ");
Serial.println(port);
}
to test I used a Nano with a ENC28J60 ethernet module
// UDP transmit/receive structure using ENC28J60 tested on UNO and Nano
// **** change IP addresses and ports to suit requirements *****
#include <EthernetENC.h> // for ENC28J60
#include <EthernetUdp.h> // for UDP
#define nodeID 2 // <<< set up required node ID
struct __attribute__((packed)) Struct1 {
byte StructureID; // identifies the structure type
byte NodeID; // ID of transmitting node
int16_t seq; // sequence number
int32_t distance;
float voltage;
};
Struct1 struct1 = { 1, nodeID, 0, 25, 4.5 }, struct2;
// ***** IP of this machine and remote machine *********
IPAddress localIP; // these will be read from the keyboard
IPAddress remoteIP;
// Enter a MAC address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEC };
unsigned int localPort = 999; // local port to listen on
unsigned int remotePort = 999; // remote port to transmiit too
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial)
;
Serial.println("\nEthernet transmit/receive structure ");
// Check for Ethernet hardware present
// You can use Ethernet.init(pin) to configure the CS pin
Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH Shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit FeatherWing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit FeatherWing Ethernet
localIP = getIPaddress("\nenter local IP address (e.g. 192.168.1.176)? ");
Serial.print("\nRemote ");
//displayMACaddress(mac);
mac[5] = localIP[3]; // change default MAC address
displayMACaddress(mac);
// start the Ethernet
Ethernet.begin(mac, localIP);
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) delay(1); // do nothing, no point running without Ethernet hardware
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
Udp.begin(localPort); // start UDP
Serial.print("Ethernet UDP started ");
displayIPaddress(localIP, localPort);
// get remote IP address
remoteIP = getIPaddress("\nenter remote IP address (e.g. 192.168.1.176)? ");
Serial.print("\nRemote ");
displayIPaddress(remoteIP, remotePort);
}
void loop() {
Udp.begin(localPort);
// if Serial text entered transmit as a datagram
if (Serial.available()) {
while (Serial.available()) Serial.read();
Serial.print("Transmitting datagram to ");
displayIPaddress(remoteIP, remotePort);
struct1.seq++; // increment packet sequence number
struct1.distance += 1; // setup test values
struct1.voltage += 1;
Serial.print(" Node ");
Serial.print(nodeID);
Serial.print(" seq number ");
Serial.print(struct1.seq);
Serial.print(" distance = ");
Serial.print(struct1.distance);
Serial.print(" voltage = ");
Serial.println(struct1.voltage);
Udp.beginPacket(remoteIP, remotePort); // send to remote localIP and port 999
Udp.write((const uint8_t*)&struct1, sizeof(struct1));
Udp.endPacket();
Udp.endPacket();
}
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
displayIPaddress(Udp.remoteIP(), Udp.remotePort());
// if packet is correct size read it and display contents
if (packetSize == sizeof(struct2)) {
Udp.read((unsigned char*)&struct2, sizeof(struct2)); //packetBuffer, UDP_TX_PACKET_MAX_SIZE);
Serial.print("Contents: ");
Serial.print(" StructureID ");
Serial.print(struct2.StructureID);
Serial.print(" from Node ");
Serial.print(struct2.NodeID);
Serial.print(" seq number ");
Serial.print(struct2.seq);
Serial.print(" distance 1 = ");
Serial.print(struct2.distance);
Serial.print(" voltage 1 = ");
Serial.println(struct2.voltage);
checkSeqNumber(struct2.NodeID, struct2.seq);
}
}
delay(10);
}
// read IP address from keyboard and check it
IPAddress getIPaddress(const char* prompt) {
IPAddress ip;
while (1) { // read IP (end with new line)
Serial.print(prompt);
while (Serial.available() == 0) delay(10);
char text[40] = { 0 };
Serial.readBytesUntil('\n', (char*)text, 40);
//Serial.println(text);
if (ip.fromString(text)) break; // if IP OK break while
Serial.println("\ninvalid IP try again");
}
return ip;
}
// set transmit mode
void checkSeqNumber(int NodeID, int seq) {
static int seqNumbers[] = { 0, 0, 0, 0 }, seqErrors = 0;
if (NodeID >= sizeof(seqNumbers) / sizeof(int)) return;
if (seq != seqNumbers[NodeID]) { // check for sequence error!
Serial.print(" seq number error expected ");
Serial.print(seqNumbers[NodeID]);
Serial.print(" received ");
Serial.print(seq);
Serial.print(" seq errors ");
Serial.println(++seqErrors);
seqNumbers[NodeID] = seq;
}
seqNumbers[NodeID]++; // next sequence nunber expected
}
// print IPAdress and port
void displayIPaddress(const IPAddress address, unsigned int port) {
Serial.print(" IP ");
for (int i = 0; i < 4; i++) {
Serial.print(address[i], DEC);
if (i < 3) Serial.print(".");
}
Serial.print(" port ");
Serial.println(port);
}
void displayMACaddress(byte address[]) {
Serial.print("MAC address ");
for (int i = 0; i < 6; i++) {
Serial.print("0x");
Serial.print(address[i], HEX);
if (i < 5) Serial.print(".");
}
Serial.println();
}
Mega serial output (hit serial monitor keyboard to transmit a datagram)
UDP transmit/receive structure
Configured Ethernet using DHCP OK
My localIP address: 192.168.1.177
UDP begin() OK
UDP_TX_PACKET_MAX_SIZE 100
Received packet of size 12 From 192.168.1.176, port 999
Contents: StructureID 1 from Node 2 seq number 1 distance 1 = 26 voltage 1 = 5.50
seq number error expected 0 received 1 seq errors 1
Received packet of size 12 From 192.168.1.176, port 999
Contents: StructureID 1 from Node 2 seq number 2 distance 1 = 27 voltage 1 = 6.50
Received packet of size 12 From 192.168.1.176, port 999
Contents: StructureID 1 from Node 2 seq number 3 distance 1 = 28 voltage 1 = 7.50
Transmitting datagram to IP 192.168.1.176 port 999
Node 1 seq number 1 distance = 26 voltage = 5.50
Transmitting datagram to IP 192.168.1.176 port 999
Node 1 seq number 2 distance = 27 voltage = 6.50
Transmitting datagram to IP 192.168.1.176 port 999
Node 1 seq number 3 distance = 28 voltage = 7.50
nano output
Ethernet transmit/receive structure
enter local IP address (e.g. 192.168.1.176)?
Remote MAC address 0xDE.0xAD.0xBE.0xEF.0xFE.0xB0
Ethernet cable is not connected.
Ethernet UDP started IP 192.168.1.176 port 999
enter remote IP address (e.g. 192.168.1.176)?
Remote IP 192.168.1.177 port 999
Transmitting datagram to IP 192.168.1.177 port 999
Node 2 seq number 1 distance = 26 voltage = 5.50
Transmitting datagram to IP 192.168.1.177 port 999
Node 2 seq number 2 distance = 27 voltage = 6.50
Transmitting datagram to IP 192.168.1.177 port 999
Node 2 seq number 3 distance = 28 voltage = 7.50
Received packet of size 12
From IP 192.168.1.177 port 999
Contents: StructureID 1 from Node 1 seq number 1 distance 1 = 26 voltage 1 = 5.50
seq number error expected 0 received 1 seq errors 1
Received packet of size 12
From IP 192.168.1.177 port 999
Contents: StructureID 1 from Node 1 seq number 2 distance 1 = 27 voltage 1 = 6.50
Received packet of size 12
From IP 192.168.1.177 port 999
Contents: StructureID 1 from Node 1 seq number 3 distance 1 = 28 voltage 1 = 7.50