Starting with the SunFounder DIY Bionic Robot Lizard, I am trying to build a chameleon that uses TCS34725 RGB sensor to control a set of eight RGB LEDs so that when the lizard crawls over surfaces of different colors, it changes color to match the surface. At the moment I am using ten swatches of colored construction paper as test surfaces.
The lizard comes with a Nano on an extension board that provides a power supply and a row of triple pins that include GND, VCC and Signal. I am using PWM pins 9, 10, 11 to control the brightness of the RBG LEDs, The total current draw is well less than the maximum 150mA per pin specified in the Nano datasheet. My test program for the RGB sensor with the LEDs works fine (see below)
#include <Wire.h>
#include "Adafruit_TCS34725.h"
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_101MS, TCS34725_GAIN_60X);
const int PWM_PIN_RED = 9; // Pulse Width Modulation output pin for Red lead of RGB LED
const int PWM_PIN_GREEN = 10; // Pulse Width Modulation output pin for Green lead of RGB LED
const int PWM_PIN_BLUE = 11; // Pulse Width Modulation output pin for Blue lead of RGB LED
class ColorMatcher {
private:
// class member variables, initialized upon instantiation
// First index is color swatch 0..9 ~ Red, Orange .. White; 2nd index is R,G,B ~ 0,1,2
double outputPWM[10][3] = {{253, 0, 2}, {253, 221, 0}, {230, 253, 0}, {0, 253, 1}, {0, 253, 41}, {0, 0, 246}, {100, 0, 246}, {2, 2, 0}, {0, 0, 0}, {107, 253, 102}};
double colorSwatch[10][3] = {{143, 57, 61}, {155, 55, 48}, {175, 121, 75}, {72, 102, 81}, {58, 103, 128}, {58, 80, 118}, {82, 76, 100}, {105, 78, 71}, {90, 82, 81}, {196, 191, 194}};
double reading[3] = {0.0, 0.0, 0.0};
#define commonAnode false // set to false if using a common cathode LED
double sepFunction(double x1, double x2, double y1, double y2, double z1, double z2) {
double separation;
separation = sqrt(sq(x2 - x1) + sq(y2 - y1) + sq(z2 - z1));
return separation;
}
public:
ColorMatcher() {
pinMode(PWM_PIN_RED, OUTPUT);
pinMode(PWM_PIN_GREEN, OUTPUT);
pinMode(PWM_PIN_BLUE, OUTPUT);
}
void Update() {
uint16_t r, g, b, c;
tcs.setInterrupt(false); // turn on LED
delay(60); // takes 50ms to read
tcs.getRawData(&r, &g, &b, &c);
tcs.setInterrupt(true); // turn off LED
uint32_t sum = c;
float R, G, B;
R = r; R /= sum; // Compute the fraction of light passing through the red filter, relative to no filter
G = g; G /= sum;
B = b; B /= sum;
R *= 256; G *= 256; B *= 256; // Compute fractions of filtered light relative to 256
reading[0] = R;
reading[1] = G;
reading[2] = B;
double shortest = 512; //pick an initial separation which is way too big
int n = -1; //index matching closest colorSwatch vector
for (int i = 0; i < 10; i = i + 1) {
double distance = sepFunction(reading[0], colorSwatch[i][0], reading[1], colorSwatch[i][1], reading[2], colorSwatch[i][2]);
if (distance < shortest) {
shortest = distance;
n = i;
}
}
Serial.print("n = "); Serial.println(n);
analogWrite(PWM_PIN_RED, outputPWM[n][0]); //
analogWrite(PWM_PIN_GREEN, outputPWM[n][1]); //
analogWrite(PWM_PIN_BLUE, outputPWM[n][2]); //
}
}; // end ColorMatcher class
ColorMatcher colorMatcher; // Create colorMatcher object
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Begin Serial");
if (tcs.begin()) {
Serial.println("Ready");
} else {
Serial.println("No TCS34725 found ... check your connections");
while (1);
}
}
void loop() {
// put your main code here, to run repeatedly:
colorMatcher.Update();
}
[/code]
type or paste code here
The code for making the lizard crawl also works as expected. However, when I try to integrate the code for the RGB sensor / LEDs, it fails when I try to attach a servo. See below, line number 186
/* Object Libraries for RGB sensor and servos*/
#include <Wire.h>
#include "Adafruit_TCS34725.h"
/* Object for RGB sensor */
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_101MS, TCS34725_GAIN_60X);
#include <Servo.h>
/* Objects for Servos */
Servo Servo_1; // front legs of lizard
Servo Servo_2; // waist of lizard
Servo Servo_3; // back legs of lizard
/* Constants for RGB LEDs */
const int PWM_PIN_RED = 9; // Pulse Width Modulation output pin for Red lead of RGB LED
const int PWM_PIN_GREEN = 10; // Pulse Width Modulation output pin for Green lead of RGB LED
const int PWM_PIN_BLUE = 11; // Pulse Width Modulation output pin for Blue lead of RGB LED
/* Constants and variables for servos */
const bool HALF = true; // used to indicate half-turn
const bool FULL = false; // used to indicate full-turn
const bool RIGHT = true;
const bool LEFT = false;
const bool CW = true;
const bool CCW = false;
int T1DEG = 17; // milliseconds to move through one degree
int zeropos[] = {74, 83, 94}; // array of initial positions
int waist_angle = 25; // angle turned by waist servo
int step_angle = 35; // angle turned by front and back servos when stepping
int turn_angle = 55; // angle turned by front and back servos when making a turn
/* ColorMatcher object */
class ColorMatcher {
private:
// class member variables, initialized upon instantiation
// First index is color swatch 0..9 ~ Red, Orange .. White; 2nd index is R,G,B ~ 0,1,2
double outputPWM[10][3] = {{253, 0, 2}, {253, 221, 0}, {230, 253, 0}, {0, 253, 1}, {0, 253, 41}, {0, 0, 246}, {100, 0, 246}, {2, 2, 0}, {0, 0, 0}, {107, 253, 102}};
double colorSwatch[10][3] = {{143, 57, 61}, {155, 55, 48}, {175, 121, 75}, {72, 102, 81}, {58, 103, 128}, {58, 80, 118}, {82, 76, 100}, {105, 78, 71}, {90, 82, 81}, {196, 191, 194}};
double reading[3] = {0.0, 0.0, 0.0};
#define commonAnode false // set to false if using a common cathode LED
double sepFunction(double x1, double x2, double y1, double y2, double z1, double z2) {
double separation;
separation = sqrt(sq(x2 - x1) + sq(y2 - y1) + sq(z2 - z1));
return separation;
}
public:
ColorMatcher() {
pinMode(PWM_PIN_RED, OUTPUT);
pinMode(PWM_PIN_GREEN, OUTPUT);
pinMode(PWM_PIN_BLUE, OUTPUT);
}
void Update() {
uint16_t r, g, b, c;
tcs.setInterrupt(false); // turn on LED
delay(60); // takes 50ms to read
tcs.getRawData(&r, &g, &b, &c);
tcs.setInterrupt(true); // turn off LED
uint32_t sum = c;
float R, G, B;
R = r; R /= sum; // Compute the fraction of light passing through the red filter, relative to no filter
G = g; G /= sum;
B = b; B /= sum;
R *= 256; G *= 256; B *= 256; // Compute fractions of filtered light relative to 256
reading[0] = R;
reading[1] = G;
reading[2] = B;
double shortest = 512; //pick an initial separation which is way too big
int n = -1; //index matching closest colorSwatch vector
for (int i = 0; i < 10; i = i + 1) {
double distance = sepFunction(reading[0], colorSwatch[i][0], reading[1], colorSwatch[i][1], reading[2], colorSwatch[i][2]);
if (distance < shortest) {
shortest = distance;
n = i;
}
}
Serial.print("n = "); Serial.println(n);
analogWrite(PWM_PIN_RED, outputPWM[n][0]); //
analogWrite(PWM_PIN_GREEN, outputPWM[n][1]); //
analogWrite(PWM_PIN_BLUE, outputPWM[n][2]); //
}
}; // end ColorMatcher class
ColorMatcher colorMatcher; // Create colorMatcher object
void reportangles() {
Serial.print("Servo_1: "); Serial.println(zeropos[0]);
Serial.print("Servo_2: "); Serial.println(zeropos[1]);
Serial.print("Servo_3: "); Serial.println(zeropos[2]);
}
void twist_action(bool half, bool cw) {
int n, k;
if (half)
{
n = 1;
}
else
{
n = 2;
}
if (cw)
{
k = 1;
}
else
{
k = -1;
}
for (int i = 0; i < n * waist_angle; i++)
{
Servo_2.write(zeropos[1] + k * i);
delay(T1DEG);
}
zeropos[1] = zeropos[1] + k * n * waist_angle;
reportangles();
}
void step_action(bool half, bool right) {
int n, k;
if (half)
{
n = 1;
}
else
{
n = 2;
}
if (right)
{
k = 1;
}
else
{
k = -1;
}
for (int i = 0; i < n * step_angle; i++)
{
Servo_1.write(zeropos[0] + k * i);
Servo_3.write(zeropos[2] - k * i);
delay(T1DEG);
};
zeropos[0] = zeropos[0] + k * n * step_angle;
zeropos[2] = zeropos[2] - k * n * step_angle;
reportangles();
}
void crawlForward()
{
twist_action(HALF, CW);
step_action(HALF, RIGHT);
twist_action(FULL, CCW);
step_action(FULL, LEFT);
twist_action(FULL, CW);
step_action(FULL, RIGHT);
twist_action(HALF, CCW);
step_action(HALF, LEFT);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Begin Serial");
if (tcs.begin()) {
Serial.println("Ready");
} else {
Serial.println("No TCS34725 found ... check your connections");
while (1);
}
//Servo_1.attach(4); // Uncommenting this line causes RGB LEDs on pin 9 (PWM) to not illuminate
// DC voltage on pin 9 is 3.4V when this is commented out;
// when uncommented, voltage drops to 2.1V
//Servo_2.attach(3);
//Servo_3.attach(2);
//Servo_1.write(zeropos[0]);
//Servo_2.write(zeropos[1]);
//Servo_3.write(zeropos[2]);
//Serial.println("Finished setup");
//reportangles();
//delay(1000);
}
void loop() {
// put your main code here, to run repeatedly:
//crawlForward();
//delay(100);
colorMatcher.Update();
delay(100);
}
[/code]
The RGB sensor SDA line is connected to pin A4 and SCL to A5.
If I leave line #186 commented out, then everything is fine; the voltage of pin 9 (red LED) is 3.4V. If I uncomment line #186 (Servo_1.attach(4);) the voltage drops to 2.1V and the LED won't illuminate. I have tried using an external power supply to put 5V on the VCC pin, but that seems to make no difference.
Here is a rough schematic:

Why would attaching a servo cause my RGB sensor/LED code to fail?
Thanks.
David
type or paste code here

