Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

SPI, Netduino, and RGB LED Strip


  • Please log in to reply
63 replies to this topic

#1 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 15 October 2011 - 09:20 PM

Thanks to all your help and a little elbow grease, I finally have my Netduino Mini set up properly and interfacing with my RGB LED Strip (see here for more info).

I am using SPI to write to the strip, and I've noticed some inconsistent behavior, and I think I might be writing to the device too quickly. Sometimes, when I run my program, only the last addressed LED in the chain will change color, while the others remain white. Sometimes, I can see all the LEDs change color, but only for a flash, before returning to white. Each LED receives a 24 bit RGB value (where MSB is red), which it pushes down to its neighbor. I've tried instituting a delay from anywhere between 500 microseconds to 2 seconds, and the effect seems the same. The value for white is 0x00FFFFFF (all bits set), but I am not setting that color right now.

I've attached my source so you can see everything that I am doing, but here are the snippets that I think are of most interest:

Init function, where I set up SPI (don't mind the clock pin input into the function...I am eliminating that)
public void Init(int numOfLEDs, Cpu.Pin clockPin)
        {
            NumOfLEDs = numOfLEDs;

            // Create a new SPI device
            _data = new SPI(new SPI.Configuration(
                Pins.GPIO_PIN_13,          //Set to Default SS pin (13 on Netduino Mini)      
                false,                  // SS active-low (irrelevant)
                0,                      // No SS setup time(irrelevant)
                0,                      // No SS hold time(irrelevant)
                false,                  // Clock low on idle (so it will be low for 500µs after transmission, which triggers the output of the leds)
                true,                  // Data valid on rising edge
                2000,                   // 2MHz clock rate (allows for 500µs between writes)
                SPI.SPI_module.SPI1     // SPI device 1
                )
            );/**/
            postData();
        }

The postData function:
private void postData()
        {
            //Each LED requires 24 bits of data 
            //MSB: R7, R6, R5..., G7, G6..., B7, B6... B0  
            //Once the 24 bits have been delivered, the IC immediately relays these bits to its neighbor 
            //Pulling the clock low for 500us or more causes the IC to post the data. 

            for (int LED_number = 0; LED_number < _LEDS.Length; LED_number++)
            {
                int this_led_color = _LEDS[LED_number]; //24 bits of color data 

                byte[] data = IntToBytes(this_led_color);
                //Debug.Print("Byte[0]=" + data[0] + ", Byte[1]=" + data[1] + ", Byte[2]=" + data[2] + ", Byte[3]=" + data[3]);
                Debug.Print("Byte[0]=" + data[0] + ", Byte[1]=" + data[1] + ", Byte[2]=" + data[2]);
                _data.Write(data);
                //DelayMicroSec(2000000);
                
            }
        }

Thanks for your help and time! :)

#2 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 16 October 2011 - 04:06 AM

Hello again. On Netduino, the SPI itself is very fast, but the delay between one "Write" and another one is very long. So long that the natural delay itself could act as "start" for the led strip. So, you should try another way. Instead of writing each led independently, set up the whole buffer for N led, then write it all at once. Cheers
Biggest fault of Netduino? It runs by electricity.

#3 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 16 October 2011 - 06:59 AM

Hello again Mario. :) I gave that a shot and that seemed to improve the situation...a little. What seems to be happening now is that the colors seem to shift out of order...sometimes the first two of 6 might be white, the last red, etc. The shift is definitely out of order from what I have written. I think maybe I need to institute a delay between writes?

#4 Stefan W.

Stefan W.

    Advanced Member

  • Members
  • PipPipPip
  • 153 posts

Posted 16 October 2011 - 10:49 AM

Is the error "random"? Have you tried reducing the clock rate (on a phone right now so I can't look at the datasheet for timing info)?
I believe that no discovery of fact, however trivial, can be wholly useless to the race, and that no trumpeting of falsehood, however virtuous in intent, can be anything but vicious.
-- H.L. Mencken, "What I Believe"

#5 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 16 October 2011 - 06:57 PM

The error was seemingly random until I reduced the clock rate to 2khz (I simply converted the 500 microsecond delay to a frequency that would match it). What happens now is that the LED strip flashes the proper color (for less than a second!) before going back to white (it stays white most of the time). Originally, I would write each 24 bit value at a time, as the color value is pushed down the strip per write, but then I took Mario's suggestion of gathering all the bits into a buffer and writing at once, which seems to have helped. White is 0xFFFFFF I believe, so I wonder where that value could be coming from so frequently. :unsure:

#6 Stefan W.

Stefan W.

    Advanced Member

  • Members
  • PipPipPip
  • 153 posts

Posted 16 October 2011 - 09:20 PM

The 500 microsecond delay is supposed to happen after you sent the data, it's unrelated to the frequency (except that it means that you can't use a frequency <= 1khz because then it has 500 µs lows during data transfer). 0xFF means "all bits high", so my random guess is that means that you have some noise/other data on the clock line and your data line is high ... is there anything else connected to the clock pin?
I believe that no discovery of fact, however trivial, can be wholly useless to the race, and that no trumpeting of falsehood, however virtuous in intent, can be anything but vicious.
-- H.L. Mencken, "What I Believe"

#7 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 16 October 2011 - 09:36 PM

The only thing connected to the clock pin is the clock line on the strip. I will double check the connection just to be sure. Since I am not sending anything out on that pin, maybe I should just disconnect it?

#8 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 17 October 2011 - 03:35 AM

Disregard what I said earlier. This is what I had read about the LEDs. I think it will help, but I am posting in case someone gets to the answer faster than I can... Gray Scale Data Word Format and Timing CLK pin keeps low more than 500uS will make the WS2801 internal status register reset, and at this moment, the gray scale data in the data shift registers will be latched. Now WS2801 is ready for gray scale data transport. When the WS2801 receives total 24 clock rising edges, the WS2801 enters relay mode, which relays the input signal got from CKI and SDI with very low distortion (100pS typical) and very low delay time ( 8 ns typical). The data format and the timing diagram can be seen in Fig 11. The gray scale data frame is comprised of 3 gray data words, each data word is composed of 8 gray scale data bits, total 24 bits. The 8bit gray data can easily realize the linear 256 LED gray levels control. During data transfer, the first bit is the data frame signal, then is the MSB of the ROUT channel, the last one transferred into the data shift register is the LSB of the BOUT channel.

#9 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 17 October 2011 - 03:57 AM

Re-hello again!
So, let's review the checklist:
- I assume that the head of the strip (i.e. the wiring to the Netduino) is over 20cm long (overall), thus I wouldn't set the SPI frequency above some MegaHertz. Let's say 1MHz.
- If the strip has N chips = N leds, then your byte array to be sent is 3*N bytes long.
- Your code consist only in a Write, without any break during the transfer.
Is it that all right?

One more detail. I remember some experience about the SPI on Netduino, and when you are exchanging a relatively long stream of bytes, the GC can break the transfer for a while. This is much easier as the stream gets longer, for obvious statistical considerations.
It means that when the GC delays the data exchange, the pause could be seen as a "reset" by the led strip.

I'd try the follows:
  • write a test code avoiding (wherever possible) objects that will be garbaged, so use pinned instances, readonly's, etc.
  • perform the test over a small number of leds, so that the byte-array is short enough (e.g. 2-3 frames).
Cheers
Biggest fault of Netduino? It runs by electricity.

#10 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 17 October 2011 - 04:12 AM

Forget: there is still an open problem about the min threshold for the "high" level, that is 4V.
This could be an issue, and the unexpected behavior could derive from the improper working point of the chips.

To solve this trouble, you should use (for example) a 74HC14, that is a 6-inverting HCMOS gates with Schmitt-trigger input.
Basically, you may power this chip at +5V, while you will drive it by the nominal levels offered by the Netduino.
Since this chip embeds 6-inverters, you should use two-pairs (4 gates in total) to act as "level-shifter".
Cheers
Biggest fault of Netduino? It runs by electricity.

#11 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 17 October 2011 - 04:21 AM

Hello again Mario! :) I am not so sure if that min threshold plays a role. The strip is powered separately by an adapter, with the data pin on the strip connected to SPI MOSI, while the clock pin is connected to SPCK on the chip. I fell back to bit banging on AD0 and AD1, and while I get a more predictable result, it looks like as soon as the color appears, it disappears, becoming white again. I've read in another thread that the Netduino may be sending signals too fast, but that is in the case for one LED. And to answer your checklist: 1) Yes, the strip is longer than 20 cm (it is 1m in length) and I had dropped the frequency down to 2khz. 2) My byte array (when using SPI) was 3 * sizeof(byte) * _LEDS.Length. 3) Yes, there were only writes. The SPI object has a WriteRead, but the other methods are irrelevant. Unless, you are talking about other operations that occur between writes?

#12 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 17 October 2011 - 04:32 AM

1) the whole strip doesn't mind how long is. The important length is from the Netduino to the very first WS2801. Hereinafter, every segment from/to adjacent WS2801's is independent. However, I wouldn't drop the frequency so low, because the timing is comparable to the reset delay. This may cause confusion over confusion. Feel free to use the bitbang, if you think it's better, although I guess the native SPI would be the best way. 2) Excellent. 3) OK, although a WriteRead has no sense, since you won't read any data incoming. The code running in the Netduino is managed, thus there is the GC clean-up taking place sometime. This happens anytime, without any ability to know when, how long, etc. I've seen that it takes place during a SPI transfer, which is a low-level process. For "high-level" tasks, such a managed code routine, the behavior is much more evident. To minimize the GC task, you should write your code as there's no object to be garbaged. Everything keeps alive forever, thus the GC returns immediately. No breaks during any process.
Biggest fault of Netduino? It runs by electricity.

#13 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 17 October 2011 - 04:52 AM

The power of the strip has no meaning. The problem is that the WS2801 requires at least 4V to detect a logic "one", and the Netduino isn't able to reach such a voltage. You may do a workaround, even without having any level shifter (as the 74HC14). Just keep using the bitbang, but modify the circuit as follows: - connect a pull-up resistor (1-2KOhms) to +5V, to both the clock and data wires. Then, modify the code so that: - to output a logic "zero" the pin should be configured as OUTPUT and LOW; - to output a logic "one" the pin should be configured as INPUT without pullup; Those for both clock and data. I must go for breakfast, maybe I'll back in a couple of hours. Cheers
Biggest fault of Netduino? It runs by electricity.

#14 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 17 October 2011 - 05:00 AM

Mario, thank you again for your help. Enjoy your breakfast!

If it is of any interest to you, I have a logic level converter that does 3.3V to 5V and back. It's info can be seen here.

With this, this is what I am thinking: I am thinking of routing SPI MOSI to TX1 on the low voltage side, then routing RX1 on the high voltage side to the SDI side.

I am going to start a separate thread on the details of what I intend to do. Thanks!

#15 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 17 October 2011 - 05:33 AM

The level converter fits perfectly. However, about the MOSI is correct to wire it to TX1, but you must do the same thing with SCLK to TX2. Your circuit uses only two outputs coming from Netduino: why do you need the RX? Please, also note that such a converter is made by pull-up resistors, thus its speed won't be so much. At this point I'd try to get the SPI rate even slower than 1MHz, try to set at 100KHz. Cheers
Biggest fault of Netduino? It runs by electricity.

#16 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 17 October 2011 - 05:59 AM

I had included the RX as the output to the strip, so it would go SPI_MOSI->LV (Low Voltage) TX1, RX1 HV->SDI. That's what I meant, and yes, there'd just be two inputs from the Netduino, and the corresponding outputs (RXs) will go to the strip. However, in doing this, I will have to do some rewiring (saving it for tomorrow...almost 11PM here). Mind, the converter requires power from both high voltage and low voltage source. This is what I am thinking of now on that: 1) Disconnect input power for Netduino from USB FTDI cable. 2) Connect power to Netduino with 9V battery (Positive to pin 24, negative to Pin 23) 3) Since VIN is providing power, pin 21 will provide a +5V output. Connect this pin to HV power input on logic level converter, and pin 4 (the other GND on Netduino) to GND on the HV logic level converter. So, that takes care of the higher voltage input. What I don't understand now is where I am going to get the lower voltage on the system. I have a 3.7V battery, but that's greater than the 3.3V outputted on the MOSI and SPCK on the Netduino. Bye for now!

#17 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 17 October 2011 - 07:08 AM

So, do you have a Netduino Mini model? If not, the +5V power is available also when the USB is connected. I don't see any reason to power the Netduino with a battery, although is fully doable. I don't understand your consideration about the 3.7V battery. Where do you use it?
Biggest fault of Netduino? It runs by electricity.

#18 iukpo

iukpo

    Advanced Member

  • Members
  • PipPipPip
  • 85 posts

Posted 17 October 2011 - 07:16 AM

Yes, I do have a Netduino Mini. I only brought up the batteries (9V for Netduino, 3.7 for Logic Level Converter) because the Logic Level converter requires two power sources: one from the higher voltage, the other from the lower voltage. If I power the Mini with the 9V, I can get a 5V output on Pin 21, thus taking care of the higher voltage power source. I need a power source for the lower voltages, which is the 3.3V outputs. Unless, maybe, I could use one of the pins on the Netduino (slave select pin?) to provide that lower voltage power?

#19 Stefan W.

Stefan W.

    Advanced Member

  • Members
  • PipPipPip
  • 153 posts

Posted 17 October 2011 - 01:46 PM

Using a netduino pin as the 3.3V supply is hacky, but could work (output port, logic level high) - however make sure that you don't draw too much current from it (you don't if you just use it for this level converter). A "clean" solution would involve another regulator like http://www.sparkfun.com/products/526 (make sure you read the datasheet and add the caps if you do that).
I believe that no discovery of fact, however trivial, can be wholly useless to the race, and that no trumpeting of falsehood, however virtuous in intent, can be anything but vicious.
-- H.L. Mencken, "What I Believe"

#20 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 17 October 2011 - 03:05 PM

Now I understand! The Mini does not provide a 3V3 output! Also, Stefan is right. Since the level converter does not require much current, everything should work. Cheers
Biggest fault of Netduino? It runs by electricity.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.