Library for ShiftBrite

I made a library for the neat ShiftBrite ShiftBrite RGB LED Module | macetech.com. It's a 10bit (billions of colors!) RGB led color mixing doodad. It's heavily based on his example code (infact, a bunch of it is copy and pasted), but now I've wrapped it up into an easy to use library! Questions, comments, etc welcome. I'd certainly like to hear what people think of the approach, what a better approach might be, other ideas, etc.

I've got the complete library in a zip file, but I don't know where to upload it.

Without further ado, the header file:

#ifndef ShiftBrite_h
#define ShiftBrite_h

#define SB_Ver 1.0

#ifndef Wiring_h
#include "wiring.h"
#endif


class ShiftBrite
{
  private:
      int datapin; //pins the ShiftBrite is connected to
      int latchpin;
      int enablepin;
      int clockpin;
      
      void initPins(); //sets up pins modes, etc.
      void sendPacket(int mode, int r, int g, int b);
  
 public:
    ShiftBrite(int dp, int lp, int ep, int cp);
      ShiftBrite(int cp);
      
      void setPower(int r, int g, int b);
      void setPower(int p);
      
      void setColor(int r, int g, int b);
};

#endif

The cpp:

//Matt G.
//onion@doorcreekorchard.com
//July 2008

#include "ShiftBrite.h"


//====Public
//==Constructors
ShiftBrite::ShiftBrite(int dp, int lp, int ep, int cp)
{
      datapin=dp;
      latchpin=lp;
      enablepin=ep;
      clockpin=cp;
      initPins();
}


ShiftBrite::ShiftBrite(int cp)
{
      clockpin=cp;
      enablepin=cp+1;
      latchpin=cp+2;
      datapin=cp+3;
      initPins();
}

//==
void ShiftBrite::setPower(int r, int g, int b)
{
      sendPacket(B01,r,g,b); //B01 sets the mode to write to the current registers
}

void ShiftBrite::setPower(int p)
{
      sendPacket(B01,p,p,p);
}

void ShiftBrite::setColor(int r, int g, int b)
{
      sendPacket(B00,r,g,b); //B00 sets the mode to write to the PWM registers
}

//============


//====Private
void ShiftBrite::initPins()
{
      pinMode(datapin, OUTPUT);
      pinMode(latchpin, OUTPUT);
      pinMode(enablepin, OUTPUT);
      pinMode(clockpin, OUTPUT);
      digitalWrite(latchpin, LOW);
      digitalWrite(enablepin, LOW);
}

void ShiftBrite::sendPacket(int mode, int r, int g, int b) 
{
      unsigned long SB_CommandPacket;
      
      SB_CommandPacket = mode & B11;
      SB_CommandPacket = (SB_CommandPacket << 10)  | (b & 1023);
      SB_CommandPacket = (SB_CommandPacket << 10)  | (r & 1023);
      SB_CommandPacket = (SB_CommandPacket << 10)  | (g & 1023);
      
      shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 24);
      shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 16);
      shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket >> 8);
      shiftOut(datapin, clockpin, MSBFIRST, SB_CommandPacket);
      
      delay(1); // adjustment may be necessary depending on chain length
      digitalWrite(latchpin,HIGH); // latch data into registers
      delay(5); // adjustment may be necessary depending on chain length
      digitalWrite(latchpin,LOW);
}

The keywords.txt:

#######################################
# Syntax Coloring Map For ShiftBrite
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

ShiftBrite      KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

setPower      KEYWORD2
setColor      KEYWORD2

#######################################
# Instances (KEYWORD2)
#######################################


#######################################
# Constants (LITERAL1)
#######################################

Example code:

#include "ShiftBrite.h"

ShiftBrite SB(10); //A ShiftBrite starting on pin 10, assumes the next pins are sequentially going up

void setup() {
  pinMode(9,OUTPUT);
  digitalWrite(9,HIGH); //this is un UGLY HACK to supply +5 on pin 9 
                    //so the SB can be directly hooked on the the arduino.  
                    //This will probably burn out your arduino and cause the end of days.  
                    //Find a better way of supply power to the SBs
  SB.setPower(127); //Full power captin!
}


//This examples has three ShiftBrites chained together in series, and cycles some colours through them
void loop() {
  SB.setColor(1023,0,0); // SB #3 (since the data gets pushed through the SBs, the last one is set first
  SB.setColor(0,1023,0); // SB #2
  SB.setColor(0,0,1023); // SB #1
  delay(500);
  SB.setColor(0,1023,0); 
  SB.setColor(0,0,1023);
  SB.setColor(1023,0,0);
  delay(500);
  SB.setColor(0,0,1023); 
  SB.setColor(1023,0,0);
  SB.setColor(0,1023,0);
  delay(500);
}

Ok, I've made a new version of the ShiftBright with the following improvements/additions:

  1. It now uses a much higher performance shiftOut function and other speed ups (courtesy of MartinFick and mem). Hopefully this improves the usability and decreases visual lag when having long chains of ShiftBrites linked together.
  2. You can now use 5bit values to specify colors, either as individual RGB channels, or as all three channels packed into a 16 bit int (discards the most significant bit, as only 15 bits are used). 5 bit values are set via a lookup table. The included LUT is a very simple 2 point linear table (first 26 entries are 0-400, remaining are 400-1023). It's also the same for each channel. I'm not sure how to make a more accurate LUT, so that's what I went with. It's pretty easy to replace my LUT with whatever you want though.

I have it as a zip file, and would rather upload that then making a post for every file. Is there a place in the wiki or elsewhere I can upload it?

I have it as a zip file, and would rather upload that then making a post for every file. Is there a place in the wiki or elsewhere I can upload it?

If you want, you can put it in the arduino playground. Read about how to do this here: Arduino Playground - Participate
Have a look at some of the other contributions there for ideas on style and layout for the write-up

I've added some stuff to the playground before, but I couldn't figure out how to upload files to it. Is there something I'm missing?

Info on how to upload files into the wiki is here: PmWiki | PmWiki / Uploads

I think you may also find there is some arduino playground specific help on uploading files somewhere in the playground

Thanks! Made the wiki entry and the library is now uploaded!

edit: almost forgot to include a link to it: Arduino Playground - ShiftBriteLib

Hi chippey, is your lib able to controll a chain of SB? i mean set different color for each SB.
I see your example but i don't understand how sendPacket can work for SB chain.

From A6281 spec

After all of the data is written to each A6281 in the chain, the
data is latched into each A6281 via a low-to-high transition on
the LI pin.

but for what i can understand you move the latch pin each 32bit

Ciao

Alessandro,

You are correct in that I move the latch every 32bits. You don't need to when writing to a chain of ShiftBrites, but as far as I can tell, it doesn't seem to hurt (except for a slight decrease in speed when writing the data out to the shiftbrites). You can write to multiple shiftbrites in a chain with consecutive calls to setColor. (Some of the example sketches do this).

I am planning on better ways to write to a chain of shiftbrites for future versions of the library, just haven't gotten to it yet.

Hope that answer helps!

Cheers!

A latch pulse for every 32 bit is actually a good thing, for the configuration word only. If noise gets into the data lines somehow, it is possible to accidentally activate the A6281 "test bits" which the datasheet doesn't explain except for "don't use these." One effect of activating a test bit is the shift register stops passing data to the next device. If this happens, you have to write the configuration registers before the device will pass data again. That means if you try to update the array with one latch per cycle, it'll take one refresh period times the number of shiftbrites to reset the whole chain. With a latch for each device, it should only take the time required to send to each shiftbrite once.

If you do this with the actual brightness control registers, you will latch the previous LED's data each time...if the LEDs had very different colors, you would see the pattern sliding along the chain.

So I would say for configuration registers, you should latch each time (assuming all the configuration registers are identical). And for the brightness control registers, you should latch once the data for the entire chain has been shifted through.

chippey & macegr thanks for reply, i'm very happy to have understand correctly the code, i'm in pretty new in "written" code because i'm a labview programmer where everithings is a drawing :wink:
I'll try to modify the lib too simply creating a new sendpacket funcion whitout the latch bit and a new macro for color a chain that call it

chippey, I tried the library in 0012 and it's not working. I get the "expected unqualified-id before 'int'" etc. I played with it a while, looking through these forums, but was not able to get it working. Any ideas?

macegr--

Many older libraries fail with that message in 0012 because of a some macros at the top of the new wiring.h which make it difficult to co-exist with stdlib.h in a library. If you remove or comment out the lines (in wiring.h)

#define int(x)...
down to
#define boolean(x)

and also
#define round(x)
and
#define abs(x)

this may improve things.

Mikal

mikalhart, that did the trick. I had already tried commenting out everything except the round()! :-?

Thanks!

@macegr

Yeah, I got that same error too. I found a fix(es) though. 0012 somehow doesn't like the include of wiring.h (even though it looks like wiring.h should be able to handle it), and also doesn't like uint16_t in the 5bit luts, so I changed that too.

I'll post a zip file soon with the changes after I clean things up a bit. I'm also toying with a new version of the library to handle long chains of ShiftBrites more effectively and in a more sensible way. Still trying to figure out what that more sensible way is though, and how best to do it ::slight_smile:

edit: Heh, just saw mikalhart's reply. Looks like there's more than one solution. Off to tweak more code! :smiley:

Any progress on this?

Hello I to would like to check on the progress of this. I also am having problems getting the library to work. I keep getting the Wprogram.h error and i am to much of a newbie to fix it. any help would be appreciated

I have found that adding the following sequence immediately after the last #include <libraryname.n> line in your sketch resolves the Arduino 0012 library incompatibility problem in most cases. (If it doesn't, let me know what the error message is.)

#undef int
#undef char
#undef long
#undef byte
#undef abs
#undef float
#undef round

Mikal