-
Notifications
You must be signed in to change notification settings - Fork 26
Receive more than 480 channels #1
Comments
Any idea how to fix this? I have a fully working, non-arduino, esp-idf, freertos version of my code running now and can confirm nothing above chan 480. I can experiment...just not sure where to start. Shouldn't it suspend checking for the break until after it receives 512 bytes? I monitored the event.size when in DMX_DATA mode and it is always 120. So it appears it gets a thinks it sees a break after reading 120x4, then flushes. So what is it seeing as the early break...or am I not thinking right about what is going on? |
I currently have no spare time to work on this issues. But I know why this happens and how to fix this 😅🙈 |
Well, I've got the time...I'm retired. So I'm willing to help if you give some direction. |
I put your fix into my code. freertos just reboots every time it hits the new code. So I checked the values of event.size and current_rx_addr at that point. So, when it reads that data at that point the total is still 480. I started reading the uart.c code. It appears the 120 bytes event.size reports (both in the 'case UART_DATA:' section and in the 'case UART_BREAK:' section in dmx.c) comes from the define in uart.c '#define UART_FULL_THRESH_DEFAULT (120)'. Does that make sense? |
Mhh this fix was just an idea and i had no time to test it... |
So maybe I have to move the receive code to be full interrupt driven |
I saw the "needs testing" flag, that's why I had at it. ;) Hmm...interrupt maybe.BUt, looking at the low level routines in uart.c (and at the ESP32 tech manual) it looks like the driver is doing interrupts on the 120 bytes avail in the uart buffer.) But, seems weird that it's getting a data signal at every 120 bytes, then gets a break signal at 480 bytes (i.e. 360+ 120) and that means it still needs to find 32 more bytes to get 512 DMX slots. Below is what I took from your update. If the line in bold (and it's associated code) is uncommented the ESP32 panic reboots repeatedly. With it commented out and the preceding print statements are uncommented, I can see the state event size, and count of bytes delivered so far. Note, I also added prints to see if ther was any other kind of uart error happening. These never print, so I don't think there are overruns, etc. happening.
|
So what does the stack trace say? |
Repeats this: `Rebooting... ELF file SHA256: 0000000000000000000000000000000000000000000000000000000000000000 Backtrace: 0x400838d8:0x3ffb5540 0x400d1025:0x3ffb5580 0x400832b9:0x3ffb55b0 Rebooting...` |
Now you need to decode the Backtrace: https://github.com/me-no-dev/EspExceptionDecoder |
After much digging in the bowels of the internet...I discovered the magic incantation to put in the platformio.ini file to get necessary output to the elf file for the decoder to do something. That done, it provides:
uart_event_task at src/dmx.c line 158 is:
|
What does your high water mark says? |
High water mark? Where? |
So, spent a lot of quality time with this today... ;) after the break detect, it reads 120 bytes for each UART_DATA event. |
Maybe the |
uart_get_buffered_len is how I came to my conclusions above. But it returns 0 once the break event has triggered. |
I created an Issue at the ESP-IDF repository: espressif/esp-idf#4537 |
I posted in the esp forum trying to see if anyone had any ideas, but haven't seen any replies. So that is a good idea. |
I found this when googling for solutions to BREAK detection (since the ESP UART seems designed specifically for using BREAK as an end-of-message marker). In one of the threads related to this, someone was suggesting using BREAK to know when new data is in the buffer, which is a problem because it's acceptable for a DMX transmitter to only send one packet per second, which would create a 1 second lag. So you just need to figure out how to flush that buffer. However, for BREAK detection, Sparkfun has a brilliant solution in their library: https://github.com/sparkfun/SparkFunDMX They turn the pin into a GPIO, watch for it to go low for 88us (using interrupts), and then switch the port over to a UART to receive the data. |
@benpeoples unfortunately the detection of the break did not work properly and reliably. As a result, there were jumping channels which made it impossible to use. See also Issue 3 in the SparkFun repository sparkfun/SparkFunDMX#3 |
ARGH. That's frustrating. I'd hoped it would do it. I did a deep dive yesterday into the low level workings of the ESP32 UART. I think it's possible to get BRK_DET to successfully tell you that you have a DMX BREAK (in time), but it (the UART) is really not well designed to do this and I'm concerned that it's going to be unreliable. When I started my current project, it was pre-ESP32 and I was using an external SPI UART... I guess I'm heading back to that. =) Good luck! |
You can try to reconfig the IRQ after uart_driver_install() to throw an event after every byte. Of course there are a lot of events thrown then (one after every byte), so you get every single byte one by one until next break occurs.
|
This may be the case for DMX use with LED strings. Not sure how well that solution will work when using it for PWM control of multiple channels of the 60/50 hertz duty cycle of a triac dimmer. |
I just tested it (not with Arduino, but this should not matter); Another solution (with the default interrupt at 120 bytes) I just tried is to modify the uart.c in the uart_rx_intr_handler_default(void *param).
with this you can handle an additional receive call in the dmx.cpp "case UART_BREAK:" in the uart_event_task:
I hope I have modified every variable name correctly in the snippets to work with the given dmx.cpp, because I am using my own implementation, but basically with the same workflow. |
Why not configure the UART to throw an event after 128 or even 512 bytes? then we should get all channels and have very little CPU overhead |
Yes, that was also my first thought, but some DMX Controllers only sent the slots needed and not the full 512 slot frame (I have a simple 24 fader controller that only sends out the first 24 slots).. In this case we do not recognize the whole sent frame if the controller sends something between the n*128 bytes. |
If you know the sender that is fine. And, you restrict, your receiver to that the first X number of slots, fine, but that is rarely the case if what you are developing for use in professional venue. The DMX specification is to send all 512 slots and the receiver is supposed to pick the ones that match its address setting. Professional receivers for stage lighting and such can, typically, be addressed to any one or more address in the 512 range. So it needs to get all 512 frames, extract one or more address frames from anywhere in the 512 packet. It also, should be able to determine if the universe. So, the low level driver can't ignore part of the packet. And, must respond to values changing in each of it's addressed frames so as not to get choppy fades or jumps from one level to another. Or worse lose a frame and see it as 0, setting the PWM so as it appears to flicker or pulse. Some of this can, and should, be managed in higher level code, but the low level driver needs to reliably receive the complete frame. |
Just to chime in, it's also VERY important that you check the start code. There are many things other than the NSC now, so you need to be able to get the break, check the start code after the BREAK, and then start counting slots until you get to yours-- it's perfectly fine to have a state machine that just throws away packets one by one as they come in (that is, you don't have to buffer the full 512 slots). And I agree that you don't want to ever rely on there being 512 slots. Standard does not specify a minimum number of slots, and I've actually done some lovely work by sending devices 12 slot universes at some ridiculous framerate. Also, I've come across devices (specifically addressable DMX pixels) that are perfectly happy to have a start address above 512. While I don't think there's any requirement that you support this in the standard, not having your software fall over if it keeps getting bytes after the 512th slot would be good for reliability. |
Because of clearing the uart queue after detected break, the last channels are not received
The text was updated successfully, but these errors were encountered: