sparkfun / SparkFunDMX

https://www.sparkfun.com/
Other
30 stars 6 forks source link

DMX read example not working for me #3

Closed macdroid53 closed 8 months ago

macdroid53 commented 4 years ago

I can't seem to get correct values from a DMX bus.

I'm using an ESP32.

I can put my Saleae logic analyzer on the rx pin and it decodes the DMX values fine. But, dmx.read() in the read example, never returns the correct value. Always 0.

Questions:

Any idea what I'm doing wrong?

marmilicious commented 4 years ago

@macdroid53 When I was looking for a DMX library for the ESP32 I tried this library, however I could not get it to work for me. It seemed like it was receiving data but it wasn't correct, but I don't have a analyzer so couldn't really investigate in depth like you did. If you're not specifically wanting to use the SparkFunDMX library, I'll throw this suggestion out which did work for me on the ESP32: https://github.com/claudeheintz/LXESP32DMX

AndyEngland521 commented 4 years ago

Hmm, I was trying to create a stripped down version of LXESP32DMX. @macdroid53 I believe you're correct in your thinking that the interrupt still continues. It knows the startCode has occurred when the interrupt is triggered twice with an interval greater than 87 uS. The fix is probably to change

else if (_READWRITE == _READ)//In a perfect world, this function ends serial communication upon packet completion and attaches RX to a CHANGE interrupt so the start code can be read again
  { 
    while (DMXSerial.available())
    {
      if (currentChannel == 0)
      {
        DMXSerial.read();
      }
      dmxData[currentChannel++] = DMXSerial.read();
    }
    if (currentChannel > chanSize) //Set the channel counter back to 0 if we reach the known end size of our packet
    {
      currentChannel = 0;
    }
}

to

else if (_READWRITE == _READ)//In a perfect world, this function ends serial communication upon packet completion and attaches RX to a CHANGE interrupt so the start code can be read again
  { 
    while (DMXSerial.available())
    {
      if (currentChannel == 0)
      {
        DMXSerial.read();
      }
      dmxData[currentChannel++] = DMXSerial.read();
    }
    if (currentChannel > chanSize) //Set the channel counter back to 0 if we reach the known end size of our packet
    {
      currentChannel = 0;
          attachInterrupt(digitalPinToInterrupt(rxPin), startCode, CHANGE);
    }
  }

and changing

void SparkFunDMX::startCode() {
  if ((micros() - _lastTimeStamp) >= 87)
  {
    currentChannel = 0;
    DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);
  }
  _lastTimeStamp = micros();
}

to

void SparkFunDMX::startCode() {
  if ((micros() - _lastTimeStamp) >= 87)
  {
    currentChannel = 0;
        detachInterrupt(digitalPinToInterrupt(rxPin));
    DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);
  }
  _lastTimeStamp = micros();
}

However I don't have any DMX Shields lying on my desk and probably won't be able to snag a few to test until later in the week.

macdroid53 commented 4 years ago

Wouldn't you want to disconnect the serial object as well?

else if (_READWRITE == _READ)//In a perfect world, this function ends serial communication upon packet completion and attaches RX to a CHANGE interrupt so the start code can be read again
  { 
    while (DMXSerial.available())
    {
      if (currentChannel == 0)
      {
        DMXSerial.read();
      }
      dmxData[currentChannel++] = DMXSerial.read();
    }
    if (currentChannel > chanSize) //Set the channel counter back to 0 if we reach the known end size of our packet
    {
      currentChannel = 0;
          DMXSerial.end(); //Disconnect serial object
          attachInterrupt(digitalPinToInterrupt(rxPin), startCode, CHANGE);
    }
  }
macdroid53 commented 4 years ago

@marmilicious I have that library set up. It consistently gets correct values for any DMX slot under 13. Not sure what's up with that, but I did log an issue.

jepye commented 4 years ago

So is there any progress on this? The data I receive is shifted by some inconsistent amount every frame and I end up seeing the start frame as two consecutive channels set to 0.

After spending a lot of time failing to get the LXESP32DMX library to work yesterday my modified inputTest.ino suddenly works today. However, the SparkFun library is simpler to use and I need to be able to distribute the code and tell people to use a library that is working easily.

macdroid53 commented 4 years ago

I ended up using LXESP32DMX. I did modify the example slightly for my purposes. And it is working just fine. Note, I am using only for reading the DMX values.

Also, note, the serial output from the example provided with the library outputs nothing if all channels are set to zero (i.e. light off, DMX value 0). If you bump one of the selected channels, it will show the value.

macdroid53 commented 4 years ago

@AndyEngland521 Interesting, I got a notification that you'd posted to this thread from github...but, I don't see the replay here.

You asked: "What were you using to send DMX data?"

I used two sources, my DMX test unit and a HOG 4. The logic analyzer connected said both were producing solid DMX, with repeatable values in each slot.

It appeared the code did not trigger on the break reliably. And thus did not consistently read the same slot each time for a selected slot.

LXDMX is working fine...after I figured out the example only sends if a chosen slot is non zero.

AndyEngland521 commented 4 years ago

Noted, I'm working on a solution at the moment that uses a timer as an interrupt instead of a pin change interrupt and it's detecting breaks reliably. I deleted my comment as I realized I didn't really need the info, but it does help a bit. Currently working out kinks.

AndyEngland521 commented 4 years ago

@macdroid53 @marmilicious @jepye v1.0.5 has a new way of detecting startCodes that seems to be far more reliable. Everything is working over here on my equipment. Give it a try if you're feeling up to it.

macdroid53 commented 4 years ago

Hi Andy, Sorry for the delay, many diversions. I have run the new code. Seems to work for me, but...and it's probably my expectations, there's something I don't understand.

With DMX gear I've used in theater, you select the address of the device, any number from 1 to 512.

So, for a four channel dimmer, I might choose 31. And the device knows it's now on channel 31,32,33,34. Or 500 and then 500,501,502,503.

With this driver I need to set Total_Channels to be some value greater than the highest channel number to be read. So if I set it to 100, I can read 31, but not 101. (Also, if I set it to 512, the ESP32 crashes repeatedly. 400 is ok, but 450 crashes.)

luksal commented 4 years ago

Hello @AndyEngland521 the new detection of the start code works more reliable, but i still got problems, where the channels are shifted. Either in the way that channel 2 gets channel 3 or channel 2 gets channel 1. Any ideas on how to fix this?

greiginsydney commented 4 years ago

Hi @AndyEngland521 ,

I'm wanting to receive DMX into the SparkFun DMX shield, and for my testing I'm generating a stream using an ENTTEC USB dongle, but regardless of the value I send this basic test code always reports a DMX value of zero:

#include <SparkFunDMX.h>

SparkFunDMX dmx;

//Channel Definitions
#define TOTAL_CHANNELS 512

int DmxChannel = 1;
uint8_t currentValue = 0;

void setup()
{
  dmx.initRead(TOTAL_CHANNELS);           // initialization for complete bus
  Serial.begin(115200);
}

void loop()
{
  dmx.update();
  currentValue = dmx.read(DmxChannel);
  Serial.println("DMX Channel = " + String(DmxChannel) + ", Pattern = " + String(currentValue));
}

I note @macdroid53 reports setting a TOTAL_CHANNELS of 512 will crash the ESP. Is it critical that this value match the number of channels being transmitted, or is TOTAL_CHANNELS just used to instantiate the channel array and isn't tied to the timing?

Does anything look obviously wrong in my code? I've based it on the DMXInput example. I had earlier included these two lines, but when I scanned the library they didn't seem relevant, so I pulled them out:

uint8_t x = 0;
int myDirection = 1;

Thanks.

luksal commented 4 years ago

I finally found a robust working solution using ESP-IDF functions and the build-in break detection. I will prepare an example and upload it soon

AndyEngland521 commented 4 years ago

@luksal Thanks a ton! looking forward to it.

luksal commented 4 years ago

Here you go: https://github.com/luksal/ESP32-DMX-RX

sorazs commented 4 years ago

me too receive invalid value from DMX bus, but i resolved modifying SparkFunDMX.cpp at row 58 from "if (_interruptCounter > 9)" to "if (_interruptCounter > 7)"

macdroid53 commented 4 years ago

I've been working on a version that does not need modifications to the serial driver. Unfortunately, I found a bug in the driver and now am in the bowels of the driver. The code is based off that mentioned by luksal above, but is ESP-IDF rather than Arduino.

luksal commented 4 years ago

You can use my code with ESp-IDF if you like, because there are no more dependencies on the Arduino Framework. It's packet in an Arduino library, but you can use it out of the box with Arduino IDE or PlatfromIO if you like. For other IDEs you just need the two library files

macdroid53 commented 4 years ago

Did you figure out the lost 32 bytes issue? That was the crux of what was going on in issues report in ESP over at github.

luksal commented 4 years ago

Unfortunately, I haven't had the time to do this yet. I hope that this will be declared as a bug in ESP-IDF and that it will be fixed without the need to change the core files. As a work around I have limited the selectable address space accordingly and so far I can handle it without any problems.

macdroid53 commented 4 years ago

Limiting the address space is ok if you control the design of the receiving device (i.e. the spark fun board driving LED strings). But, sort of cripples the code if it would be used in other situations where devices are expected handle the full range of DMX addresses.

As for being declared a bug in ESP-IDF...I don't know what has to happen to make the official. The issue you filed has been "assigned", but I don't think either assigner or the assignee has participated in the discussion over there. At this point, the solution has been shown to work in a 3.x version of the IDF, no change has been made to the 4.x code, and 4.x has been released...so, I have no idea if it is considered a bug... At this point I can get all 512 DMX slots, but, it looses sync with the break detect and lights flash at that point because for one cycle it DMX value changes abruptly to the correct value then back to the wrong value. (My higher level of code is a modded version of yours, and I might have broken the break sync...I need to look at that in more detail, haven't had time lately.

christo83 commented 2 years ago

Hello,

I use an ESP32 Thing Plus board and a DMX shield. I tried to read the input from a DMX table but without success. I used the arduino library but got this first error : U2TXD_OUT_IDX not defined. So I replaced the variable in the code by this : U0TXD_OUT_IDX. The code uploaded well. Nevertheless, when I try to read a channel the value is always 0. I tried some solutions proposed above without success.

Do you have any idea how to solve this issue?

Thank you in advance