RGBpixel

From Noisebridge
Jump to navigation Jump to search

Addressable RGB LED "pixels" from Cool Neon

Wiring[edit]

  • RED - +5v
  • GREEN - Data
  • YELLOW - Clock
  • BLUE - Ground

CoolNeonRGBpixelWires.jpeg

Code[edit]

Simple Test[edit]

/*
Developed by: thex (noisebridge)
Updated: 20131122
Revised: 20140829 (evil dan)
https://noisebridge.net/wiki/RGBpixel
*/

// Arduino UNO Default wiring, Yellow to Pin 13 & Green to Pin 11

#include <SPI.h>

int waitTime = 100;
byte maxPower = 0x33;

int offset = 0;

/*
color         hex       r    g    b    deg
==========================================
RED         #FF0000    255,   0, 0      0
ORANGE      #FF7F00    255, 127, 0      30
YELLOW      #FFFF00    255, 255, 0      60
CHARTREUSE  #7FFF00    127, 255, 0      90
GREEN       #00FF00      0, 255, 0      120
SPRING      #00FF7F      0, 255, 127    150
CYAN        #00FFFF      0, 255, 255    180
AZURE       #007FFF      0, 127, 255    210
BLUE        #0000FF      0,   0, 255    240
VIOLET      #7F00FF    127,   0, 255    270
MAGENTA     #FF00FF    255,   0, 255    300
ROSE        #FF007F    255,   0, 127    330
*/

void setup() 
{
  // Set the SPI parameters
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  
  sendEmptyFrame();
}

void loop()
{
  for (int o = 0; o < offset; o++)
    sendColor(maxPower, maxPower, maxPower);
    
  offset++;
  if (offset > 25)
    offset = 0;
    
  for (int i = 0; i < 2; i++)
  {
    // RED
    sendColor(maxPower,0x00,0x00);
    // ORANGE
    sendColor(maxPower, maxPower>>1, 0x00);
    // YELLOW
    sendColor(maxPower, maxPower, 0x00);
    // CHARTREUSE
    sendColor(maxPower>>1, maxPower, 0x00);
    // GREEN
    sendColor(0x00,maxPower,0x00);
    // SPRING
    sendColor(0x00, maxPower, maxPower>>1);
    // CYAN
    sendColor(0x00, maxPower, maxPower);
    // AZURE
    sendColor(0x00, maxPower>>1, maxPower);
    // BLUE
    sendColor(0x00,0x00,maxPower);
    // VIOLOET
    sendColor(maxPower>>1, 0x00, maxPower);
    // MAGENTA
    sendColor(maxPower, 0x00, maxPower);
    // ROSE
    sendColor(maxPower, 0x00, maxPower>>1);
  }
  sendEmptyFrame();
  
  delay(waitTime);
}


// Extrapolated functions from TCL Library

void sendFrame(byte flag, byte red, byte green, byte blue)
{
  SPI.transfer(flag);
  SPI.transfer(blue);
  SPI.transfer(green);
  SPI.transfer(red);
}

void sendColor(byte red, byte green, byte blue)
 {
  byte flag;

  flag = makeFlag(red,green,blue);

  sendFrame(flag,red,green,blue);
}

void sendEmptyFrame()
{
  sendFrame(0x00, 0x00, 0x00, 0x00);
}

byte makeFlag(byte red, byte green, byte blue) 
{
  byte flag = 0;

  flag = (red&0xC0)>>6;
  flag |= ((green&0xC0)>>4);
  flag |= ((blue&0xC0)>>2);
  return ~flag;
}


Evil Dan Edition [EXPERIMENTAL][edit]

/*
EvilDan of moisebridge
*/

#include <SPI.h>

struct lenvec
{
  int len;
  unsigned long *vals;  
};

const int updateDelay = 200;
const unsigned long MAX_COUNT = 0xffffffff;
const int PIXEL_COUNT = 25;
const int COLOR_COUNT = 255;    // changed to constant (+hex)
byte colors[COLOR_COUNT][3];   // added color table for all pixels (+hex)

void sendAll(void (*f)(void));
void sendPackedRGB(unsigned long);
void sendRed(void);
void sendYellow(void);
void sendBlue(void);
void sendGreen(void);
void sendOff(void);
void sendOn(void);
void sendGreen(void);
void sendVector(unsigned long *, int);
void sendByteAsRYBG(byte);

void loop()
{  
  static unsigned long count = 0;
  
  // sendPrimes();

  // sendLongAsRYBG(nextPrime());
  // countRYBG(16);
  /***
  sendLongAsRYBG(count);
  count += 1;
  if( count >= MAX_COUNT )
  {
    count = 0;
  }
  ***/
  // pissRainbeau();
  // sendMagicVals();
  sendLongAsRYBG(getLongFromSerial());
  delay(updateDelay);
}

void setup()
{
  setColorPixelTable();
  initSerialAndSPI();
  sendAll(sendOff);  
  sendFlair();
  sendAll(sendOff);
  delay(500);
}

void initSerialAndSPI()
{
  Serial.begin(9600);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  sendSPIEndFrame();
}

void sendFlair()
{
  int flashcount = 11;
  int flashrate = 100; // times per second
  int millisec = int(1000 / flashrate);
  for( int i = 0; i < flashcount; i++)
  {
    int pause = i * millisec;
    sendAll(sendRed);
    delay(pause);
    sendAll(sendYellow);
    delay(pause);
    sendAll(sendBlue);
    delay(pause);
    sendAll(sendGreen);
    delay(pause);
  }
}

void sendPackedRGB(unsigned long p)
{
     byte r, g, b;
     r = byte((p >> 16) & 0xff);
     g = byte((p >> 8) & 0xff);
     b = byte(p & 0xff);
     sendSPI(r, g, b);
}

unsigned long packRGB(byte red, byte green, byte blue)
{
  unsigned long rgb;
  rgb = (red * 65536) + (green * 256) + blue;
  // rgb = (red << 16) | (green << 8) | blue;
  return rgb;
}

void sendVector(unsigned long v[], int len)
{
  for (int i = 0; i < len; i++)
  {
     sendPackedRGB(v[i]);
  }
  sendSPIEndFrame();

/***
  delay(150);
  sendAll(sendOff);
  delay(20);
***/
}

void sendPixel(int i, unsigned long p)
{
  static unsigned long vals[PIXEL_COUNT];
  
  if( i >= PIXEL_COUNT )
    return;
  
  vals[i] = p;
  sendVector(vals, PIXEL_COUNT);
  sendSPIEndFrame();
}

unsigned long * getRYBGVector()
{
  static int init = 1;
  static unsigned long v[PIXEL_COUNT];
  
  if( init)
  {

    for(int i = 0; i < (PIXEL_COUNT - 4); i+=4)
    {
      v[i] = packRGB(127, 0, 0);  // red
      v[i+1] = packRGB(127, 127, 0);  // yellow
      v[i+2] = packRGB(0, 0, 127);  // blue
      v[i+3] = packRGB(0, 127, 0);  // green
    }
    init = 0;
  }
  return v;
}

void setColorPixelTable()
{
  for (int i = 0; i < COLOR_COUNT; i++)
  {
   colors[i][0] = (i%2) ? byte(i*10) : 0x00;
   colors[i][1] = (i%2) ? 0x00 : byte(i*10);
   colors[i][2] = 0x00;
  } 
}

void pissRainbeau()
{
    static unsigned long count = 0;
    byte r, g, b;
    
    for (int i = COLOR_COUNT; i > 0; i--)
    {
       setColorDataFromTable((count + i) % COLOR_COUNT);
    }
    sendSPIEndFrame();
    
    while (count >= COLOR_COUNT) count -= COLOR_COUNT;
    
    Serial.println(String(count++));
}

void sendSPIEndFrame()
{
  for (int i = 0; i < 4; i++)
    SPI.transfer(0x00);
}

void setColorDataFromTable(int i)
{
  sendSPI(byte(colors[i][0]), byte(colors[i][1]), byte(colors[i][2]));
}

byte makeFlag(byte red, byte green, byte blue) 
{
  byte flag = 0;

  flag = (red&0xC0)>>6;
  flag |= ((green&0xC0)>>4);
  flag |= ((blue&0xC0)>>2);
  return ~flag;
}

void sendSPI(byte r, byte g, byte b)
{
  SPI.transfer(makeFlag(r, g, b));
  SPI.transfer(b); // Blue
  SPI.transfer(g); // Green
  SPI.transfer(r); // Red
}

void sendAll(void (*f)(void))
{
  for (int i = 0; i < PIXEL_COUNT; i++)
  {
     f();
  }
  sendSPIEndFrame();
}

void sendAllOff()
{
  sendAll(sendOff);
}

void sendOff(void)
{
  sendSPI(0, 0, 0);
}

void sendRed(void)
{
  sendSPI(127, 0, 0);
}

void sendYellow(void)
{
  sendSPI(127, 127, 0);
}

void sendBlue(void)
{
  sendSPI(0, 0, 127);
}

void sendGreen(void)
{
  sendSPI(0, 127, 0);
}

void sendByteAsRYBG(byte val)
{
  static unsigned long ret[4] = {0, 0, 0, 0};
  sendVector(byte2RYBGVector(val), 4); 
}

void sendLongAsRYBG(unsigned long val)
{
  sendVector(long2RYBGVector(val), 16); 
}

unsigned long * long2RYBGVector(unsigned long val)
{
  static unsigned long ret[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  for( int i = 0; i < 16; i++)
  {
    ret[i] = RYBGColor(byte(val & 0x00000003));
    val >>= 2;
  }
  return ret;
}

unsigned long * byte2RYBGVector(byte val)
{
  static unsigned long ret[4];
  for( int i = 0; i < 4; i++ )
  {
     ret[i] = RYBGColor(byte(val & 0x03));
     val >>= 2;
  }
  return ret;
}

unsigned long RYBGColor(byte val)
{
  static unsigned long RYBG[] = {
    packRGB(127, 0, 0),    // red
    packRGB(127, 127, 0),  // yellow
    packRGB(0, 0, 127),    // blue
    packRGB(0, 127, 0)     // green
  };
  return RYBG[val % 4]; 
}

unsigned long nextPrime()
{
  static unsigned long n = 0;
  unsigned long i = 3;
  
  if( n < 3 )
  {
    if( n == 0 )
    {
      n = 2;
    } else if( n == 2 ) {
      n = 3;
    }
    // n = 2 ? n < 3 : 3;
    return n;
  }
  
  n += 2;
  for( ; ; )
  {
    if ( i * i > n )  // no divisor found - current n is prime
    {
      break;
    }
    if( n % i == 0)
    {
      i = 3;
      // if( MAX_COUNT - 2 < n )
      if( 100 < n )
      {
        n = 2;
        break;
      }
      n += 2;
    } else {
      i += 2;
    }
  }
  return(n);
}

void sendPrimes()
{
  static unsigned long primes[] = {
    2, 3, 5, 7, 11, 13, 17, 19,
    23, 29, 31, 37, 41, 43, 47, 53,
    59, 61, 67, 71, 73, 79, 83, 89,
    91, 97, 0};
  unsigned long *p = primes;
  while( *p )
  {
    sendByteAsRYBG(byte(*p % 256));
    p++; 
  }
}

void countRYBG(byte count)
{
  for( int i = 0; i < count; i++ )
  {
    sendByteAsRYBG( byte(i % 256) );
    delay(updateDelay);
  }
}

void sendMagicVals()
{
  struct lenvec lv = GetMagicVals();
  sendVector(lv.vals, lv.len);
}

struct lenvec GetMagicVals()
{
   struct lenvec lv;
   lv.vals = getRYBGVector();
   lv.len = PIXEL_COUNT;
   return lv;
}

unsigned long getLongFromSerial()
{
  unsigned long ret;
  byte num_read;
  char input_str[256];
  char term = '\n';

  while( Serial.available() <= 0 )
  {
    delay(updateDelay);
  }

  num_read = Serial.readBytesUntil(term, input_str, 256);
  input_str[num_read] = 0;
  ret = strtoul(input_str, NULL, 10);
  Serial.println(String(ret));

  return ret;
}

Links[edit]