Hi! I'm trying to send lighting cues to GrandMA2 via Ethernet UDP from my ESP32. This is part of a larger project where my ESP32 receives a signal from elsewhere via LoRa, and sends a corresponding lighting cue to GrandMA2.
Appreciate any help and advice!
My architecture:
- ESP32 (specifically YD-ESP32-S3) that is receiving triggers via LoRa (works fine)
- The same ESP32 is connected to HanRun HR961160C that is integrated with a Wiznet W5500. Pin connections provided below. I left some pins unconnected
- A Cat6 Ethernet cable connects between the ESP32 (via HR961160C) and an ethernet switch
- Another Cat6 Ethernet cable connects the ethernet switch and eth0 port of GrandMA2 (which has 2x ethernet ports)
Pin Connection
| HanRun HR961160C | YD-ESP32-S3 |
|---|---|
| MO | 13 |
| SCK | 12 |
| CS | 10 |
| MI | 11 |
What I have so far:
- For the sending of Ethernet UDP, I mostly followed a working code from here.
- I'll append my code below (it will be truncated to just the relevant basic logic of ESP32 receive a trigger, then send lighting cue to GrandMA2)
- During setup(), I get success messages like "Setup: Found Ethernet Shield" and "Setup: UDP port connection successful to 6004"
- During loop(), upon ESP32 triggered to send udpMsg out: "Loop: Begin packet successful" and "Loop: Message sent via UDP" sends out.
- The udpMsg string is using the example string given by GrandMA2 manual here.
The problem: Nothing is received at GrandMA2 side. I'm not sure how to begin debugging this.
The code:
// Goal: upon triggered, ESP32 sends udp msg to GrandMA2
#include "Arduino.h"
// Ethernet / UDP: follows https://forum.arduino.cc/t/inter-arduino-comms-w-udp/652761/20
#include <SPI.h>
#include <Ethernet.h>
#define idLocal 10 // arbitrary
// #define idRemote 20 // not used
#define grandmaPORT 6004 // GrandMa2 actual port
EthernetUDP sendUdp;
char UDPRecvBuffer[UDP_TX_PACKET_MAX_SIZE];
// char UDPSendBuffer[] = "ack"; // not used
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, idLocal}; // arbitrarily set
IPAddress local_IP(10, 1, 1, idLocal); // arbitrarily set
IPAddress remote_IP(192, 168, 0, 57); // GrandMA2 actual IP
// Trigger logic
// a bunch of pins & states for trigger logic
// ...
// LoRa | not relevant to issue; leaving it here in case it matters
// #include "LoRa_E220.h"
// LoRa_E220 e220ttl(17, 18, &Serial1, 1, 21,38, UART_BPS_RATE_9600);
// Lora TXD -> 17
// Lora RXD -> 18
// Lora Aux -> 1
// Lora M0 -> 21
// Lora M1 -> 38
// DFPlayer | not relevant to issue; leaving it here in case it matters
// #include "DFRobotDFPlayerMini.h"
// #define FPSerial Serial2 // note: Serial1 for Lora
// DFRobotDFPlayerMini myDFPlayer;
int triggered = 0; // simplified the trigger logic: if triggered==1, then send udpMsg
void setup() {
// awake
Serial.begin(9600); //115200
delay(1000);
timer(); // prints current timestamp
Serial.println("ESP32 | Receiver Awake");
delay(100);
// Lora START //
// timer(); // prints current timestamp
// Serial.println("Starting LoRa Master");
// e220ttl.begin();
// timer(); // prints current timestamp
// Serial.println("LoRa: ready");
// Lora END //
// DFPlayer START //
// timer(); // prints current timestamp
// Serial.println("DFPlayer: starting");
// FPSerial.begin(9600, SERIAL_8N1,41,40); // baud_rate?, serial?, rx, tx
// Serial.println("DFPlayer: FPSerial started");
// ... more code for DFPlayer setup...
// DFPlayer END //
// Trigger-related Pins START //
// ... more code for trigger related pins
// END //
// Ethernet UDP START //
Ethernet.begin(mac, local_IP);
delay(1000);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
timer(); // prints current timestamp
Serial.println("Setup: Ethernet shield was not found. Sorry, can't run without hardware. :(");
} else {
timer(); // prints current timestamp
Serial.println("Setup: Found Ethernet Shield");
}
int Udp_Conn = sendUdp.begin(grandmaPORT);
if (Udp_Conn) {
timer(); // prints current timestamp
Serial.print("Setup: UDP port connection successful to ");
Serial.println(grandmaPORT);
Serial.print(Udp_Conn);
Serial.print(" function return code ");
Serial.print("to ");
Serial.print(sendUdp.remoteIP());
Serial.print(":");
Serial.println(sendUdp.remotePort());
}
else {
timer(); // prints current timestamp
Serial.print("Setup: UDP port connection failed to ");
Serial.println(grandmaPORT);
Serial.print("Loop: Error occurred during begin [");
Serial.print(Udp_Conn);
Serial.println("]");
Serial.print("to ");
Serial.print(sendUdp.remoteIP());
Serial.print(":");
Serial.println(sendUdp.remotePort());
}
timer(); // prints current timestamp
Serial.println("ESP32: End setup()!");
// set triggered to true to trigger udpMsg in a loop
int triggered = 1;
}
void loop() {
// ... truncated code for trigger logic ...
if (triggered==1) {
int UdpConn = sendUdp.beginPacket(remote_IP, grandmaPORT);
if (UdpConn) {
timer();
Serial.println("Loop: Begin packet successful");
}
else {
timer();
Serial.print("Loop: _UDP packet begin failed. Host not found");
Serial.println(sendUdp.remoteIP());
}
String udpMsg = "47 4D 41 00 4D 53 43 00 13 00 00 00 F0 7F 7F 02 7F 07 01 F7"; // example from https://help2.malighting.com/Page/grandMA2/remote_control_msc/en/3.9/udp#toc_header_anchor_7
sendUdp.print(udpMsg);
int UdpSent = sendUdp.endPacket();
if (UdpSent) {
timer();
Serial.println("Loop: Message sent via UDP");
Serial.println();
}
else {
timer();
Serial.print("Loop: Error occurred during write [");
Serial.print(UdpSent);
Serial.println("]");
Serial.print("to ");
Serial.print(sendUdp.remoteIP());
Serial.print(":");
Serial.println(sendUdp.remotePort());
}
}
delay(100);
}
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- */
//// Utility Functions
void timer() {
// Get the current time in milliseconds
unsigned long currentMillis = millis();
// Calculate hours, minutes, seconds, and milliseconds
int hours = (currentMillis / 3600000) % 24; // 3600000 milliseconds in an hour
int minutes = (currentMillis / 60000) % 60; // 60000 milliseconds in a minute
int seconds = (currentMillis / 1000) % 60; // 1000 milliseconds in a second
int milliseconds = currentMillis % 1000;
// Print the timestamp in the desired format
Serial.print(hours);
Serial.print(":");
Serial.print(minutes);
Serial.print(":");
Serial.print(seconds);
Serial.print(".");
Serial.print(milliseconds);
Serial.print(" | "); // to follow up with another Serial.println(<msg>) in code
// prints: 15:05:15.629 | <msg>
}