E1.20 RDM (Remote Device Management) Protocol Forums

E1.20 RDM (Remote Device Management) Protocol Forums (http://www.rdmprotocol.org/forums/index.php)
-   RDM General Implementation Discussion (http://www.rdmprotocol.org/forums/forumdisplay.php?f=4)
-   -   Discovery response not recognized (http://www.rdmprotocol.org/forums/showthread.php?t=1330)

lensfocus January 12th, 2022 04:36 PM

Discovery response not recognized
 
I am developing a new lighting device, and need to implement the RDM protocol. I am new to DMX and RDM, but I have the DMX working fine. I am having a problem getting the controller that I am using to recognize my response to the discovery message.



I'm using an ENTTEC USB PRO MK2 for testing, and am trying to get it to recognize my board in the RDM discovery process. It is not seeing my responses to the DISC_UNIQUE_BRANCH message, and I'm not sure why. I can see my response on the RS485 bus using a scope. I know it is seeing my response, because it is continuing to send discovery messages with a narrowing range of IDs, so it thinks there is a collision on the bus. I'm thinking that my checksum is not correct?


I saw two examples of source code on the web for this, and they both use the same algorithm to encode the response. However, in looking at the protocol document (ANSI E1.20), there is a disconnect somewhere.


Here is the suggested code from the web to send a response:

_rdmCheckSum = 6 * 0xFF;
for (byte i = 0; i < 7; i++)
disc->headerFE[i] = 0xFE;
disc->headerAA = 0xAA;
for (byte i = 0; i < 6; i++) {
disc->maskedDevID[i+i] = _devID[i] | 0xAA;
disc->maskedDevID[i+i+1] = _devID[i] | 0x55;
_rdmCheckSum += _devID[i];
}
disc->checksum[0] = (_rdmCheckSum >> 8) | 0xAA;
disc->checksum[1] = (_rdmCheckSum >> 8) | 0x55;
disc->checksum[2] = (_rdmCheckSum & 0xFF) | 0xAA;
disc->checksum[3] = (_rdmCheckSum & 0xFF) | 0x55;

I have two issues with this.
1. Why do they initialize the checksum to 6 * 0xFF instead of zero?
2. The checksum should be adding the actual bytes sent after they are ORed, not the original bytes.


So, I tried changing it to this, to comply with the protocol:

_rdmCheckSum = 0;
for (byte i = 0; i < 7; i++)
disc->headerFE[i] = 0xFE;
disc->headerAA = 0xAA;
for (byte i = 0; i < 6; i++) {
u32 idx = i+i;
disc->maskedDevID[idx] = _devID[i] | 0xAA;
_rdmCheckSum += disc->maskedDevID[idx];
idx++;
disc->maskedDevID[idx] = _devID[i] | 0x55;
_rdmCheckSum += disc->maskedDevID[idx];
}
disc->checksum[0] = (_rdmCheckSum >> 8) | 0xAA;
disc->checksum[1] = (_rdmCheckSum >> 8) | 0x55;
disc->checksum[2] = (_rdmCheckSum & 0xFF) | 0xAA;
disc->checksum[3] = (_rdmCheckSum & 0xFF) | 0x55;

but I still don't get a MUTE message saying that the controller sees my response.

Thanks for any help you can provide!

ericthegeek January 13th, 2022 08:47 AM

You can use this EUID calculator to see if the conversion is being done correctly.

http://rdm.openlighting.org/tools/uid-converter


The converter is bidirectional, so you can enter your UID and see the expected EUID. You can also dump the EUID from the wire and decode it.

lensfocus January 13th, 2022 09:49 AM

Thanks for that link, ericthegeek.


It confirms that my re-write has the correct data. However, I'm still not getting a "MUTE" reply, the controller is just continuing to narrow the address range, thinking there is a collision.


It really helps to rule that out. Now that I know that the data is correct, I can start looking at a possible hardware problem. The signal on my scope showing my output data does look a little weird.


Any idea why the example software has those changes? -Like initializing the checksum to non-zero..

sblair January 13th, 2022 10:11 AM

Welcome to the forums!

A couple random thoughts of things I've ran into before to also check:

- Could be a timing issue in the response. Make sure everything is within the right timing window.
- You might need to leave some additional time between sending the packet and shutting off the Tx drive. It is super easy to disable TX before the packet has fully been sent chopping off some bits at the end and causing the behavior you are seeing.

Scott

ericthegeek January 13th, 2022 10:27 AM

Look at the 485 data on the wire with a scope and decode it. Then you can see what's actually being sent, not what you think you're sending. As Scott said, turning off Transmit Enable prematurely is a common problem. You need to wait for the shift register to finish sending the byte, not for the "TX FIFO empty" interrupt.



I ran the reference code you found through a C compiler and it does produce the correct output. It has some clever boolean optimizations to reduce the work at runtime. For example: If you add 0xAA and 0x55, you get 0xFF.


If you add (0xAA.or.VALUE) to (0x55.or.VALUE) you get 0xFF+VALUE. Do this six times (for each byte of the UID), and you see why it init's the checksum to 6 * 0xFF.

lensfocus January 13th, 2022 10:45 AM

Thanks so much for your responses, Scott and ericthegeek..


I found the problem, it was a bad ground on my RS485 driver chip!


I did try adding a delay after sending the packet before enabling the receive, but that was allright, I am waiting till the Tx buffer is empty first.



Anyway, I still have the question about the checksum initialization.


ericthegeek, I understand what you said that 6 * 0xFF is the same as adding the header bytes, but the header isn't supposed to be included in the discovery response checksum! I am now getting a "MUTE" instruction addressed to my UID after discovery after initially setting the checksum to zero.


Thanks again, this is a great forum!

ericthegeek January 13th, 2022 11:00 AM

Quote:

Originally Posted by lensfocus
I found the problem, it was a bad ground on my RS485 driver chip!

Oh good, glad you found the problem.



Quote:

Originally Posted by lensfocus
ericthegeek, I understand what you said that 6 * 0xFF is the same as adding the header bytes, but the header isn't supposed to be included in the discovery response checksum! I am now getting a "MUTE" instruction addressed to my UID after discovery after initially setting the checksum to zero.


The 6 * 0xFF isn't from the header (the header is 0xFE, not 0xFF).


Each byte of the UID is Boolean OR'd with 0xAA and 0x55.


We've established that (0xAA.or.VALUE)+(0x55.or.VALUE) == 0xFF+VALUE.


If you expand that out 6 times, once for each byte of the EUID you get:


(0xFF+UID_5)+(0xFF+UID_4)+(0xFF+UID_3)+(0xFF+UID_2)+(0xFF+UID_1)+(0xFF +UID_0)


That can be simplified to (6*0xFF)+UID_5+UID_4+UID_3+UID_2+UID_1+UID_0, which is the calculation that's done on that code snippet. Whoever figured out that simplification is clearly smarter than I am.


Quote:

Originally Posted by lensfocus
Thanks again, this is a great forum!


That's why we're here. The goal is to keep RDM developers on track and to help improve interoperability for everyone.


It's often worth browsing through older threads too, it can help you avoid many of the common pitfalls.

sblair January 13th, 2022 11:19 AM

Quote:

Originally Posted by ericthegeek (Post 3418)
Oh good, glad you found the problem.

Whoever figured out that simplification is clearly smarter than I am.

And that is exactly why I don't try to be clever in my code. I'll just end up confusing myself later. I don't recommend trying to be too smart in your code. Eric is one of the more brilliant people I know. If the code is trying to be too clever for him, then it's too clever for most anyone.

lensfocus January 13th, 2022 12:09 PM

Thanks, that actually makes sense now. But I absolutely agree that getting too tricky (to save a processor cycle or two) usually makes for un-decipherable code in the future.


All times are GMT -6. The time now is 05:17 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2022, vBulletin Solutions, Inc.