Sending cues to GrandMA2 lighting sys via Ethernet UDP from ESP32

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>
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.