ColorPAL and NeoPixels
TheZane
Posts: 2
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:
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.
Here are the two source sketches that I am pulling from:
ColorPAL
NeoPixels
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
Also, thanks Martin_H for your work. It brought the sensor to life a few days ago.
The original code for the ColorPAL never yielded results but here it is: http://learn.parallax.com/colorpal-arduino-demo
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] == '$') { 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); }
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.
Here are the two source sketches that I am pulling from:
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] == '$') { 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); }
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). } }
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
Also, thanks Martin_H for your work. It brought the sensor to life a few days ago.
The original code for the ColorPAL never yielded results but here it is: http://learn.parallax.com/colorpal-arduino-demo
Comments
Here's the Arduino forum post on the topic.
I suspect something with the NeoPixel driver and the soft serial conflicted.
I pulled out a Propeller, and the two drivers went together without any issue.
Here's the Propeller code.
I bet if the ColorPAL were moved to the hardware serial on the Arduino, it wouldn't conflict with NeoPixel driver.
I think the conflict could also be solved by using a Mega. The Mega's additional hardware serial shouldn't conflict with the NeoPixel driver.