Understanding DP1903 timing (WS2811 variant)

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1. I am writing code for interfacing DP1903 with MCU. MCU is run by 16Mhz internal oscillator.
As per DP1903 datasheet;
TIH = 2us & T1L = 0.5us  +-150ns
T0H = 0.5us & T0L = 2us  +-150ns
Treset >= 24us

 

2. Data-sheet: http://www.depuw.com/Public/imag...
Page 4 & 5 specify timings.

 

3. What is purpose of mentioning 800Khz & 400Khz speed? How does I have to account this is in code?
Data-sheet specify timings as already written in point 1, so I need to write code according to that, right?
So how does this 800Khz comes in between? What does it signify?

 

4. Suppose I have to send a zero & then a reset pulse at some given point.
So timing will be T0H, T0L & Treset, i.e
   a. Pin high for 0.5us
   b. Pin low for 2.0us
   c. Pin low for 24us

Do after step b, I have to make high & then low again? As in page4, on T0L completion bit again goes to high? Or it is for representation only, I can combine step b & c & keep pin low for 24+2 = 26us?

 

5. Attached is my code. I saw some problem sometimes when I run the code. Code is run on full speed optimization i.e O3,
mainly problem occurs when I turn on all lights blue, The lights do not go all blue, but some whitish color appears.

 

6. I have 100 led connected. Also noticed if I make 24us delay, color don't appear correctly at all, with 50us there is some problem, increasing further delay don't have any effect.  Why is that so?

 

7. For 0.5us, 8 nops are used, while for 2us, 32 nops are used.

 

int main(void)  
{
    LED_pin_output_low();

    while(1)
    {
        ws2811_reset_us(50);
        for(led_cnt = 0U ; led_cnt < 100U ; led_cnt++)
        {  
            ws2811_rgb_write(0xff, 0x00, 0x00);
        }
        delay_sec(2);
        
        ws2811_reset_us(50);
        for(led_cnt = 0U ; led_cnt < 100U ; led_cnt++)
        {  
            ws2811_rgb_write(0x00, 0xff, 0x00);
        }
        delay_sec(2);
        
        ws2811_reset_us(50);
        for(led_cnt = 0U ; led_cnt < 100U ; led_cnt++)
        {  
            ws2811_rgb_write(0x00, 0x00, 0xff);
        }        
        delay_sec(2);
        
    }
        
 
} /* function ends here */  



static void ws2811_rgb_write(uint8_t red, uint8_t green , uint8_t blue)  
{
    uint8_t red_arr[8];
    uint8_t green_arr[8];
    uint8_t blue_arr[8];
  
    uint8_t cnt;
    uint8_t idx;

/* store the bits values of RGB in a array */    
    idx = 0x80U;
    for(cnt = 0U; cnt < 8U; cnt++)
    {
        if(red & idx)
        {
            red_arr[cnt] = 1U;
        }  
        else
        {
            red_arr[cnt] = 0U;
        }  

        if(green & idx)
        {
            green_arr[cnt] = 1U;
        }  
        else
        {
            green_arr[cnt] = 0U;
        }  
        
        if(blue & idx)
        {
            blue_arr[cnt] = 1U;
        }  
        else
        {
            blue_arr[cnt] = 0U;
        }          
        
        idx = idx >> 1U;
    }  
    
/* send pixels as fast as possible */ 
/* red pixel */    
    if(red_arr[0]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(red_arr[1]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(red_arr[2]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(red_arr[3]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(red_arr[4]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(red_arr[5]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(red_arr[6]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }      
    if(red_arr[7]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  

/* green pixel */  
    if(green_arr[0]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(green_arr[1]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(green_arr[2]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(green_arr[3]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(green_arr[4]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(green_arr[5]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(green_arr[6]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }      
    if(green_arr[7]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); } 

/* blue pixel */  
    if(blue_arr[0]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(blue_arr[1]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(blue_arr[2]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(blue_arr[3]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(blue_arr[4]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(blue_arr[5]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }  
    if(blue_arr[6]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }      
    if(blue_arr[7]) { ws2811_bit_set(); }  else { ws2811_bit_reset(); }
    
} /* function ends here */  



static inline void ws2811_bit_set(void)  
{
    LED_PIN_ON();
    
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    
    LED_PIN_OFF();

    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
        
}



static inline void ws2811_bit_reset(void)  
{
    LED_PIN_ON();
    
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    
    LED_PIN_OFF();

    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    __no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();__no_operation();
    
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you tried one of many WS2811 drivers in existence to see if it just works?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Which AVR has an internal 16MHz oscillator? A quick Google will find the extensive amount of information written about these leds.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which AVR has an internal 16MHz oscillator?

Xmegas? But we can't say for sure.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Vindhyachal Takniki wrote:
2. Data-sheet: http://www.depuw.com/Public/imag...

Do you have an English vrsion of that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Which AVR has an internal 16MHz oscillator?

 

It's cross-posted on the TI MSP430 forum: https://e2e.ti.com/support/micro... - so quite possibly not even AVR at all!

 

EDIT

 

But, then, it is here under 'General Electronics' - not a specific AVR forum.

 

Last Edited: Mon. Aug 21, 2017 - 09:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you using interrupts anywhere in the code?

If so, then you have to disable them during shifting.

 

Also, +/-150ns timing is quite narrow. Compiler settings / optimisation / code inlining / etch become quite important

Stuff like this is probably best done in assembly (which would make it independent on compiler settings / future proof.).

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

  I don't believe that you will be able to use C language to run the DP1903 if that IC has the same timing as the WS2811 [NeoPixel] IC.  The microSecond timing needed is too critical. 

 

  I suggest downloading the AdaFruit library for the WS2811 [NeoPixel] IC.   This source code (for C++) has assembly language in-line routines embedded in the code that allows working easily with this programmable LED IC.  It is precisely coded for an AVR using a 16MHz system clock.  I was able to transfer the in-line assembly code from this Adafruit NeoPixel library to an 8MHz Tiny45 AVR and get the LEDs lighted, but it was a lot of work even with 10 years of AVR assembler background.

 

There are different variations of the WS2811 IC.  One works at 400KHz and the other at 800KHz.  Probably the DP1903 has only one version, mostly likely 800KHz.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
  I don't believe that you will be able to use C ... The microSecond timing needed is too critical. 

In particular, the tolerance on those microsecond timings:

Paulvdh wrote:
 +/-150ns timing is quite narrow ... Stuff like this is probably best done in assembly

 

Howver, AIUI, the critical part is just the bit timings;  the reset timing is non-critical - so long as it's longer than the 24us minimum:

 

 

So you can do whatever you like between the bursts.

 

In that respect, it looks like 1-WireTM

 

 

 

Paulvdh wrote:
Are you using interrupts anywhere in the code?

If so, then you have to disable them during shifting.

Would apply whether you use 'C' or assembler.

 

But where has the OP gone ... ?

 

frown

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
quite possibly not even AVR at all!

Maybe still the STM8http://www.avrfreaks.net/comment...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
But where has the OP gone ... ?

(s)he seems to be making a habit of posting the same thing to multiple forums, and then ignoring them all:

 

http://www.avrfreaks.net/comment...

 

http://www.avrfreaks.net/comment...

 

http://www.avrfreaks.net/comment...

 

frown

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

315 post here, pity if he gets banned!!

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have no interuupts at all.

In C code I have reduced 32nops to 24nops 

& 8 nops to 4 nops.

 

There is slight imprvement in code but still sometimes it misbehaves like on certain led glow it start flashing

I think main problem will be here as in OP, if someone help to understand

 

4. Suppose I have to send a zero & then a reset pulse at some given point.
So timing will be T0H, T0L & Treset, i.e
   a. Pin high for 0.5us
   b. Pin low for 2.0us
   c. Pin low for 24us

Do after step b, I have to make high & then low again? As in page4, on T0L completion bit again goes to high? Or it is for representation only, I can combine step b & c & keep pin low for 24+2 = 26us?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Vindhyachal Takniki wrote:
Do after step b, I have to make high & then low again?

No.

 

it is for representation only

Yes.

 

I can combine step b & c & keep pin low for 24+2 = 26us?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look at this post: http://www.avrfreaks.net/comment... - and follow the link.

 

That took me to: http://www.avrfreaks.net/comment... - "Each bit is encoded as a pulse"

 

And: http://www.avrfreaks.net/comment... - addresses the misleading rising edges shown at the ends of the sequences shown in the datasheet.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1. One mistake was T1H, T1L,T0H,T0L needs to half at 800khz, I was not doing it. Actually DP1903 data sheet was in Chinese.

2. It can be operated to 400Khz & 800khz. What does these frequency define? I dont understand. 
When already all the timings are defined, then what does 800khz defines?

3. Still i have certain problem, most of time code is working fine, but sometimes there is flickering.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Vindhyachal Takniki wrote:
2. It can be operated to 400Khz (sic?) & 800khz (sic?). What does these frequency define? I dont understand.

Read the datasheet carefully - does it actually say that?

 

Does it actually talk about frequencies?

 

I can't read the Chinese version, but the WorldSemi WS2811 datasheet says:

 

 

https://cdn-shop.adafruit.com/da...

 

That says bps -  bits per second - not kHz.

 

So it's talking about the (effective) communication speed.

 

Clearly, there is a "fast" mode and a "slow" mode - and "fast" is twice the speed of "slow".

 

When already all the timings are defined, then what does 800khz (sic) defines?

The timings show how the individual bits on the line are formed.

 

The 800kbps tells you the effective data transfer rate that is achieved with those timings.

 

It's like saying that, for a UART at 9600 baud, each individual bit time is 104us.

 

EDIT

 

clarify UART

 

 

Last Edited: Sat. Aug 26, 2017 - 09:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Vindhyachal Takniki wrote:
most of time code is working fine, but sometimes there is flickering.

Probably means that your code is marginal: so, most of the time, it only just works; but some of the time it goes over the limit and does not work properly.

 

You are going to have to use an oscilloscope or logic analyser or similar to see exactly what timings your code is actually giving ...

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i have ordered a new string. This one had some issues with original controller also. Will check.