Closed mahmoud2802 closed 1 year ago
No it currently does not.
do you have any plan to add?
What platform do you use?
Currently I do not have plans, but I doubt I would support it for platforms other than esp if I did at first.
sorry. i don't understand what is your mean of platform .
i want build a led WiFi controller(esp8266 12f) with support multiple led chip (ws2812-SK6812 ,ws2821 (DMX512)).i use your library and it doesn't support for DMX 512 protocol .
Platforms or architecture refers to the CPU type. Many arduinos are Atmel AVR, but you mentioneded esp8266, which is another.
If I was gifted some of these ws2821 I would add support for esp.
I was alos thinking about this option, even considered hacking into your code, but the structure of the library is a little beyond me. Reason is actually that i have not found a reliable DMX output for ESP8266 in combination with wifi, and i know your DMA output is reliable. DMX does require some additional hardware (The MAX485), and the format is a little different from the normal one, being that it does use 1 start & 2 stop bits, but it is normal Serial 8N2 (inverted polarity for the MAX485 but that does not affect the software side of things) at 250kbps for the rest of it, with a minimum reset-break of 88us (most libraries use more though, starting at about 100us) So not the strange HIGH - LOW timing that is common for ledstrips. I am willing to gift you some ledstrip and be involved in the enhancement, if only i can find a place where they still sell it. It seems like a simple enhancement, where all that is really needed is to convert 8 bytes into 11 bytes, which include the start & stop bits, and setting the transmission speed & break length.
https://en.wikipedia.org/wiki/DMX512 https://www.ledlightinghut.com/files/WS2821%20Datasheet.pdf
I can't even find an official spec on the WS2821. World Semi website doesn't even reference them at all.
I found these on alibaba. https://www.alibaba.com/product-detail/WS2821-led-pixel-panel_60724183923.html?spm=a2700.galleryofferlist.normal_offer.d_title.4c746839xBd8DK
Good find ! I did find a datasheet, though, i know they basically receive DMX and there is some kind of addressing function, though in the fixtures i have seen, the address is simply cascading. They are not cheap, but i guess for testing you'd only need a few. I ran into fixtures which contained these LEDs which were built several years ago, but where the limitation has now become apparent. They are slow, and there is a limit in addresses on the chain. In the end DMX is a lighting standard system, and that is what i would use it for. (other than obviously fixing setups that were built with DMX LED-strip) There is reliable transmission available for AVR's but on an ESP i have not managed. Actually a UART method is the most obvious of course, no complications, but the libraries that i have found for it have incomplete frames in combination with WiFi traffic and connection. DMA mode also should be easy enough, but within your code, i am pretty sure i'll mess it up. Anyway if you want some DMX-Led-dots.. Let me know.
@devarishi7 Just send me a donation (see top of the wiki) and I will order some for testing.
Done, i think it should do the trick. Keep me updated on the progress.
So howz the progress ?
I could not get the i2s method (DMA) to function correctly yet, I was going to look at just using the Uart to do the work (there are uart methods for WS2812 already).
The order for actual LEDs is a complete unknown. It just states in transit and can take months or just days.
Ah well let's hope they arrive quickly. I thought the DMA would be fairly straightforward, somehow creating a way to add the start and stop bits and set the speed. When i was looking at it, i got a little stuck on setting the speed, with all templates and all, it is not a programming style that i am familiar with. The adding the start and stop bits would appear similar to creating the neopixel bytes i guess. I have never tried you UART mode to be honest. i am willing to do some testing on it. At DMX speed.
Mmm, DMX512 is not the same as the WS2821. The differences are minor but interesting. DMX512: the first slot/channel is always zero data for lighting; with another 512 slots possibly sent after. Also, the data is least significant first bit order (0-7). WS2821: it omits the weird slot 0 and the data order most significant first (7-0).
I guess my question is, DMX512 or WS2821?
hehe.. Eh well i was not aware of a couple of things here. I know about the startcode. The LED strips i've found actually respond to DMX512 without issue, but it is possible that these are not WS2821's or that WS2821's do discard the startcode (i think it's that !) In any case, these DMX LED-strip are meant to be connected to a DMX512 system without extra interface, that is what made them popular for a while. No extra controllers.
About the reverse order of the data-bits, i was not aware of that, and i am not even sure that is the case anymore. I have seen it on the WIKI page as well, but nowhere in any library or DMX reception transmission system anywhere.
I know that the logic levels are inverted compared to normal Serial (eg Logic 'HIGH' == '1' & 'LOW' == '0') but since there is normally speaking a 2 wire input to a RS485 transceiver, this compensation can be done hardware wise really easily.
Now about the order of bits, i know this sketch works on an AtMega328p
`
volatile uint16_t dmxaddress = 1; volatile uint16_t i = 0; volatile uint8_t dmxreceived = 0; volatile uint16_t dmxcurrent = 0; volatile uint8_t dmxvalue[NUMBER_OF_CHANNELS]; uint8_t dmxoutput[DMX_OUTPUT_CHANNELS];
volatile uint8_t dmxnewvalue = 0; volatile uint8_t zerocounter = 0; volatile bool storeSerial = false;
void setup() { pinMode(PWM_LED_PIN, OUTPUT); // first dmxchannel LED value pinMode(DMX_PING, OUTPUT); //ping LED init_uart(); SetupTimerRegisters(); }
void loop() { ReceiveDMX(); Processing(); SendDMX(); }
void ReceiveDMX() { dmxnewvalue = 0; dmxcurrent = 0; zerocounter = 0; i = 0; UCSR0C = RECEIVE_FORMAT; //0x06; // 8N1 bitSet(UCSR0B, RXCIE0); // enable RX bitSet(TIMSK2, OCIE2A); while (dmxnewvalue != 1); }
void Processing() { // main processing static bool pin = true; pin = !pin; analogWrite(5, dmxvalue[0]); digitalWrite(13, pin); CopyValues(); }
void CopyValues() { for (uint8_t j = 0; j < 3; j++) { for (uint8_t k = 0; k < 9; k += 3) { dmxoutput[k + j] = dmxvalue[j + 3]; } } }
void SendDMX() { UCSR0C = BREAK_FORMAT; //0x06; // 8N1 UBRR0H = (UBBREAK >> 8); // set baud rate UBRR0L = (UBBREAK & 0xFF); // HL register uart_write(0); UCSR0C = TRANSMIT_FORMAT; //0x0E; // 8N2 UBRR0H = (UBDMX >> 8); // set baud rate UBRR0L = (UBDMX & 0xFF); // HL register uart_write(0); // start code uart_write_buffer(); }
void uart_write(char data) { UDR0 = data; while ((UCSR0A & 1 << TXC0) == 0); UCSR0A |= 1 << TXC0; }
void uart_write_buffer() { for (uint16_t j = 0; j < DMX_OUTPUT_CHANNELS; j++) { UDR0 = dmxoutput[j]; while ((UCSR0A & 1 << TXC0) == 0); UCSR0A |= 1 << TXC0; } }
void init_uart() { DDRD |= (1 << PORTD1); // set TX pin to output DDRD &= ~(1 << PORTD0); // set RX pin to input UCSR0A = 0x02; // 1<<U2X | 0<<MPCM; UCSR0B = 1 << RXCIE0 | 0 << TXCIE0 | 0 << UDRIE0 | 1 << RXEN0 | 1 << TXEN0 | 0 << UCSZ02; // Enable TX & RX, disable RX interrupt UCSR0C = RECEIVE_FORMAT; // 8N1 UBRR0H = (UBDMX >> 8); // set baud rate UBRR0L = (UBDMX & 0xFF); // HL register }
void SetupTimerRegisters() { // Sets up Timer2 to fire every 4us cli(); bitClear(TCCR2A, COM2A1); bitClear(TCCR2A, COM2A0); bitClear(TCCR2A, COM2B1); bitClear(TCCR2A, COM2B0); bitSet(TCCR2A, WGM21); bitClear(TCCR2A, WGM20); bitClear(TCCR2B, FOC2A); bitClear(TCCR2B, FOC2B); bitClear(TCCR2B, WGM22); bitClear(TCCR2B, CS22); bitClear(TCCR2B, CS21); bitSet(TCCR2B, CS20); OCR2A = 64; bitClear(TIMSK2, OCIE2B); bitSet(TIMSK2, OCIE2A); bitClear(TIMSK2, TOIE2); sei(); }
ISR(TIMER2_COMPA_vect) { if (bitRead(PIND, PIND0)) { // checks if the pin has gone HIGH zerocounter = 0; } else { zerocounter++; if (zerocounter == 20) // if 80us have passed 'Break' has been detected { bitClear(TIMSK2, OCIE2A); // disable Timer2 Interrupt storeSerial = true; } } } //end Timer2 ISR
ISR(USART_RX_vect) { / The receive buffer (UDR0) must be read during the reception ISR, or the ISR will just execute again immediately upon exiting. / dmxreceived = UDR0; if (storeSerial) { dmxcurrent++; //increment address counter starts at 0 // and skip the start code if (dmxcurrent > dmxaddress) { //check if the current address is the one we want. dmxvalue[i] = dmxreceived; i++; if ((i == NUMBER_OF_CHANNELS) || (dmxcurrent > MAX_DMX_CHANNELS + 1 )) { bitClear(UCSR0B, RXCIE0); storeSerial = false; dmxnewvalue = 1; //set newvalue, so that the main code can be executed. } } } } // end ISR ` And that the test LED on pin 5 Lights up correctly (active HIGH) and so i don't see any inverted order (unless there is something about the UART i don't know) So. The startcode (0), Yes ! For the rest DMX512 is Serial at 250kbps (inverted logic) and i did see that the WS2821's can go up to 750kbps, but that is optional, I don't think there is any inverted bit order. (unless the UART always does, but in that case i am confident that WS2821's would have them inverted as well) I can confirm the DMX strips functionality with an object that is at the entrance to a club here in Amsterdam if needed. nb CopyValues() is just a function to copy 1 input pixel into a few output pixels, confirming reception and transmission.
The LSB (reverse order of the bits) is something the UART does automatically, but not the i2s hardware that is used for the ESP8266 DMA methods.
Ok, well the LED strip 'claims' to be fully DMX512 compatible (at least the ones that are the target) If WS2821's don't have that, they would not claim that, but regardless of that, easiest would i guess be to just add the possibility for either way, like you do with the speed for WS2812's and even that for the inverted logic level and even the startcode. Anyway, DMX512 is very commonly used, the strips are rare.
Here is my current work on using the i2s (DMA). While it does send a data stream, and the general timing is correct, the output stream doesn't match the data in the i2s buffer. The break and first slot are malformed even when the bits in the buffer are correct. The refactored i2s (DMA) for WS2812x still works fine and these share that core code, so I am really confused as to why it doesn't work.
Test Sketch
#include <NeoPixelBus.h>
const uint16_t PixelCount = 10; // this example assumes at least 4 pixels, making it smaller will cause a failure
const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
const uint8_t DebugPin = 5;
// NeoEsp8266Dmx512Method
// NeoWs2812xMethod
typedef NeoPixelBus<NeoRgbFeature, NeoEsp8266Dmx512Method> NeoBus;
NeoBus* strip;
void setup() {
Serial.begin(115200);
while (!Serial); // wait for serial attach
Serial.println();
Serial.println("Initializing...");
Serial.flush();
strip = new NeoBus(PixelCount, PixelPin);
// this resets all the neopixels to an off state
strip->Begin();
strip->Show();
pinMode(DebugPin, OUTPUT);
digitalWrite(DebugPin, LOW);
Serial.println();
Serial.println("Running...");
}
const RgbColor cTest1(0b01000100, 0b10001000, 0b00000001);
void loop() {
delay(10000);
Serial.println("Colors ...");
strip->SetPixelColor(0, cTest1);
digitalWrite(DebugPin, HIGH);
strip->Show();
digitalWrite(DebugPin, LOW);
delay(10);
Serial.println("Off ...");
// turn off the pixels
strip->SetPixelColor(0, 0);
strip->SetPixelColor(1, 0);
strip->SetPixelColor(2, 0);
strip->SetPixelColor(3, 0);
strip->Show();
}
Hmm that is a bit disturbing. I assume that you tested it by simply replacing the method within the same sketch (i mean that it still works for WS2812)
If the data in the buffer is correct, i am stumped as well of course.
As for the conversion, The nibble lookup table is nice, it took me a bit to figure it out. I think i would have first added the start & stop bits first and then inverted (or not) but it is clearly not the issue.
I can't see from your oscilloscope what i am supposed to see, Is that the datastream for the first pixel as set in the sketch ? The startcode appears to be not correct. Maybe it becomes a bit more clear when i see a few results.
Also i think it may be better to increase the MAB to 12us, but that may have to come of the break time really. Actually shouldn't the whole break + MAB be a total of 160us (4 bytes) There is no issue in the break being to long.
I am just thinking out loud here, i don't know in what way the UART and the I2S stream interact.
Found the problem. The i2s requires 32bit values otherwise endianness of the bytes are a problem. I wrote the original so long ago I forgot this detail and code just did things inside to work with it. Due to this, I had to rework the encoding part completely but the new one works on byte boundaries of source data now.
Here is the logic capture for both normal (top) and inverted (bottom)
The branch mentioned above contains the changes if you would like to pull it down and give it a try. I will merge this in after a little more testing.
Ah perfect ! I am going to set up for testing over the weekend.
added WS2821 (3x faster, same protocol) and merged into master
v2.7.0
Sorry about the late response, but i ran into some issue testing, which is probably related to me using an older core for the esp (2.4.2) which is the least bloated (for flash, i am actually quite tight on flash use of the ESP-01's i am using) and functioning core, but that core throws me a lot of warnings and errors in combination with your latest version. Also just as a small note, NeoEsp8266Dmx512Method
has not been added to the keyword list
Ok i can see you are reading what i write. Now i got the thing upload properly, though i had to decrease my FS size to keep OTA working, but that is of later concern. Then i somehow had the wires on the XLR inverted, but once that was fixed, i kept having the inconsistent behaviour, basically it appeared as if either the address was shifting which would mean that maybe the break was not recognized correctly. I started out making sure i would send at least a full frame (increasing the number of pixels to 171, which didn't help, then i went into the SRC, to increase the breaktime, but to no avail, then i tried to increase ByteSendTimeUs , bu that didn't matter, and then doing the math i saw.
// 4.2 us bit send, 250Kbps
and i was under the impression that 250Kbps would make a bitlength of 4 us (not 4.2 us) I mean 1 / 250000 = 0.000004 (if i have the number of zeroes correctly) So with a bit of guesswork i modified
static const uint32_t I2sClockDivisor = 21; // 0-63
to
static const uint32_t I2sClockDivisor = 20; // 0-63
And that did the trick !
I will have to do some more testing in regards to how the whole program responds to wifi requests etc, but i am not expecting any issues. Also i will have to move all the new code into the older version, since i do want my FS to be 128KB, and ESPcore 3.0.2 just won't fit and have OTA updates, but i think i've got it sorted.
Thanx a ton !
Was this for DM512 or ws2821?
This was for DMX512. I also changed the ByteSendTimeUs to 44us (11 * 4uS) Of course i am not actually using WS2821's , but am actually receiving DMX on a UART, but regardless it should be 250Kbps, which is 4uS per bit, and increasing to 4.2us like you have done is beyond the 3.5% tolerance of the UART i am using. to receive But that really does work as expected, and the great thing about I2S is that it has no disturbance from the wifi the way a UART mode tends to on an ESP. (don't know about your UART method, but all others i've tested create a broken frame at times particularly when connecting to it as an Access point) Anther question i have is (well i can find out through testing i guess as well) Is I2S mode affected by Serial.swap() ? In other words can i receive on UART0 on the alternate pins while using GPIO3 as an I2S output ?
with regards to the WS2821SpeedBase i actually recommend setting
I2sClockDivisor = 27
I2sBaseClockDivisor = 8
whoich results in a bit length of 1.35us resulting in 740740bps which is a lot closer to the 750Kbps that the datasheets suggests. ByuteSentTimeUs can be reduced to 15 in that case.
So about the 'other question' i had, the documentation wasn't quite clear about it. But testing has confirmed that the UART0 swapped RX pin can be used without issues as long as
Serial.begin(); Serial.swap()
get called before
NeoPixelBus::begin()
Since RX0 is actually the only available RX on almost any ESP unit (although the swap pin isn't exposed on the ESP-01) it might be good to update the documentation. (now i am wondering if i should open a separate issue for this. !? )
@devarishi7 You are asking questions like this is a discussion area, it is not, issues are for tracking bugs. Further, with topics that are not what the issue is about. Please use the appropriate forum, like the discussion area or gitter channel.
https://github.com/Makuna/NeoPixelBus/issues/78 and https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods.
But maybe a complete FAQ on the topic is needed.
I checked the SRC, and my correction from August 2nd has not been implemented. 250Kbps = 4.0us per bit (not 4.2us) etc. The way it is now it will not work for the standard DMX512 format.
with regards to the WS2821SpeedBase i actually recommend setting
I2sClockDivisor = 27 I2sBaseClockDivisor = 8
whoich results in a bit length of 1.35us resulting in 740740bps which is a lot closer to the 750Kbps that the datasheets suggests. ByuteSentTimeUs can be reduced to 15 in that case.
This comment was missed. Checking the DMX512 E1.11 timing update, the pulse needs to be within a very narrow range. Description Min Typical Max Unit Bit Rate 245 250 255 kbit / s Bit Time 3.92 4 4.08 μs
Yes and i tested it with 4.0us (250Kbps) and that works perfectly, and the current 4.2us setting doesn't really. For now i have been giving the correction when i refer to it for new users. I don't have a way of testing the WS2821SpeedBase unfortunately.
https://github.com/Makuna/NeoPixelBus/pull/636
I also found a bug that caused the WS2821 to output incorrect signal. I will put a new release with these fixes within the week as I may have introduced other bugs with other changes 8-/
https://github.com/Makuna/NeoPixelBus/pull/642
Continue to find more bugs where break was incorrectly sized for WS2821 due to improper assumptions of speed and bit size.
This does affect the DMX512 just a little and would appreciate a confirmation with these changes. It should allow a slightly less wait between shows.
Oh eh, well i'm on holidays at the moment for 6 weeks, and i didn't bring all required devices, but as long as the break for DMX512 is at least 88us all is good and any length up to 140us i have never had any issues (conceptinetics.h uses 136us and that's fine)
v.2.7.3
Now i am also using ESP32, and i was wondering if / hoping that you plan to add / adapt the current working method for the ESP8266 into the ESP32 I2S & I2Sx methods ? I think i might be able to manage myself but i can not do better than you i am sure.
Now i am also using ESP32, and i was wondering if / hoping that you plan to add / adapt the current working method for the ESP8266 into the ESP32 I2S & I2Sx methods ? I think i might be able to manage myself but i can not do better than you i am sure.
Make a formal request in a new conversation or issue and reference this one.
dose it support dmx512 for ic like ws2821 and other ic like that?