Lab 3: ColorPAL
Use Serial.read() to control the Arduino
We learned we needed to enter or "send" the data to the serial monitor each time we input new data.
Play Notes on the Arduino
int inputChar;
void setup () {
pinMode(12,OUTPUT);
Serial.begin(9600);
}
// this code will play the A major scale which has 3 sharps, C#, F#, and G#
void loop(){
if (Serial.available() > 0) {
inputChar = Serial.read();
if (inputChar == 'a'){
tone(12,1760);
}
if(inputChar == 'b'){
tone(12,1976);
}
if(inputChar == 'c'){
tone(12,2216);
}
if(inputChar == 'd'){
tone(12,2348);
}
if(inputChar == 'e'){
tone(12,2636);
}
if(inputChar == 'f'){
tone(12, 2960);
}
if(inputChar == 'g'){
tone(12, 3324, 400);
}
}
}
Above is the code we used to play different tones corresponding to an A major scale.
We used a Piezo buzzer and had the same circuit set-up as in previous labs.
Create some LED flashing routines and trigger them with different letter commands
In this lab, we learned how to use to ColorPAL sensor and coded for discrepancies since the ColorPAL sensor is not perfect and also has internal reflectance.
Thus, we first calibrated our sensor by using a "white reference" and a "black reference" - we used the white cover of my notebook and then a black USB cord to then develop a color correction formula.
*Important note: To power the ColorPAL resistor, we must use Ground on the Analog side of the Arduino board.
ColorPAL Color Sensor
When we first measured our white reference, the following values appeared: R177, G132, B254. We used a white piece of paper as our reference.
Then with black reference, where the colors should all be 0 (since black is the absence of color), we read values of B7 G3 R8. For this, we used a black lid from a coffee mug.
Thus, we found our values that needed to be adjusted for.
The values from the black reference indicate Kr, Kg, and Kb.
Thus, in conjunction with the measured values, Ur, Ug, and Ub, we can find the intensity of the reflected light.
Actual reading: (Ur – Kr), (Ug – Kg), and (Ub – Ug).
U = the uncorrected measurement
The values from the white reference are labeled as Wr, Wg, and Wb.
Thus, in conjunction with the measures values, we can find the maximum range of red, green, and blue.
Range: (Wr – Kr), (Wg – Kg), and (Wb – Kb)
Thus, the corrected color measurements would be:
Cr = (Ur – Kr) / (Wr – Kr)
Cg = (Ug – Kg) / (Wg – Kg)
Cb = (Ub – Kb) / (Wb – Kb)
The corrected values range between 0 and 1. 0 would indicate a black (based on our black target) and 1 would indicate white based on our white target.
From here, we began coding so that the ColorPAL could read different colors and return the color based on a combination of R, G, and B values.
![]() |
| Circuit with the 3-pronged ColorPAL sensor. |
Here is a series of videos showing the ColorPAL working with various colors:
Below is our code including the corrected colors:
#include <OldSoftwareSerial.h>
OldSoftwareSerial Color90(2, 3); // rx = 2, tx = 3
float red;
float grn;
float blu;
int Cr = 0.0;
int Cg = 0.0;
int Cb = 0.0;
float Kr = 7.0;
float Kg = 3.0;
float Kb = 8.0;
float Wr = 177.0;
float Wg = 132.0;
float Wb = 254.0;
int gotcolor = 0;
int letter;
void setup()
{
Serial.begin(9600); // Start communication with serial port read value
Color90.begin(4800); // Send signal to led to read value
pinMode(2,INPUT); // serial pin out from color pal
pinMode(3,INPUT); // from same serial pin, signal pulls up, sends, pulls down, reads
digitalWrite(2,HIGH); // Enable the pull-up resistor
digitalWrite(3,HIGH); // Enable the pull-up resistor
pinMode(2,OUTPUT); // send signal out
pinMode(3,OUTPUT);
digitalWrite(2,LOW); // turn pin off so pin 3 can go high
digitalWrite(3,LOW);
pinMode(2,INPUT); // Input signal to print
pinMode(3,INPUT);
Serial.println("Pass 1");
// delay(20);
while( digitalRead(2) != HIGH || digitalRead(3) != HIGH ) {
Serial.println("In the loop");
delay(50);
}
Serial.println("Pass 2");
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
digitalWrite(2,LOW);
digitalWrite(3,LOW);
delay(100); // spec is 80, but not all ColorPAL units work with 80
pinMode(2,INPUT);
pinMode(3,OUTPUT);
delay(100);
}
// This oscillates back and forth on one wire to turn off led, send signal,
// turn on led, read signal. very fast strobe read - arduino is not capable of
// one wire signal communication over digital ports, so this is a way around
// that over 2 wires communicating with 1 pin on the sensor.
//---------------------------------
void loop()
{
readcolor();
Serial.println(Rainbow(red,grn,blu));
// readcolor();
// Serial.print("R");
// Serial.print(red);
// Serial.print(" G");
// Serial.print(grn);
// Serial.print(" B");
// Serial.println(blu);
gotcolor = 0;
delay(1000);
}
void readcolor() { // Reads ColorPAL, putting results in the red,grn,blu variables
char rByte[9];
char dummy[4];
delay(20);
Color90.begin(4800);
Color90.print("= (00 $ m) !"); // set up loop to continuously send color data
pinMode(3,INPUT);
gotcolor = 0;
while (gotcolor == 0) {
rByte[0] = Color90.read();
if( rByte[0] == '$' ) {
gotcolor = 1;
for(int i=0; i<9; i++) {
rByte[i] = Color90.read();
// Serial.print(rByte[i]);
}
Serial.println("");
dummy[0] = rByte[0];
dummy[1] = rByte[1];
dummy[2] = rByte[2];
dummy[3] = 0;
Cr = strtol(dummy,NULL,16);
red = (Cr-Kr)/(Wr-Kr); //corrected red
dummy[0] = rByte[3];
dummy[1] = rByte[4];
dummy[2] = rByte[5];
Cg = strtol(dummy,NULL,16);
grn= (Cg-Kg)/(Wg-Kg); //corrected green
dummy[0] = rByte[6];
dummy[1] = rByte[7];
dummy[2] = rByte[8];
Cb = strtol(dummy,NULL,16);
blu = (Cb-Kb)/(Wb-Kb); //corrected blue
}
}
}
String Rainbow(double red, double green, double blue){
if(red>=0.45){
if ((green <=0.1) && (blue <= 0.1)){
return "red";
}
else if((green >= 0.5) && (green > blue)){
return "yellow";
}
else{
return "color";
}
}
else if((blue > green) && (blue > red)){
return "blue";
}
else if((green > blue) && (green > red)){
return "green";
}
else{
return "color";
}
}

Comments
Post a Comment