Pages: [1]   Go Down
Author Topic: LPD8806 RGB LED strip support  (Read 3800 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I have been running various LED strip projects based on the LPD8806 chipset.
Is anyone trying to port the libraries for the LPD8806 chipsets to the Due ?

I'm looking forward to participating in testing any good trial

Thanks,
Rudy
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bump.

I have a similar problem.  I'm getting compile errors when trying to verify the LEDbeltKit example.  I'm doing
this in Arduino 1.5.1r2.  Any ideas on what header file needs updating?

Thanks,
Jon



C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp: In member function 'void LPD8806::updatePins(uint8_t, uint8_t)':
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:62: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:64: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp: In member function 'void LPD8806::startSPI()':
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:84: error: 'SPI_CLOCK_DIV8' was not declared in this scope
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:89: error: 'SPDR' was not declared in this scope
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp: In member function 'void LPD8806::show()':
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:129: error: 'SPSR' was not declared in this scope
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:129: error: 'SPIF' was not declared in this scope
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:130: error: 'SPDR' was not declared in this scope
Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 23
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The library seems to use AVR specific registers to drive SPI.
Someone should made a porting of the library to SAM3X CPU, or convert the lib to use SPI library bundled in Arduino IDE.

Can you post a link to the library code(just to give it a look)?
Logged

C.

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
The library I'm using is the one from Adafruit posted on github on https://github.com/adafruit/LPD8806

KR,
Rudy
Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 23
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I see,

open LPD8806.cpp and change this (line 89):

Code:
  SPDR = 0; // 'Prime' the SPI bus with initial latch (no wait)

with:
Code:
  SPI.transfer(0x00);

and replace this (line 128):

Code:
    for (i=0; i<n3; i++ ) {
      while(!(SPSR & (1<<SPIF))); // Wait for prior byte out
      SPDR = pixels[i]; // Issue new byte
    }

with this:

Code:
    for (i=0; i<n3; i++ ) {
      SPI.transfer(pixels[i]);
    }

and tell me how it goes.
Logged

C.

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, that helped to clear a bunch of my errors.  I still have a few more.  I'm not sure if the type RwReg and uint8_t are the
same, and also the SPI_CLOCK_DIV8 doesn't seem to be declared, and I'm not sure what value it should be.

Thanks,
Jon

C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp: In member function 'void LPD8806::updatePins(uint8_t, uint8_t)':
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:62: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:64: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp: In member function 'void LPD8806::startSPI()':
C:\Users\Jon\Downloads\arduino\arduino-1.5.1r2\libraries\LPD8806_master\LPD8806.cpp:84: error: 'SPI_CLOCK_DIV8' was not declared in this scope
Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 23
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeah,

with SPI_CLOCK_DIV8 you get a 2Mhz SPI clock from an Atmega328 running at 16Mhz, since the Due runs at 84Mhz you need 42 to obtain the same clock. So replace SPI_CLOCK_DIV8 with 42.

About the registers try to change the declaration volatile uint8_t* to volatileuint32_t*.

Logged

C.

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I have the same problème than Rudyv
I follow what you said Cmaglie and numbers of errors has decreased !
But I still have errors smiley-sad :

LPD8806.cpp: In member function 'void LPD8806::updatePins(uint32_t, uint32_t)':
LPD8806.cpp:58: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
LPD8806.cpp:60: error: cannot convert 'volatile RwReg*' to 'volatile uint8_t*' in assignment
LPD8806.cpp: In member function 'void LPD8806::startSPI()':
LPD8806.cpp:85: error: 'SPDR' was not declared in this scope
LPD8806.cpp: In member function 'void LPD8806::show()':
LPD8806.cpp:125: error: 'SPSR' was not declared in this scope
LPD8806.cpp:125: error: 'SPIF' was not declared in this scope
LPD8806.cpp:126: error: 'SPDR' was not declared in this scope

Have you other ideas in order to solve that ?

Thank you for all
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I made some progress and tried today to re-use an LPD8806 library from mbed, as it is ARM based I tried to see if I can get it to work.

Unfortunately it gives me some compiling issues. I'll insert the program and the used 8806.h and 8806.ccp files.
Can someone have a look and let me know how we can get this working ?


The 8806.h file is
Code:
// Arduino Due library for LPD8806 led strip, borrowed from MBED.


// Mbed library to control LPD8806-based RGB LED Strips
// (c) 2011 Jelmer Tiete
// This library is ported from the Arduino implementation of Adafruit Industries
// found at: http://github.com/adafruit/LPD8806
// and their strips: http://www.adafruit.com/products/306
// Released under the MIT License: http://mbed.org/license/mit
//
// standard connected to 1st hardware SPI
// LPD8806  <> MBED
// DATA     -> P5
// CLOCK    -> p7
/*****************************************************************************/
#if (ARDUINO >= 100)
 #include <Arduino.h>
#else
 #include <WProgram.h>
#endif


#define HARDWARE_SPI 1
#ifndef LPD8806_H
#define LPD8806_H

class LPD8806 {

 public:

  LPD8806(uint16_t n);
  void
    begin(void),
    show(void),
    setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
    setPixelColor(uint16_t n, uint32_t c);
  uint16_t
    numPixels(void);
  uint32_t
    Color(uint8_t, uint8_t, uint8_t);

 private:

  uint8_t
    *pixels;     // Holds LED color values
  uint16_t
    numLEDs;     // Number of RGB LEDs in strand
    
  void
    writezeros(uint16_t n);
};
#endif

The 8806.ccp file is the following

Code:
//Library for Arduino Due LPD8806
//taken from MBEd as it is ARM based
//
//
//Mbed library to control LPD8806-based RGB LED Strips
// (c) 2011 Jelmer Tiete
// This library is ported from the Arduino implementation of Adafruit Industries
// found at: http://github.com/adafruit/LPD8806
// and their strips: http://www.adafruit.com/products/306
// Released under the MIT License: http://mbed.org/license/mit
//

/*****************************************************************************/

#include "LPD8806.h"
#include <SPI.h>

//here something goes wrong
SPIClass SPI = SPIClass( SPI_MODE0 );

SPI.begin();
//SPI spi(p11, p12, p13); // mosi, miso, sclk

LPD8806::LPD8806(uint16_t n) {
    // Allocate 3 bytes per pixel:
    if (NULL != (pixels = (uint8_t *)malloc(numLEDs * 3))) {
        memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state
        numLEDs     = n;
    }
}

void LPD8806::begin(void) {

    // Setup the spi for 8 bit data, low steady state clock,
    // first edge capture, with a 2MHz clock rate
    //spi.format(8,0);
    //spi.frequency(2000000);
    SPI.setClockDivider(21);

    // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs)
    writezeros(3 * ((numLEDs + 63) / 64));
}

uint16_t LPD8806::numPixels(void) {
    return numLEDs;
}

void LPD8806::writezeros(uint16_t n) {
    while (n--) SPI.transfer(0x00);
}

// This is how data is pushed to the strip.  Unfortunately, the company
// that makes the chip didnt release the  protocol document or you need
// to sign an NDA or something stupid like that, but we reverse engineered
// this from a strip controller and it seems to work very nicely!
void LPD8806::show(void) {
    uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED

    for (i=0; i<nl3; i++ ) {
        SPI.transfer(pixels[i]);
    }

    // Write latch at end of data; latch length varies with number of LEDs
    writezeros(3 * ((numLEDs + 63) / 64));

    // We need to have a delay here, a few ms seems to do the job
    // shorter may be OK as well - need to experiment :(
// wait_ms(3);
}

// Convert R,G,B to combined 32-bit color
uint32_t LPD8806::Color(uint8_t r, uint8_t g, uint8_t b) {
    // Take the lowest 7 bits of each value and append them end to end
    // We have the top bit set high (its a 'parity-like' bit in the protocol
    // and must be set!)
    return 0x808080 | ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
}

// store the rgb component in our array
void LPD8806::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed

    pixels[n*3  ] = g | 0x80;
    pixels[n*3+1] = r | 0x80;
    pixels[n*3+2] = b | 0x80;
}

void LPD8806::setPixelColor(uint16_t n, uint32_t c) {
    if (n >= numLEDs) return; // '>=' because arrays are 0-indexed

    pixels[n*3  ] = (c >> 16) | 0x80;
    pixels[n*3+1] = (c >>  8) | 0x80;
    pixels[n*3+2] =  c        | 0x80;
}

The error I get when compiling is the following:

Quote
C:\Users\Rudy\Program Files\arduino-1.5\libraries\LPD8806\LPD8806.cpp:19: error: no matching function for call to 'SPIClass::SPIClass(int)'
C:\Users\Rudy\Program Files\arduino-1.5\hardware\arduino\sam\libraries\SPI/SPI.h:29: note: candidates are: SPIClass::SPIClass(Spi*, uint32_t, void (*)())
C:\Users\Rudy\Program Files\arduino-1.5\hardware\arduino\sam\libraries\SPI/SPI.h:27: note:                 SPIClass::SPIClass(const SPIClass&)
C:\Users\Rudy\Program Files\arduino-1.5\libraries\LPD8806\LPD8806.cpp:21: error: expected constructor, destructor, or type conversion before '.' token

Who can help me out ?
KR,
Rudy

* strandtest.pde (3.92 KB - downloaded 16 times.)
Logged

Forum Administrator
Milano, Italy
Offline Offline
Sr. Member
*****
Karma: 23
Posts: 292
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Try to comment out

Code:
SPIClass SPI = SPIClass( SPI_MODE0 );

The SPI object in Arduino is pre-instantiated.
(and remember to #include <SPI.h> in your sketch, I didn't checked)
Logged

C.

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I have put #include <SPI.h> in my sketch and in the lpd8806.ccp file.
I commented out the code you asked
Code:
//SPIClass SPI = SPIClass( SPI_MODE0 );

Then i get the following error when i compile:

Quote
C:\Users\Rudy\Program Files\arduino-1.5\libraries\LPD8806\LPD8806.cpp:21: error: expected constructor, destructor, or type conversion before '.' token

What should I try next ?
KR, Rudy
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
Adafruit has updated their library for the lpd8806 led strip and it works. So my issue is solved.
Thanks for those who helped me in finding a solution.
https://github.com/adafruit/LPD8806

Kr, Rudy
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello, this thread was the closest i could find relating to my problem..

im working with the LPD8806 RGB Led strip. It has 44 LED's

my script uploads, the wiring is good, ran all the troubleshooters from adafruit here http://learn.adafruit.com/digital-led-strip/troubleshooting and still only the first two LED's follow the script.  The others light up in random colours, dim or remain off. The script i use is from the 8806 library, strandtest and longstrandtest.

i've doublechecked everything more than twice and dont know whats wrong.. Anyone that can help me?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

nevermind the strip was defect for some reason...
Logged

Pages: [1]   Go Up
Jump to: