Neopixels and Color Sensor

I am designing a lighting rig that will light sculptural paintings from two points, one of each side. The idea is to have a Parallax ColorPAL scan colored objects that the viewer chooses and then send the data to the two points. So scan A will go to Point A and Scan B will go to Point B. For now I will have the selected colors be cast until new inputs are made. I imagine this working like a teeter totter. This is the initial end goal. Maybe later I will add a few idling animations or patterns.

This is my first major project involving Arduino and coding for that matter.

So I have been trying to learn how to merge sketches and have successfully made this one from two others. One is a test for NeoPixels that drives the LED in single colors and the other is a basic adapted example for the ColorPAL for Arduino boards that creates data readings in the form of three digit hex for Red Green and Blue:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#include <SoftwareSerial.h>

// I/O Pin definitions.
#define PIN 6

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      8

int delayval = 0; // delay for half a second

const int sio = 13;
const int unused = 255; // non-existant pin value
const int sioBaud = 4800;

// Received RGB values from ColorPAL.
int red;
int grn;
int blu;

// Set up two software serials on the same pin.
// This mimic PBASIC's serin and serout function.
SoftwareSerial serin(sio, unused);
SoftwareSerial serout(unused, sio);

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

// -----[ Initialization ]--------------------------------------------------
void setup() {
  // initialize serial communication:
  Serial.begin(9600);

  // Reset the ColorPAL and enter direct command mode.
  reset();

  // Program ColorPAL to send $ then color data.
  serout.begin(sioBaud);
  pinMode(sio, OUTPUT);
  serout.print("= (00 $ m) !"); // buffer commmands, loop print $ and data end_loop now execute
  // serout is unused from this point forwards
  serout.end();

  // Now turn the sio pin into an input to read data from the color pal.
  serin.begin(sioBaud);
  pinMode(sio, INPUT);

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// -----[ Program Code ]----------------------------------------------------
void loop() {
  readData();

  // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.

  for (int i = 0; i < NUMPIXELS; i++) {

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    strip.setPixelColor(i, strip.Color(red, grn, blu)); // Moderately bright green color.

    strip.show(); // This sends the updated pixel color to the hardware.

    delay(delayval); // Delay for a period of time (in milliseconds).

  }
}

// -----[ Subroutines ]-----------------------------------------------------
// reset: Sends a long break to reset ColorPAL and enter direct command mode.
void reset()
{
  pinMode(sio, OUTPUT);
  digitalWrite(sio, LOW);  // Pull sio low to eliminate any residual charge.
  pinMode(sio, INPUT);     // Return pin to input.
  while (digitalRead(sio) != HIGH); // Wait for pin to be pulled high by ColorPAL.
  pinMode(sio, OUTPUT);
  digitalWrite(sio, LOW);  // Pull pin low.
  delay(80);               // Keep low for 80ms to enter Direct mode.
  pinMode(sio, INPUT);     // Return pin to input.
  delay(10);               // Pause another 10ms
}

// -----[ Read Data ]-------------------------------------------------------
void readData()
{
  char buffer[32];

  if (serin.available() > 0)
  {
    // Wait for a $ and then read three 3 digit hex numbers
    buffer[0] = serin.read();
    if (buffer[0] == '

Right now the sensor data changes the NeoPixel strip to the correct color based on the hex data created however, this action is erratic and is not adhering to a pattern of time. Along with this, the sensor is creating false readings in the dark. Without the line of code that controls the LEDs the sensor puts out data readings in a correct constant flow (I am assuming at a rate of 10ms?). At this point my thoughts on solutions for the current code would be to change the rate at which the sensor takes in data to a slower rate. I am assuming that the Arduino is having trouble bouncing between read sensor and light LED and is tripping on itself. At some point I realize that I will have to create code that reads color inputs and directs those readings to two separate iso outputs. Not sure where to go at this point.

Basically I am just looking to see if I am on the right track or if there are any suggestions on how to accomplish this project.

Also, what does "$" mean in this line "if (buffer[0] == '$')". The money sign is not defined in the language section of this site.

If this is relevant here is an example of the ColorPAL reading correctly with the LED code omitted. it is displaying a transition from no object to the introduction of my finger tip.

and here is an image of the readings with the LED code present. Nothing is in front of the ColorPAL

)
{
for (int i = 0; i < 9; i++)
{
// Wait for the next input character.
while (serin.available() == 0);
buffer[i] = serin.read();

    // every so often the data terminates early.  If this happens return
    if (buffer[i] == '

Right now the sensor data changes the NeoPixel strip to the correct color based on the hex data created however, this action is erratic and is not adhering to a pattern of time. Along with this, the sensor is creating false readings in the dark. Without the line of code that controls the LEDs the sensor puts out data readings in a correct constant flow (I am assuming at a rate of 10ms?). At this point my thoughts on solutions for the current code would be to change the rate at which the sensor takes in data to a slower rate. I am assuming that the Arduino is having trouble bouncing between read sensor and light LED and is tripping on itself. At some point I realize that I will have to create code that reads color inputs and directs those readings to two separate iso outputs. Not sure where to go at this point.

Basically I am just looking to see if I am on the right track or if there are any suggestions on how to accomplish this project.

Also, what does "$" mean in this line "if (buffer[0] == '$')". The money sign is not defined in the language section of this site.

If this is relevant here is an example of the ColorPAL reading correctly with the LED code omitted. it is displaying a transition from no object to the introduction of my finger tip.

![|381x500](upload://oder2ayrOUsMzVBLG7G9zZADqsZ.jpeg)

and here is an image of the readings with the LED code present. Nothing is in front of the ColorPAL

![|358x500](upload://76mHzjgtIXFayG1pkZl721WK2Zd.jpeg))
          return;
      }
      parseAndPrint(buffer);
      delay(10);
    }
  }
}

void parseAndPrint(char * data)
{
  // parse the hex data into integers.
  sscanf (data, "%3x%3x%3x", &red, &grn, &blu);

  // format using the format expected by the windows program and output it.
  char buffer[32];
  sprintf(buffer, "R%4.4d G%4.4d B%4.4d", red, grn, blu);
  Serial.println(buffer);
}

Right now the sensor data changes the NeoPixel strip to the correct color based on the hex data created however, this action is erratic and is not adhering to a pattern of time. Along with this, the sensor is creating false readings in the dark. Without the line of code that controls the LEDs the sensor puts out data readings in a correct constant flow (I am assuming at a rate of 10ms?). At this point my thoughts on solutions for the current code would be to change the rate at which the sensor takes in data to a slower rate. I am assuming that the Arduino is having trouble bouncing between read sensor and light LED and is tripping on itself. At some point I realize that I will have to create code that reads color inputs and directs those readings to two separate iso outputs. Not sure where to go at this point.

Basically I am just looking to see if I am on the right track or if there are any suggestions on how to accomplish this project.

Also, what does "$" mean in this line "if (buffer[0] == '$')". The money sign is not defined in the language section of this site.

If this is relevant here is an example of the ColorPAL reading correctly with the LED code omitted. it is displaying a transition from no object to the introduction of my finger tip.

and here is an image of the readings with the LED code present. Nothing is in front of the ColorPAL

To insert an image you need right click the image and select "Copy image URL".

Edit: Images removed from this reply.

TheZane:
Also, what does "$" mean in this line "if (buffer[0] == '$')". The money sign is not defined in the language section of this site.

I imagine the dollar sign is a character used by the ColorPal to indicate the beginning of a message.

That is some strange code for communicating with the ColorPal. I don't understand why two instances of software serial were used. Edit: I understand now. The ColorPal has a single I/O pin. One instance is used for tx and one instance is used for rx.

One item that jumps out at me is this:

int delayval = 0; // delay for half a second

I don't know what a delay of zero does, but I imagine your code might not work as expected if you don't give the ColorPal sensor time to generate a new reading.

Thanks for the heads up about the images. Fixed!

Code: [Select]
int delayval = 0; // delay for half a second

I don't know what a delay of zero does, but I imagine your code might not work as expected if you don't give the ColorPal sensor time to generate a new reading.

I just went into the code and removed this part to see what would happen. Seems the results are the same without it. That portion of the code came over with the NeoPixel example. In its original code it changed how quickly each light lit up in a chain of eight.

int delayval = 500; // delay for half a second

Each light would turn on a half second after the last until all were lit. Making it 0 in this code made all the lights turn on at once.

TheZane:
int delayval = 500; // delay for half a second

Each light would turn on a half second after the last until all were lit. Making it 0 in this code made all the lights turn on at once.

I have a ColorPAL and some NeoPixels. I've been meaning to try using NeoPixels with an Arduino anyway so I'll probably give your code a try.

Is the main problem the erratic behavior?

Do you think the ColorPAL is giving incorrect data?

DuaneDegn:
I have a ColorPAL and some NeoPixels. I've been meaning to try using NeoPixels with an Arduino anyway so I'll probably give your code a try.

Is the main problem the erratic behavior?

Do you think the ColorPAL is giving incorrect data?

Yes to both questions.

Here are the codes I pulled from if you would like.

NeoPixels

// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN            6

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      16

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second

void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  // End of trinket special code

  pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {

  // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.

  for(int i=0;i<NUMPIXELS;i++){

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.

    pixels.show(); // This sends the updated pixel color to the hardware.

    delay(delayval); // Delay for a period of time (in milliseconds).

  }
}

ColorPAL

/* ColorPal Sensor Example
 * Author.... Martin Heermance based upon Phil Pilgrim's PBASIC example
 * with some assistance from Gordon McComb.
 * This program drives the Parallax ColorPAL color sensor and provides
 * serial RGB data to the PC-hosted TCS230_ColorPAL_match.exe color
 * matching program.
 */

#include <SoftwareSerial.h>

// I/O Pin definitions.
const int sio = 13;
const int unused = 255; // non-existant pin value
const int sioBaud = 4800;

// Received RGB values from ColorPAL.
int red;
int grn;
int blu;

// Set up two software serials on the same pin.
// This mimic PBASIC's serin and serout function.
SoftwareSerial serin(sio, unused);
SoftwareSerial serout(unused, sio);

// -----[ Initialization ]--------------------------------------------------
void setup()
{
  // initialize serial communication:
  Serial.begin(9600);
  
  // Reset the ColorPAL and enter direct command mode.
  reset();
  
  // Program ColorPAL to send $ then color data.
  serout.begin(sioBaud);
  pinMode(sio, OUTPUT);
  serout.print("= (00 $ m) !"); // buffer commmands, loop print $ and data end_loop now execute
  // serout is unused from this point forwards
  serout.end();

  // Now turn the sio pin into an input to read data from the color pal.
  serin.begin(sioBaud);
  pinMode(sio, INPUT);
}

// -----[ Program Code ]----------------------------------------------------
// SERIN sio, baud, [WAIT("$"), HEX3 red, HEX3 grn, HEX3 blu] ' Receive RGB data back.
void loop()
{
  readData();
}  

// -----[ Subroutines ]-----------------------------------------------------

// reset: Sends a long break to reset ColorPAL and enter direct command mode.
void reset()
{
  pinMode(sio, OUTPUT);
  digitalWrite(sio, LOW);  // Pull sio low to eliminate any residual charge.
  pinMode(sio, INPUT);     // Return pin to input.
  while (digitalRead(sio) != HIGH); // Wait for pin to be pulled high by ColorPAL.
  pinMode(sio, OUTPUT);
  digitalWrite(sio, LOW);  // Pull pin low.
  delay(80);               // Keep low for 80ms to enter Direct mode.
  pinMode(sio, INPUT);     // Return pin to input.
  delay(10);               // Pause another 10ms
}

void readData()
{
  char buffer[32];
  
  if (serin.available() > 0)
  {
    // Wait for a $ and then read three 3 digit hex numbers
    buffer[0] = serin.read();
    if (buffer[0] == '

Also here are links to the Libraries

The ColorPAL code is the way it is because of Martin_H. He was adapting the program to arduino to run ColorPAL Color Matching Program which only ran with .bs files. See his journey here if you want.

The original code never yielded results but you may have better luck: http://learn.parallax.com/colorpal-arduino-demo)
    {
      for(int i = 0; i < 9; i++)
      {
        // Wait for the next input character.
        while (serin.available() == 0);   
        buffer[i] = serin.read();

// every so often the data terminates early.  If this happens return
        if (buffer[i] == '


Also here are links to the Libraries
https://www.parallax.com/product/28380
https://github.com/adafruit/Adafruit_NeoPixel

The ColorPAL code is the way it is because of Martin_H. He was adapting the program to arduino to run ColorPAL Color Matching Program which only ran with .bs files. See his journey here if you want.
http://forums.parallax.com/discussion/138612/colorpal-arduino-problem

The original code never yielded results but you may have better luck: http://learn.parallax.com/colorpal-arduino-demo)
          return;
      }
      parseAndPrint(buffer);
      delay(10);
    }
  }
}

void parseAndPrint(char * data)
{
  // parse the hex data into integers.
  sscanf (data, "%3x%3x%3x", &red, &grn, &blu);

  // format using the format expected by the windows program and output it.
  char buffer[32];
  sprintf(buffer, "R%4.4d G%4.4d B%4.4d", red, grn, blu);
  Serial.println(buffer);
}

Also here are links to the Libraries

The ColorPAL code is the way it is because of Martin_H. He was adapting the program to arduino to run ColorPAL Color Matching Program which only ran with .bs files. See his journey here if you want.

The original code never yielded results but you may have better luck: http://learn.parallax.com/colorpal-arduino-demo

TheZane:
The ColorPAL code is the way it is because of Martin_H. He was adapting the program to arduino to run ColorPAL Color Matching Program which only ran with .bs files. See his journey here if you want.
http://forums.parallax.com/discussion/138612/colorpal-arduino-problem

Martin_H knows a lot more about Arduinos than I do.

I like to think Martin is a friend of mine (I've been participating in the Parallax forums for about six years).

Thanks for adding the original versions of the code. I'll try to see if I can help get consistent readings from the sensor.

Here's my first attempt.

It does some interesting things I think.

The program has a global brightness variable. I have set to one third of the maximum brightness.

If you want to change the brightness level, change the "DEFAULT_BRIGHTNESS" in this section of code.

const int MAX_BRIGHTNESS = 255;
const int DEFAULT_BRIGHTNESS = MAX_BRIGHTNESS / 3;
int brightness = DEFAULT_BRIGHTNESS;

The code scales the brightness from the ColorPal so at least one of the NeoPixels' colors is the full brightness.

It's possible to keep the brightness from being scaled up as it currently is and let you know what to change later.

Hopefully this code will work okay for you.

I changed the baud from 9600 to 115200. I also changed the pin assignments from what you had (they're the same as the original code).

Here's what I have so far.

/* NeoPal151123d
 *  
 * by Duane Degn 
 * November 23, 2015
 * 
 * 
 * Based on code by Martin Heermance and code from Adafruit.
 * 
 * Comments from ColorPal code:
 * ColorPal Sensor Example
 * Author.... Martin Heermance based upon Phil Pilgrim's PBASIC example
 * with some assistance from Gordon McComb.
 * This program drives the Parallax ColorPAL color sensor and provides
 * serial RGB data to the PC-hosted TCS230_ColorPAL_match.exe color
 * matching program.
 */

#define NEOPIXEL_PIN 6
#define NUMPIXELS 16
#include <SoftwareSerial.h>
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);


const int MAX_PIXEL_INDEX = NUMPIXELS - 1;

const int SIO_PIN = 2;
const int UNUSED_PIN = 255; // non-existant pin value
const int SIO_BAUD = 4800;
const int USB_BAUD = 115200;

const int DELAY_VALUE = 100;
const int MAX_BRIGHTNESS = 255;
const int DEFAULT_BRIGHTNESS = MAX_BRIGHTNESS / 3;
int brightness = DEFAULT_BRIGHTNESS;

// Received RGB values from ColorPAL.
int red;
int green;
int blue;

// Set up two software serials on the same pin.
// This mimic PBASIC's serin and serout function.
SoftwareSerial serin(SIO_PIN, UNUSED_PIN);
SoftwareSerial serout(UNUSED_PIN, SIO_PIN);

// -----[ Initialization ]--------------------------------------------------
void setup()
{
  // initialize serial communication:
  Serial.begin(USB_BAUD);

  // Reset the ColorPAL and enter direct command mode.
  reset();

  // Program ColorPAL to send $ then color data.
  serout.begin(SIO_BAUD);
  pinMode(SIO_PIN, OUTPUT);
  serout.print("= (00 $ m) !"); // buffer commmands, loop print $ and data end_loop now execute
  // serout is unused from this point forwards
  serout.end();

  // Now turn the SIO_PIN pin into an input to read data from the color pal.
  serin.begin(SIO_BAUD);
  pinMode(SIO_PIN, INPUT);
  pixels.begin(); // This initializes the NeoPixel library.
}

// -----[ Program Code ]----------------------------------------------------
// SERIN SIO_PIN, baud, [WAIT("$"), HEX3 red, HEX3 green, HEX3 blue] ' Receive RGB data back.
void loop()
{
  boolean goodDataFlag = readData();
  if (goodDataFlag)
  {
    scalePalToPixel(0, MAX_BRIGHTNESS, 0, MAX_PIXEL_INDEX);
    pixels.show(); // This sends the updated pixel color to the hardware.
    delay(DELAY_VALUE);
  }
  else
  {
    Serial.println("Error, Bad Data);
  }
}

void scalePalToPixel(int maxPal, int maxPixel, int firstPixel, int lastPixel)
{

  if (maxPal == 0)
  {
    if (red >= blue && red >= green)
    {
      maxPal = red;
    }
    else if (green >= red && green >= blue)
    {
      maxPal = green;
    }
    else
    {
      maxPal = blue;
    }
  }
  int localRed = red * maxPixel / maxPal;
  int localGreen = green * maxPixel / maxPal;
  int localBlue = blue * maxPixel / maxPal;
  for (int i = firstPixel; i <= lastPixel; i++)
  {
    setPixel(i, localRed, localGreen, localBlue, brightness);
  }
}
void setPixel(int pixelIndex, int fullBrightnessRed, int fullBrightnessGreen, int fullBrightnessBlue, int localBrightness)
{
  pixels.setPixelColor(pixelIndex, pixels.Color(fullBrightnessRed * localBrightness / MAX_BRIGHTNESS, fullBrightnessGreen * localBrightness / MAX_BRIGHTNESS, fullBrightnessBlue * localBrightness / MAX_BRIGHTNESS)); // Moderately bright green color.
}

// reset: Sends a long break to reset ColorPAL and enter direct command mode.
void reset()
{
  pinMode(SIO_PIN, OUTPUT);
  digitalWrite(SIO_PIN, LOW);  // Pull SIO_PIN low to eliminate any residual charge.
  pinMode(SIO_PIN, INPUT);     // Return pin to input.
  while (digitalRead(SIO_PIN) != HIGH); // Wait for pin to be pulled high by ColorPAL.
  pinMode(SIO_PIN, OUTPUT);
  digitalWrite(SIO_PIN, LOW);  // Pull pin low.
  delay(80);               // Keep low for 80ms to enter Direct mode.
  pinMode(SIO_PIN, INPUT);     // Return pin to input.
  delay(10);               // Pause another 10ms
}

boolean readData()
{
  char buffer[32];

  if (serin.available() > 0)
  {
    // Wait for a $ and then read three 3 digit hex numbers
    buffer[0] = serin.read();
    if (buffer[0] == '

)
    {
      for (int i = 0; i < 9; i++)
      {
        // Wait for the next input character.
        while (serin.available() == 0);
        buffer[i] = serin.read();

// every so often the data terminates early.  If this happens return
        if (buffer[i] == '


)
          return 0;
      }
      parseAndPrint(buffer);
      delay(10);

    }
  }
  return 1;
}

void parseAndPrint(char * data)
{
  // parse the hex data into integers.
  sscanf (data, "%3x%3x%3x", &red, &green, &blue);

  // format using the format expected by the windows program and output it.
  char buffer[32];
  sprintf(buffer, "R%4.4d G%4.4d B%4.4d", red, green, blue);
  Serial.println(buffer);
}

Thanks Duane! I'll give it a go later this afternoon and let you know what happens.

Just a heads up. The code I posted doesn't appear to compile. I doesn't produce an error message, it the IDE just hangs.

I thought the problem was my PC but I rebooted and it hung again.

I'm trying to fix this. I don't understand what I did to break it.

This is a harder problem to solve than I had original thought it would be.

The code below sort of works but it's awful.

/* NeoPal151124a
 *  
 * by Duane Degn 
 * November 24, 2015
 * 
 * 
 * Based on code by Martin Heermance and code from Adafruit.
 * 
 * Comments from ColorPal code:
 * 
 * ColorPal Sensor Example
 * Author.... Martin Heermance based upon Phil Pilgrim's PBASIC example
 * with some assistance from Gordon McComb.
 * This program drives the Parallax ColorPAL color sensor and provides
 * serial RGB data to the PC-hosted TCS230_ColorPAL_match.exe color
 * matching program.
 */
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>
#define NEOPIXEL_PIN 6
#define NUMPIXELS      8

// I/O Pin definitions.
const int SIO_PIN = 2;
const int UNUSED_PIN = 255; // non-existant pin value
const int SIO_BAUD = 4800;
const int USB_BAUD = 9600; //115200;

const unsigned long DELAY_VALUE_US = 500; //100;
const unsigned long MAX_BRIGHTNESS = 255;
const unsigned long DEFAULT_BRIGHTNESS = MAX_BRIGHTNESS / 3;
unsigned long brightness = DEFAULT_BRIGHTNESS;

// Received RGB values from ColorPAL.
unsigned long red;
unsigned long green;
unsigned long blue;

unsigned long lastRead;
// Set up two software serials on the same pin.
// This mimic PBASIC's serin and serout function.
SoftwareSerial serin(SIO_PIN, UNUSED_PIN);
SoftwareSerial serout(UNUSED_PIN, SIO_PIN);
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

// -----[ Initialization ]--------------------------------------------------
void setup()
{
  // initialize serial communication:
  Serial.begin(USB_BAUD);
  Serial.println("Beginning of NeoPal Program");
  // Reset the ColorPAL and enter direct command mode.
  reset();
  
  // Program ColorPAL to send $ then color data.
  serout.begin(SIO_BAUD);
  pinMode(SIO_PIN, OUTPUT);
  serout.print("= (00 $ m) !"); // buffer commmands, loop print $ and data end_loop now execute
  // serout is unused from this point forwards
  serout.end();

  // Now turn the SIO_PIN pin into an input to read data from the color pal.
  serin.begin(SIO_BAUD);
  pinMode(SIO_PIN, INPUT);

  pixels.begin();
  pixels.show(); // Initialize all pixels to 'off'
  lastRead = micros();
}

// -----[ Program Code ]----------------------------------------------------
// SERIN SIO_PIN, baud, [WAIT("$"), HEX3 red, HEX3 green, HEX3 blue] ' Receive RGB data back.
void loop()
{
  checkTime();
}

void checkTime()
{
  if (1)//(micros() - lastRead > DELAY_VALUE_US)
  {
    lastRead += DELAY_VALUE_US;
    Serial.println("Time for new update.");
    colorPixelsFromPal();
  }
}

void colorPixelsFromPal()
{
  int dataFlag = 0;
  
  Serial.println("colorPixelsFromPal Function");
  
  while (dataFlag == 0)
  {
    dataFlag = readData();
  }

  scalePalToPixel(0, 255, 0, NUMPIXELS - 1);
  pixels.show(); // This sends the updated pixel color to the hardware.
}
void scalePalToPixel(unsigned long maxPal, unsigned long maxPixel, int firstPixel, int lastPixel)
{
  Serial.print("scalePalToPixel, brightest color = ");
  if (maxPal == 0)
  {
    if (red >= blue && red >= green)
    {
      maxPal = red;
      Serial.print("red");
    }
    else if (green >= red && green >= blue)
    {
      maxPal = green;
      Serial.print("green");
    }
    else
    {
      maxPal = blue;
      Serial.print("blue");
    }
    
  }
  Serial.print(", maxPal = ");
  Serial.print(maxPal);
  Serial.print(", pixel colors = ");
  
  unsigned long localRed = red * maxPixel / maxPal;
  unsigned long localGreen = green * maxPixel / maxPal;
  unsigned long localBlue = blue * maxPixel / maxPal;

  Serial.print(localRed);
  Serial.print(", ");
  Serial.print(localGreen);
  Serial.print(", ");
  Serial.print(localBlue);
  Serial.print(", ColorPAL colors = ");
  Serial.print(red);
  Serial.print(", ");
  Serial.print(green);
  Serial.print(", ");
  Serial.print(blue);
    
  for (int i = firstPixel; i <= lastPixel; i++)
  {
    setPixel(i, localRed, localGreen, localBlue, brightness);
  }
}
void setPixel(int pixelIndex, byte fullBrightnessRed, byte fullBrightnessGreen, byte fullBrightnessBlue, byte localBrightness)
{
  pixels.setPixelColor(pixelIndex, pixels.Color(fullBrightnessRed * localBrightness / MAX_BRIGHTNESS, fullBrightnessGreen * localBrightness / MAX_BRIGHTNESS, fullBrightnessBlue * localBrightness / MAX_BRIGHTNESS)); // Moderately bright green color.
}

// reset: Sends a long break to reset ColorPAL and enter direct command mode.
void reset()
{
  pinMode(SIO_PIN, OUTPUT);
  digitalWrite(SIO_PIN, LOW);  // Pull SIO_PIN low to eliminate any residual charge.
  pinMode(SIO_PIN, INPUT);     // Return pin to input.
  while (digitalRead(SIO_PIN) != HIGH); // Wait for pin to be pulled high by ColorPAL.
  pinMode(SIO_PIN, OUTPUT);
  digitalWrite(SIO_PIN, LOW);  // Pull pin low.
  delay(80);               // Keep low for 80ms to enter Direct mode.
  pinMode(SIO_PIN, INPUT);     // Return pin to input.
  delay(10);               // Pause another 10ms
}

int readData()
{
  char buffer[32];

  //Serial.println("readData Function");
  
  if (serin.available() > 0)
  {
    // Wait for a $ and then read three 3 digit hex numbers
    buffer[0] = serin.read();
    if (buffer[0] == '

I think the NeoPixel library doesn't play well with the software serial.

I noticed "delay" statements seems to cause the program to freeze. I switched to a "checkTime" function. Right now the delay is commented out.

Change the code below:

  if (1)//(micros() - lastRead > DELAY_VALUE_US)

to

  if (micros() - lastRead > DELAY_VALUE_US)

and then you could experiment with different delay times in microseconds.

I haven't found any delay times which work well.

I'm not sure what else to try.)
    {
      for(int i = 0; i < 9; i++)
      {
        // Wait for the next input character.
        while (serin.available() == 0);   
        buffer[i] = serin.read();

// every so often the data terminates early.  If this happens return
        if (buffer[i] == '


I think the NeoPixel library doesn't play well with the software serial.

I noticed "delay" statements seems to cause the program to freeze. I switched to a "checkTime" function. Right now the delay is commented out.

Change the code below:

§DISCOURSE_HOISTED_CODE_1§


to 

§DISCOURSE_HOISTED_CODE_2§


and then you could experiment with different delay times in microseconds.

I haven't found any delay times which work well.

I'm not sure what else to try.)
        {
          Serial.println("End readData Function Early");
          return 0;
        }
      }
      parseAndPrint(buffer);
      //Serial.println("Good data from readData Function.");
      return 1;
    }
    else
    {
      Serial.print(", 0x");
      Serial.print(buffer[0], HEX);
      return 0;
    }
  }
  else
  {
    Serial.print("No data. ");
    return 0;
  }
}

void parseAndPrint(char * data)
{
  // parse the hex data into integers.
  sscanf (data, "%3x%3x%3x", &red, &green, &blue);

  // format using the format expected by the windows program and output it.
  //char buffer[32];
  //sprintf(buffer, "R%4.4d G%4.4d B%4.4d", red, green, blue);
  /*Serial.println();
  Serial.print("R");
  Serial.print(red);
  Serial.print(" G");
  Serial.print(green);
  Serial.print(" B");
  Serial.println(blue);*/
  
}

I think the NeoPixel library doesn't play well with the software serial.

I noticed "delay" statements seems to cause the program to freeze. I switched to a "checkTime" function. Right now the delay is commented out.

Change the code below:

§_DISCOURSE_HOISTED_CODE_1_§

to

§_DISCOURSE_HOISTED_CODE_2_§

and then you could experiment with different delay times in microseconds.

I haven't found any delay times which work well.

I'm not sure what else to try.

I'm throwing in the towel on this one.

I think you either need to switch the ColorPAL to the hardware serial or use a Mega for an additional hardware serial port.

I think the software serial doesn't play well with the NeoPixel driver.

I tried this on a Propeller microcontroller and it seems to work fine. I posted the Propeller code in your Parallax forum thread.

I'm working on a Mega. I came up with this last night. Give it a whirl. Basically the buttons just shovel data over to the NeoPixels. Works really smoothly.

/* ColorPal Sensor Example
   Author.... Zane Miller and Martin Heermance based upon Phil Pilgrim's PBASIC example
   with some assistance from Gordon McComb.
   This program drives the Parallax ColorPAL color sensor and provides
   serial RGB data to the PC-hosted TCS230_ColorPAL_match.exe color
   matching program.
*/

#include <Adafruit_NeoPixel.h>

#define buttonPinA   2    // Digital IO pin connected to the button.  This will be
// driven with a pull-up resistor so the switch should
// pull the pin to ground momentarily.  On a high -> low
// transition the button press logic will execute.
#define buttonPinB   4

#define PIXEL_PINA    6    // Digital IO pin connected to the NeoPixels.
#define PIXEL_PINB    7    // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 8

// Parameter 1 = number of pixels in strip,  neopixel stick has 8
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream, correct for neopixel stick
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
Adafruit_NeoPixel stripA = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PINA, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripB = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PINB, NEO_GRB + NEO_KHZ800);

bool oldState = HIGH;
int showType = 0;

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

#include <SoftwareSerial.h>

// I/O Pin definitions.
const int sio = 13;
const int unused = 255; // non-existant pin value
const int sioBaud = 4800;

// Received RGB values from ColorPAL.
int red;
int grn;
int blu;

// Set up two software serials on the same pin.
// This mimic PBASIC's serin and serout function.
SoftwareSerial serin(sio, unused);
SoftwareSerial serout(unused, sio);

// -----[ Initialization ]--------------------------------------------------
void setup()
{ 
  
    // initialize serial communication:
    Serial.begin(9600);

    // Reset the ColorPAL and enter direct command mode.
    reset();
   
    // Program ColorPAL to send $ then color data.
    serout.begin(sioBaud);
    pinMode(sio, OUTPUT);
    serout.print("= (00 $ m) !"); // buffer commmands, loop print $ and data end_loop now execute
    // serout is unused from this point forwards
    serout.end();

    // Now turn the sio pin into an input to read data from the color pal.
    serin.begin(sioBaud);
    pinMode(sio, INPUT);

  stripA.begin();
  stripA.show(); // Initialize all pixels to 'off'

  stripB.begin();
  stripB.show(); // Initialize all pixels to 'off'
 }


// -----[ Program Code ]----------------------------------------------------
// SERIN sio, baud, [WAIT("$"), HEX3 red, HEX3 grn, HEX3 blu] ' Receive RGB data back.
void loop()
{
{
  readData();
}

{
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPinA);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:

    digitalWrite(PIXEL_PINA, HIGH); 
         
    for (int i = 0; i < PIXEL_PINA; i++) {

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    stripA.setPixelColor(i, stripA.Color(red, grn, blu));
    
    stripA.show(); // This sends the updated pixel color to the hardware.
  }
  } else {
    // turn LED off:
    digitalWrite(PIXEL_PINA, LOW);
  }
}
{
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPinB);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:

    digitalWrite(PIXEL_PINB, HIGH); 
         
    for (int i = 0; i < PIXEL_PINB; i++) {

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    stripB.setPixelColor(i, stripB.Color(red, grn, blu));
    
    stripB.show(); // This sends the updated pixel color to the hardware.
  }
  } else {
    // turn LED off:
    digitalWrite(PIXEL_PINB, LOW);
  }
}
}
// -----[ Subroutines ]-----------------------------------------------------

// reset: Sends a long break to reset ColorPAL and enter direct command mode.

void reset()
{
  pinMode(sio, OUTPUT);
  digitalWrite(sio, LOW);  // Pull sio low to eliminate any residual charge.
  pinMode(sio, INPUT);     // Return pin to input.
  while (digitalRead(sio) != HIGH); // Wait for pin to be pulled high by ColorPAL.
  pinMode(sio, OUTPUT);
  digitalWrite(sio, LOW);  // Pull pin low.
  delay(80);               // Keep low for 80ms to enter Direct mode.
  pinMode(sio, INPUT);     // Return pin to input.
  delay(10);               // Pause another 10ms
}

void readData()
{
  char buffer[32];

  if (serin.available() > 0)
  {
    // Wait for a $ and then read three 3 digit hex numbers
    buffer[0] = serin.read();
    if (buffer[0] == '

)
    {
      for (int i = 0; i < 9; i++)
      {
        // Wait for the next input character.
        while (serin.available() == 0);
        buffer[i] = serin.read();

// every so often the data terminates early.  If this happens return
        if (buffer[i] == '


)
          return;
      }
      parseAndPrint(buffer);
      delay(10);
    }
  }
}

void parseAndPrint(char * data)
{
  // parse the hex data into integers.
  sscanf (data, "%3x%3x%3x", &red, &grn, &blu);

  // format using the format expected by the windows program and output it.
  char buffer[32];
  sprintf(buffer, "R%4.4d G%4.4d B%4.4d", red, grn, blu);
  Serial.println(buffer);
}