DIRECTION_PIN not resetting after RDM response

Questions concerning any LXSeries open source projects.
Comments and requests can also be posted on GitHub.
admin
Site Admin
Posts: 148
Joined: Mon Nov 20, 2017 4:31 pm

Re: DIRECTION_PIN not resetting after RDM response

Postby admin » Wed Jul 20, 2022 12:46 pm

I think that your compiler is being strict and wants a LXRecvCallback as the parameter to the setRDMReceivedCallback and setDataReceivedCallback functions. Just cast your function pointer to LXRecvCallback and that will probably get rid of the error message.

Code: Select all

SAMD21DMX.setDataReceivedCallback((LXRecvCallback)&gotDMXCallback);
SAMD21DMX.setRDMReceivedCallback((LXRecvCallback)&gotRDMCallback);


I'm not sure where you got the trace with the reversed destination and source UIDs. Are you absolutely sure that came from the sketch and not the testing device you are using? If so, which function is responsible for sending that?

If you comment out the mute response, discovery won't work.

I'm not sure which function you have inserted your pin toggles. Can you post the complete function and put it into code format. To format as code, click the code block button when editing your post and then paste your code in between the start and end code tags [code ] and [/code ].

xldaedalus
Posts: 17
Joined: Wed Jun 22, 2022 10:18 pm

Re: DIRECTION_PIN not resetting after RDM response

Postby xldaedalus » Sun Jul 24, 2022 4:56 pm

Here is the RDMDeviceTest.ino I've written

/*!
@file RDMDeviceTest.ino
@author Claude Heintz
@license BSD (see LXSAMD21DMX LICENSE)
@copyright 2017-2021 by Claude Heintz

Example showing LXSAMD21DMX RDM support for devices.
Control brightness of LED on GPIO14 with DMX address 1 (settable via RDM)

@section HISTORY
v1.00 - First release
*/
/**************************************************************************/
#include <LXSAMD21DMX.h>
#include <rdm/rdm_utility.h>
#include <rdm/UID.h>
#include <rdm/TOD.h>


int got_dmx = 0;
int got_rdm = 0;
uint8_t discovery_enabled = 1;
uint16_t start_address = 1;
uint16_t input_value = 0;

uint8_t device_label[33];

#define DEFAULT_DEVICE_LABEL "RDM dev test v1.0"
#define MFG_LABEL "LXDMX"
#define MODEL_DESCRIPTION "RDMDeviceTest"

#define DIRECTION_PIN 14 //A0
#define DMX_DE_PIN 15 //A1 disabled on breadboard
#define LED_PIN 25 //PIN_LED_RXL Yellow
#define BUILTIN_LED 13
#define debug_pin 18 //PIN_A4

#define TIMO_PIN 16 //A2
#define Timo_ON 1 // Timo ON
#define Timo_OFF 0 // Timo OFF
#define TIMO_CS 17 //A3

#define SERIAL_DEBUG // <-----------------------------------DEBUG----
//#define DEBUG_LOOP // <----------------------------------- forces program to test pin states only DEBUG PIN-S---
//#define TEST_PIN 30 // <-----------------------------------DEBUG PINS----

/*. HARDWARE INFO
Sparkfun SAMD21 Dev Board configured as Arduino Zero on an R3 shield layout
USB: SerialUSB.xxx <--- default for Serial Monitor, plotter, programming
Hardware Serial (TX/D1 and RX/D0): Serial1.xxx
Hardware Serial (30/TX and 31/RX): Serial.xxx <--- I use this for RS485. I use A)
*/

void setup() {
pinMode(TIMO_PIN, OUTPUT); //Timo is a wireless DMX special function SOC
digitalWrite(TIMO_PIN, Timo_OFF); //If Timo is ON, DMX is NOT handled by Serial.xxx, data received transferred via SPI
pinMode(debug_pin, OUTPUT); // my pins connected to oscope for timing and function testing
digitalWrite(debug_pin, LOW);
pinMode(DIRECTION_PIN, OUTPUT);
digitalWrite(DIRECTION_PIN, LOW); //start in receive mode

pinMode(TIMO_CS, OUTPUT); //talk to Timo SOC
digitalWrite(TIMO_CS, HIGH); //defualt not selected

#ifdef SERIAL_DEBUG // <--------------Use only if using serial monitor---------------------DEBUG----
SerialUSB.begin(115200);
while (!SerialUSB)
{
; // wait for SerialUSB port to connect. Needed for native USB port only
}
SerialUSB.println("SAMD21 RDMDeviceTest"); // test that the port has started properly

#endif

pinMode(BUILTIN_LED, OUTPUT);
pinMode(DIRECTION_PIN, OUTPUT);
digitalWrite(DIRECTION_PIN, LOW);
pinMode(LED_PIN, OUTPUT);

//diagnostic pins
// pinMode(12, OUTPUT);


#ifdef DEBUG_LOOP // <-----------------------------------DEBUG----
// pinMode(TEST_PIN, OUTPUT);
// digitalWrite(TEST_PIN, HIGH);
}
#else

strcpy((char*)device_label, DEFAULT_DEVICE_LABEL);

SAMD21DMX.setDataReceivedCallback(&gotDMXCallback);
SAMD21DMX.setRDMReceivedCallback(&gotRDMCallback);
LXSAMD21DMX::THIS_DEVICE_ID.setBytes(0x6C, 0x78, 0x0F, 0x0A, 0x0C, 0x0E); //change device ID from default

SAMD21DMX.startRDM(DIRECTION_PIN, DMX_TASK_RECEIVE);

}
#endif

//##############################################################################################

#ifdef DEBUG_LOOP // <-----------for testing pins only------------------------DEBUG----

void loop() { //
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
digitalWrite(DIRECTION_PIN, !digitalRead(DIRECTION_PIN));
// digitalWrite(BUILTIN_LED, !digitalRead(BUILTIN_LED));
digitalWrite(PIN_A4, !digitalRead(PIN_A4));
// digitalWrite(TIMO_PIN, !digitalRead(TIMO_PIN));
// digitalWrite(LED_PIN, Timo_ON);
// digitalWrite(TIMO_PIN, Timo_ON);
delay(100);

} // end Test Loop

//################################################################################################

#else

// ***************** input callback function *************

void gotDMXCallback(int slots) {
got_dmx = slots;
}

void gotRDMCallback(int len) {
// rdm start code and checksum are validated before this is called
got_rdm = len;
}

/************************************************************************

The main loop checks to see if dmx input is available (got_dmx>0)
And then reads the level of dimmer 1 to set PWM level of LED connected to pin 14

*************************************************************************/


void loop() {
// SerialUSB.print(PIN_DMX_RX);
if ( got_dmx ) {
input_value = SAMD21DMX.getSlot(start_address);
/*
*#ifdef SERIAL_DEBUG // <-----------------------------------DEBUG----`
SerialUSB.print("Chval ");
SerialUSB.println(input_value);
#endif
*/

//gamma correct
input_value = (input_value * input_value ) / 255;
//ESP8266 PWM is 10bit 0-1024
analogWrite(LED_PIN,2*input_value);
got_dmx = 0; //reset

} else if ( got_rdm ) {

uint8_t* rdmdata = SAMD21DMX.receivedRDMData();

uint8_t cmdclass = rdmdata[RDM_IDX_CMD_CLASS];
uint16_t pid = (rdmdata[RDM_IDX_PID_MSB] << 8 ) | rdmdata[RDM_IDX_PID_LSB];

/*
#ifdef SERIAL_DEBUG // <-------------check CMD received is correct----------------------DEBUG----
SerialUSB.println("Discovery ");
SerialUSB.print("cmdclass ");
SerialUSB.println(cmdclass);
SerialUSB.print("pid ");
SerialUSB.println(pid);
#endif
*/

if ( cmdclass == RDM_DISCOVERY_COMMAND ) {


if ( pid == RDM_DISC_UNIQUE_BRANCH ) {
if ( discovery_enabled ) {
uint64_t tv = SAMD21DMX.THIS_DEVICE_ID.getValue();
UID u;
u.setBytes(&rdmdata[24]); //lower
uint64_t uv = u.getValue();

if ( tv >= uv ) {
u.setBytes(&rdmdata[30]); //upper
uv = u.getValue();
if ( tv <= uv ) {
SAMD21DMX.sendRDMDiscoverBranchResponse();
}
}
}
} else { // mute RDM_DISCOVERY_COMMAND PIDs
UID destination;
destination.setBytes(&rdmdata[RDM_IDX_DESTINATION_UID]);

#ifdef SERIAL_DEBUG // <-----------------------------------DEBUG----`
SerialUSB.print("destination ");
SerialUSB.println(destination);
#endif

if ( pid == RDM_DISC_MUTE ) {
if ( destination == SAMD21DMX.THIS_DEVICE_ID ) {
discovery_enabled = 0; // <----- THIS is where the trouble starts.
// send ACK
UID source;
source.setBytes(&rdmdata[RDM_IDX_SOURCE_UID]);
SAMD21DMX.sendMuteAckRDMResponse(RDM_DISC_COMMAND_RESPONSE, source, RDM_DISC_MUTE);
}
} else if ( pid == RDM_DISC_UNMUTE ) {
if ( destination == BROADCAST_ALL_DEVICES_ID ) {
// just un-mute
discovery_enabled = 1;
} else if ( destination == SAMD21DMX.THIS_DEVICE_ID ) {
discovery_enabled = 1;
// send ACK
UID source;
source.setBytes(&rdmdata[RDM_IDX_SOURCE_UID]);
SAMD21DMX.sendMuteAckRDMResponse(RDM_DISC_COMMAND_RESPONSE, source, RDM_DISC_UNMUTE);
}
}

}

} else if ( cmdclass == RDM_GET_COMMAND ) {

#ifdef SERIAL_DEBUG // <-----------------------------------DEBUG----
SerialUSB.println("GET CMD");
#endif

UID destination;
destination.setBytes(&rdmdata[RDM_IDX_DESTINATION_UID]);

if ( destination == SAMD21DMX.THIS_DEVICE_ID ) {
UID source;
source.setBytes(&rdmdata[RDM_IDX_SOURCE_UID]);

if ( pid == RDM_DEVICE_START_ADDR ) {

uint8_t sa[2];
sa[0] = start_address >> 8;
sa[1] = start_address & 0xff;
SAMD21DMX.sendRDMGetResponse(source, pid, sa, 2);
} else if ( pid == RDM_DEVICE_MFG_LABEL ) {
const char * label = MFG_LABEL;
SAMD21DMX.sendRDMGetResponse(source, pid, (uint8_t*)label, 5);
} else if ( pid == RDM_DEVICE_MODEL_DESC ) {
const char * label = MODEL_DESCRIPTION;
SAMD21DMX.sendRDMGetResponse(source, pid, (uint8_t*)label, 13);
} else if ( pid == RDM_DEVICE_DEV_LABEL ) {
SAMD21DMX.sendRDMGetResponse(source, pid, device_label, strlen((const char*)device_label));
}


}
} else if ( cmdclass == RDM_SET_COMMAND ) {

#ifdef SERIAL_DEBUG // <-----------------------------------DEBUG----
SerialUSB.println("SET CMD");
#endif

UID destination;
destination.setBytes(&rdmdata[RDM_IDX_DESTINATION_UID]);

if ( destination == SAMD21DMX.THIS_DEVICE_ID ) {
UID source;
source.setBytes(&rdmdata[RDM_IDX_SOURCE_UID]);

if ( pid == RDM_DEVICE_START_ADDR ) {
uint16_t scratch = (rdmdata[24] << 8) + rdmdata[25];
if (( scratch > 0 ) && ( scratch < 513 )) {
start_address = scratch;
}
SAMD21DMX.sendAckRDMResponse(RDM_SET_COMMAND_RESPONSE, source, pid);

} else if ( pid == RDM_DEVICE_DEV_LABEL ) {
uint8_t llen = 0;
if ( rdmdata[2] > 24 ) { //label not empty string
llen = rdmdata[2] - 24;
if ( llen > 32 ) { //limit to max 32 characters
llen = 32;
}
}
for ( uint8_t j=0; j<33; j++) { //copy label, zero the rest of the array
if ( j < llen ) {
device_label[j] = rdmdata[24+j];
} else {
device_label[j] = 0;
}
} // <-for
SAMD21DMX.sendAckRDMResponse(RDM_SET_COMMAND_RESPONSE, source, pid);
} // <-pid RDM_DEVICE_DEV_LABEL
}
}
got_rdm = 0;
} //gotRDM
}
#endif

//-------------------------------------- END of RDMDeviceTest.ino -------------------------------------------------------------

//--------------------- Changes to MAIN code needed --------------------------------------------------------------------------
It was necessary to make changes to the Tx/Rx and SERCOM IRQ handler in LXSAMD21DMX.h
( line 530 to end)

#define use_optional_sercom_macros 6 // <-- created my own macro "Serial.xxx" Use Port 0 aka calls Serial.xxx go to Port 0
// #define use_optional_sercom_macros 1 // Use Port 1 aka calls Serial1.xxx go to Port 0


#ifdef use_optional_sercom_macros

#if ( use_optional_sercom_macros == 1 )
//********************** optional sercom macros 1 **********************
// --might be used for Arduino Zero sercom2 pins 3 and 4

#define PIN_DMX_RX (3ul)
#define PIN_DMX_TX (4ul)
#define PAD_DMX_RX SERCOM_RX_PAD_1
#define PAD_DMX_TX UART_TX_PAD_0

// Set to PIO_SERCOM or PIO_SERCOM_ALT
#define MUX_DMX_RX PIO_SERCOM_ALT
#define MUX_DMX_TX PIO_SERCOM_ALT

// SERCOMn is pointer to memory address where SERCOM registers are located.
#define DMX_SERCOM SERCOM2

// sercomN is C++ wrapper for SERCOMn (passed to UART constructor)
#define DMX_sercom sercom2

// sercom handler function
#define DMX_SERCOM_HANDLER_FUNC SERCOM2_Handler

#warning Using use_optional_sercom_macros = 1

#elif ( use_optional_sercom_macros == 2 )

//********************** optional sercom macros 2 **********************
// --might be used for Adafruit M0 Feather sercom1 pins 10 and 11

#define PIN_DMX_RX (11ul)
#define PIN_DMX_TX (10ul)
#define PAD_DMX_RX SERCOM_RX_PAD_0
#define PAD_DMX_TX UART_TX_PAD_2

// Set to PIO_SERCOM or PIO_SERCOM_ALT
#define MUX_DMX_RX PIO_SERCOM
#define MUX_DMX_TX PIO_SERCOM

// SERCOMn is pointer to memory address where SERCOM registers are located.
#define DMX_SERCOM SERCOM1

// sercomN is C++ wrapper for SERCOMn (passed to UART constructor)
#define DMX_sercom sercom1

// sercom handler function
#define DMX_SERCOM_HANDLER_FUNC SERCOM1_Handler

#warning Using use_optional_sercom_macros = 2

#elif ( use_optional_sercom_macros == 3 )

//********************** optional sercom macros 3 **********************
// --might be used for Feather M0 pins D0 and D1
// --added by shiftingtech 7-21-19

#define PIN_DMX_RX (0ul)
#define PIN_DMX_TX (1ul)
#define PAD_DMX_RX SERCOM_RX_PAD_3
#define PAD_DMX_TX UART_TX_PAD_2

// Set to PIO_SERCOM or PIO_SERCOM_ALT
#define MUX_DMX_RX PIO_SERCOM_ALT
#define MUX_DMX_TX PIO_SERCOM_ALT

// SERCOMn is pointer to memory address where SERCOM registers are located.
#define DMX_SERCOM SERCOM2

// sercomN is C++ wrapper for SERCOMn (passed to UART constructor)
#define DMX_sercom sercom2

// sercom handler function
#define DMX_SERCOM_HANDLER_FUNC SERCOM2_Handler

#warning Using use_optional_sercom_macros = 3

#elif ( use_optional_sercom_macros == 4 )

//********************** optional sercom macros 4 **********************
// --replaces Serial1 on MKR1000
// --requires commenting out lines 178 to 186 in
// Arduino15/packages/arduino/hardware/samd/1.8.4/variants/mkr1000/variant.cpp
// otherwise Serial1 will conflict on Sercom5 and this won't compile

#define PIN_DMX_RX (13ul)
#define PIN_DMX_TX (14ul)
#define PAD_DMX_RX SERCOM_RX_PAD_3
#define PAD_DMX_TX UART_TX_PAD_2

// Set to PIO_SERCOM or PIO_SERCOM_ALT
#define MUX_DMX_RX PIO_SERCOM_ALT
#define MUX_DMX_TX PIO_SERCOM_ALT

// SERCOMn is pointer to memory address where SERCOM registers are located.
#define DMX_SERCOM SERCOM5

// sercomN is C++ wrapper for SERCOMn (passed to UART constructor)
#define DMX_sercom sercom5

// sercom handler function
#define DMX_SERCOM_HANDLER_FUNC SERCOM5_Handler

#warning Using use_optional_sercom_macros = 4

#elif ( use_optional_sercom_macros == 6 )

//********************** optional sercom macros 6 ### created by Lee Paker ### **********************
// Arduino Zero Port 0 aka Serial.xxx calls go to this port Port 1 aka Serial1.xxx calls go to pins D0,D1
// SerialUSB.xxx calls go to the USB port and the "Serial Monitor function of the Arduino
#define PIN_DMX_RX (31ul)
#define PIN_DMX_TX (30ul)
#define PAD_DMX_RX SERCOM_RX_PAD_3. //per Sparkfun SAMD21 Dev Breakkout
#define PAD_DMX_TX UART_TX_PAD_2. //per Sparkfun SAMD21 Dev Breakkout

// Set to PIO_SERCOM or PIO_SERCOM_ALT
#define MUX_DMX_RX PIO_SERCOM_ALT
#define MUX_DMX_TX PIO_SERCOM_ALT

// SERCOMn is pointer to memory address where SERCOM registers are located.
#define DMX_SERCOM SERCOM5

// sercomN is C++ wrapper for SERCOMn (passed to UART constructor)
#define DMX_sercom sercom5

// sercom handler function
#define DMX_SERCOM_HANDLER_FUNC SERCOM5_Handler

#warning Using use_optional_sercom_macros = 6

#elif (use_optional_sercom_macros == 5)
//********************** optional sercom macros 5 **********************
// --might be used for SEEED XIAO M0 sercom2 pins 3 and 4

#define PIN_DMX_RX (3ul)
#define PIN_DMX_TX (4ul)
#define PAD_DMX_RX SERCOM_RX_PAD_3
#define PAD_DMX_TX UART_TX_PAD_0

// Set to PIO_SERCOM or PIO_SERCOM_ALT
#define MUX_DMX_RX PIO_SERCOM_ALT
#define MUX_DMX_TX PIO_SERCOM_ALT

// SERCOMn is pointer to memory address where SERCOM registers are located.
#define DMX_SERCOM SERCOM2

// sercomN is C++ wrapper for SERCOMn (passed to UART constructor)
#define DMX_sercom sercom2

// sercom handler function
#define DMX_SERCOM_HANDLER_FUNC SERCOM2_Handler

#warning Using use_optional_sercom_macros = 5

#endif

#else
//********************** default sercom macros **********************

#define PIN_DMX_RX (5ul)
#define PIN_DMX_TX (4ul)
#define PAD_DMX_RX SERCOM_RX_PAD_3
#define PAD_DMX_TX UART_TX_PAD_2

// Set to PIO_SERCOM or PIO_SERCOM_ALT
#define MUX_DMX_RX PIO_SERCOM_ALT
#define MUX_DMX_TX PIO_SERCOM_ALT

// SERCOMn is pointer to memory address where SERCOM registers are located.
#define DMX_SERCOM SERCOM4

// sercomN is C++ wrapper for SERCOMn (passed to UART constructor)
#define DMX_sercom sercom4

// sercom handler function
#define DMX_SERCOM_HANDLER_FUNC SERCOM4_Handler

#endif

#endif // ifndef LXSAM21_DMX_H