Long HL1606 strip to the Arduino Uno

Hi There,

Is it right that the Arduino Uno with the "HL1606 LED strip library" only can run 255 LED's ?

I have 2 x 5 meters LED strip, and i want to control alle 320 LED's in one long strip.

Hope for your reply, and for a solution on this problem.

Best Regards BamM

Yes - look at the code, the number of LEDs is a byte sized variable.

Create your own version of the library where this is an int variable perhaps? You've got the source so you can modify it...

Hi MarkT

I have found one place in the HL1606strip.cpp where there stand:

HL1606strip::HL1606strip(int dPin, int latchPin, int clkPin, uint8_t numLEDs)
{
_dPin = dPin;
_sPin = 255;
_latchPin = latchPin;
_clkPin = clkPin;
_faderEnabled = 0;

But changing from 255 to 320, makes no difference. :roll_eyes:

No, forget sPin, change numLEDs and _numLEDs in both the .cpp and .h files to int rather than uint8_t. Setting sPin to 255 means "there is no sPin", since 255 is not a valid pin number. Its the limit to the size of the led array caused by numLEDs being bytesized that's hitting you.

Oh, now i get it…

Now i have changed uint8_t n to int.
Now the first 255 LED’s act like they are supposed to, but from the 256th LED to the 320th there is just some random color. Why this?

Post the changes you've made - you didn't forget _numLEDs ? You went through the code checking that anything using the value of numLEDs or _numLEDs is wide enough?

Here is the code:

/*

  • LEDStrip - Arduino driver for HL1606-based LED strips
  • Thanks to: John M Cohn
  • Copyright (c) 2009, Synoptic Labs
  • All rights reserved.

#ifndef HL1606strip_h
#define HL1606strip_h

#include <inttypes.h>

enum {
OFF, // 0b00
ON, // 0b01
UP, // 0b10
DOWN, // 0b11
NONCMD
};

#define LATCH (_BV(7))
#define SPEED2X (_BV(6))

// colors, each bit one LED
#define BLACK 0b000
#define WHITE 0b111
#define RED 0b100
#define YELLOW 0b110
#define GREEN 0b010
#define TEAL 0b011
#define BLUE 0b001
#define VIOLET 0b101

class HL1606strip
{
private:
uint8_t _dPin;
uint8_t _sPin;
uint8_t _latchPin;
uint8_t _clkPin;
uint8_t _faderEnabled;
unsigned int _faderPulseHalfWidth;
unsigned int _faderPulseNewHalfWidth;
unsigned long _faderPulseNextEdge;

// we will control up to 255 LEDs!
int *_leds;
int _numLEDs;
public:

HL1606strip(int, int, int, int, int);
HL1606strip(int, int, int, int);

// some higher level commands we added
void setLEDcolor(uint8_t n, uint8_t color);
uint8_t getLEDcolor(uint8_t n);
void writeStrip(void);
int numLEDs(void);

uint8_t rgbPush(uint8_t, uint8_t, uint8_t);
uint8_t rgbPush2X(uint8_t, uint8_t, uint8_t);
void pushCmd(uint8_t);
void blankPush();
void latch();
void sleep();
void wakeup();
void faderSpeedSet(unsigned int);
unsigned int faderSpeedGet();
void faderCrank();
void sPulse();
};

#endif

// A basic HL1606 LED strip library, a little simpler to use than the core LEDStrip lib
// this library is a slow, & synchronous
/*

  • LEDStrip - Arduino driver for HL1606-based LED strips
  • Thanks to: John M Cohn
  • Copyright (c) 2009, Synoptic Labs
  • All rights reserved.

#if ARDUINO >= 100
#include “Arduino.h”
#else
#include “WProgram.h”
#include “avr/io.h”
#include “wiring.h”
#endif
#include “HL1606strip.h”

HL1606strip::HL1606strip(int dPin, int latchPin, int clkPin, int numLEDs)
{
_dPin = dPin;
_sPin = 255;
_latchPin = latchPin;
_clkPin = clkPin;
_faderEnabled = 0;

// how many in the string
_numLEDs = numLEDs;
_leds = (int *)malloc(numLEDs);

for (int i=0; i<numLEDs; i++) {
setLEDcolor(i, BLACK);
}

digitalWrite(_dPin, LOW);
pinMode(_dPin, OUTPUT);
digitalWrite(_sPin, LOW);
pinMode(_sPin, OUTPUT);
digitalWrite(_latchPin, LOW);
pinMode(_latchPin, OUTPUT);
digitalWrite(_clkPin, LOW);
pinMode(_clkPin, OUTPUT);
}

HL1606strip::HL1606strip(int dPin, int sPin, int latchPin, int clkPin, int numLEDs)
{
_dPin = dPin;
_sPin = sPin;
_latchPin = latchPin;
_clkPin = clkPin;
_faderEnabled = 0;

// how many in the string
_numLEDs = numLEDs;
_leds = (int *)malloc(numLEDs);

for (int i=0; i<numLEDs; i++) {
setLEDcolor(i, BLACK);
}

digitalWrite(_dPin, LOW);
pinMode(_dPin, OUTPUT);
digitalWrite(_sPin, LOW);
pinMode(_sPin, OUTPUT);
digitalWrite(_latchPin, LOW);
pinMode(_latchPin, OUTPUT);
digitalWrite(_clkPin, LOW);
pinMode(_clkPin, OUTPUT);
}

void HL1606strip::sleep()
{
digitalWrite(_dPin, LOW);
pinMode(_dPin, INPUT);
digitalWrite(_sPin, LOW);
pinMode(_sPin, INPUT);
digitalWrite(_latchPin, LOW);
pinMode(_latchPin, INPUT);
digitalWrite(_clkPin, LOW);
pinMode(_clkPin, INPUT);
}

void HL1606strip::wakeup()
{
digitalWrite(_dPin, LOW);
pinMode(_dPin, OUTPUT);
digitalWrite(_sPin, LOW);
pinMode(_sPin, OUTPUT);
digitalWrite(_latchPin, LOW);
pinMode(_latchPin, OUTPUT);
digitalWrite(_clkPin, LOW);
pinMode(_clkPin, OUTPUT);
}

void HL1606strip::faderCrank()
{
unsigned long mymillis;

if (!_faderEnabled) return;

mymillis = millis();

// Give us 250ms slop in case we don’t exactly catch our edge.
if (mymillis >= _faderPulseNextEdge && mymillis < _faderPulseNextEdge + 250) {
if (digitalRead(_sPin) == HIGH) {
digitalWrite(_sPin, LOW);
} else {
// only load new value of _faderPulseHalfWidth on rising edge
digitalWrite(_sPin, HIGH);
_faderPulseHalfWidth = _faderPulseNewHalfWidth;
}

_faderPulseNextEdge = mymillis + _faderPulseHalfWidth;
}
}

unsigned int HL1606strip::faderSpeedGet()
{
return _faderPulseHalfWidth;
}

void HL1606strip::faderSpeedSet(unsigned int halfWidthms)
{
if (halfWidthms == 0) {
_faderEnabled = 0;
_faderPulseHalfWidth = 0;
_faderPulseNewHalfWidth = 0;
digitalWrite(_sPin, LOW);
return;
}

_faderPulseNewHalfWidth = halfWidthms;

// if we’re already running, don’t re-init _faderPulseNextEdge
if (_faderEnabled != 1) { // starting from non-running state,
_faderEnabled = 1;

digitalWrite(_sPin, HIGH);
_faderPulseHalfWidth = halfWidthms;
_faderPulseNextEdge = millis() + _faderPulseHalfWidth;
}
}

/* The HL1606 drives 2 RGB LED’s. Each 3-color LED is controlled with a command

  • word consisting of 8 bits. Command word is clocked out MSB first (i.e. D8
  • is first bit sent)
  • Format of command word (using conventions in datasheet):

  • | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 |


  • | LED1 CMD | LED2 CMD | LED3 CMD | 2X | LatchOK |

  • LED{1,2,3} CMD -
  • 00 - LED off
  • 01 - LED on (max bright)
  • 10 - LED fade up (start at min bright)
  • 11 - LED fade down (start at max bright)
  • 2X - Double fade speed
  • 0 - 1X fade speed, each pulse on SI line steps brightness by 1/128th.
  • 1 - 2X fade speed, each pulse on SI line steps brightness by 1/64th.
  • LatchOK - Enable latch. Set to 0 to insert ‘white space’ in the serial
  • chain. If set to 0, the entire CMD is ignored.
  • 0 - Do not latch this CMD when Latch is thrown.
  • 1 - Latch CMD as normal when Latch is thrown.

*/

// Push a color value down the strip, setting the latch-enable //flag.
uint8_t HL1606strip::rgbPush(uint8_t redcmd, uint8_t greencmd, uint8_t bluecmd)
{
uint8_t cmd = 0;
uint8_t flags = LATCH;

if (redcmd >= NONCMD || bluecmd >= NONCMD || greencmd >= NONCMD) return 0;

cmd |= (greencmd << 4) & (_BV(5) | _BV(4));
cmd |= (redcmd << 2) & (_BV(3) | _BV(2));
cmd |= (bluecmd) & (_BV(1) | _BV(0));
cmd |= flags & (_BV(6) | _BV(7));

pushCmd(cmd);

return cmd;
}

uint8_t HL1606strip::rgbPush2X(uint8_t redcmd, uint8_t greencmd, uint8_t bluecmd)
{
uint8_t cmd = 0;
uint8_t flags = LATCH | SPEED2X;

if (redcmd >= NONCMD || bluecmd >= NONCMD || greencmd >= NONCMD) return 0;

cmd |= (greencmd << 4) & (_BV(5) | _BV(4));
cmd |= (redcmd << 2) & (_BV(3) | _BV(2));
cmd |= (bluecmd) & (_BV(1) | _BV(0));
cmd |= flags & (_BV(6) | _BV(7));

pushCmd(cmd);

return cmd;
}

void HL1606strip::sPulse()
{
if (digitalRead(_sPin) == HIGH) {
//delay(1);
digitalWrite(_sPin, LOW);
delayMicroseconds(1000);
digitalWrite(_sPin, HIGH);
delayMicroseconds(1000);
} else {
//delay(1);
digitalWrite(_sPin, HIGH);
delayMicroseconds(1000);
digitalWrite(_sPin, LOW);
delayMicroseconds(1000);
}

}

// Push a blank value down the strip, not setting latch-enable flag.
// Does not affect the status of a particular LED when latched. It’s
// like using whitespace.
void HL1606strip::blankPush()
{
pushCmd(0);
}

void HL1606strip::pushCmd(uint8_t cmd)
{
//shiftOut(_dPin, _clkPin, MSBFIRST, cmd); // doesnt work on teensy?
for (int i=0; i<8; i++) {
if (cmd & _BV(7-i)) {
digitalWrite(_dPin, HIGH);
} else {
digitalWrite(_dPin, LOW);
}
digitalWrite(_clkPin, HIGH);

digitalWrite(_clkPin, LOW);

}
}

void HL1606strip::latch()
{
digitalWrite(_latchPin, HIGH);
delayMicroseconds(1); // spec sheet specifies minimum latch pulse of 1us
digitalWrite(_latchPin, LOW);
}

/* high level commands */

// this takes about 20ms for a 160 LED strip
void HL1606strip::writeStrip(void) {
for (int i=0; i<_numLEDs; i++) {
pushCmd(_leds[_numLEDs-1-i]);
}
latch();
}

uint8_t HL1606strip::getLEDcolor(uint8_t n) {
int x;

if (n > _numLEDs) return 0;

x = _leds[n];

x &= 0x7F; // get rid of latch

uint8_t r, g, b;
r = g = b = 0;
if (x & 0x3) { b = 1; }
if (x & 0xC) { r = 1; }
if (x & 0x30) { g = 1; }

return (g << 1) | (r << 2) | b;
}

void HL1606strip::setLEDcolor(uint8_t n, uint8_t color) {
int x;

x = 0x80; // latch

if (n > _numLEDs) return;

if (color & BLUE)
x |= 0x01;
if (color & RED)
x |= 0x04;
if (color & GREEN)
x |= 0x10;

_leds[n] = x;
}

int HL1606strip::numLEDs(void) {
return _numLEDs;
}

I presume its working now then? Pretty pictures perhaps?

[You should edit the above and change quote tags to code tags ideally ;)]