Input 1 is a color sensor. The value of the color detected controls the brightness of an incandescent bulb. The thermistor reads changes in temperature from the incandescent bulb. The values of the thermistor change the angle of the servo motor.
Replacing the color sensor with a potentiometer as input one. The potentiometer controls the bulb brightness. The bulb brightness changes the temperature of the thermistor. The values of the thermistor change the direction of the servo motor as the output.
LCD display displaying color value, temperature, and motor angle
Servo motor and incandescent light bulb shown
Translucent light bulb with the thermistor
The potentiometer and arduino
Quick demo with close-ups of all components, along with showing different example color inputs.
Here we can see what happens when instead of using a color sensor, we use a potentiometer.
A small sensor can see different colors. When it sees a color, it makes a lightbulb shine brighter or dimmer. The lightbulb gets warmer or cooler, and this change makes a little arm turn to a new angle. If you press the middle button, the arm moves right away without waiting for the light or the heat to change.
Connecting the Ardiuno with the color sensor, indulescent light bulb and thermistor first
Soldering the breadbread that holds the indulescent light bulb and thermistor and trying to make it work in respect to the color sensor
Testing the color sensor and incandescent light bulb
Making sure the thermistor reads the temperature of the incandescent bulb
In our project, one of the biggest challenges was writing the code. The coding part was very difficult because one of us is more of a hardware person. We were not sure how to map three different RGB values from the color sensor to a single numerical value that could be used for the servo output, so we resorted to hard coding the colors red, orange, yellow, green, blue, and purple. In retrospect, this was a mistake. First, it was incredibly tedious hard coding all the different colors in code, and second, the end result did not come very smoothly. Instead of a range of values, the servo motor just jumped to hard coded angles.
For the other teammate, the whole process was difficult from both the coding and the hardware side because this was the first time coding or really building circuits. Not knowing where to start or how to fix the code when it was wrong was frustrating. There were many times where help was needed. For example, when looking for the right examples to follow for the code, it was important to ask which one was correct. Or when the hardware was not working, it felt like everything had been tried but nothing worked until help was asked for. From this part, some technical skills were learned like how to read through example code, connect sensors to the board, and use trial and error to find problems.
As a team, we learned that we can do hard things, even if it takes time and mistakes. Looking back, even a small change could have made the process go differently, for example if we had understood coding basics earlier or had a clearer plan for wiring. Still, the project helped us grow, and now we both know more about coding and hardware than we did before. Moving forward, we want to build on this growth by improving our coding skills and planning our projects more carefully from the beginning.
/*
Double Transducer: Color To Angle
Caden Yang & Danely Rodriguez
This code integrates a color sensor, a servo motor, an incandescent light bulb, a thermistor, and an LCD display to create a double transducer “color-to-angle” system. The color sensor detects the main color of incoming light and maps it to a brightness level that controls the bulb’s brightness. Then, either the detected color or the measured temperature determines the servo’s position. When the skip the midle button on pin 2 is pressed, the servo angle directly follows the color, but when the button is not pressed, the servo angle is instead set based on the temperature reading from the thermistor. The LCD shows real time information about the color intensity, mapped bulb brightness, measured temperature, and servo output angle.
Pin 9 (PWM): Servo Motor
Pin 2 (digital): Skip the middle button
Pin 3 (PWM): Incandescent Light Bulb
Color Sensor & LCD Display utilize I2C
*/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD at I2C address 0x27
#include <Servo.h>
Servo myServo;
int SERVOPIN = 9; // Servo pin
int buttonPin = 2; // Button pin
#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 apds; // Color sensor
// Thermistor configuration
#define THERMISTORPIN A0
#define THERMISTORNOMINAL 10000
#define TEMPERATURENOMINAL 25
#define NUMSAMPLES 5
#define BCOEFFICIENT 3977
#define SERIESRESISTOR 10000
int samples[NUMSAMPLES];
int BULBPIN = 3; // Bulb pin
bool buttonPressed = false;
// Convert RGB values to a 0–99 display range
int rgbToDisplayValue(uint16_t r, uint16_t g, uint16_t b) {
int avg = (r + g + b) / 3;
return map(avg, 0, 1023, 0, 99);
}
// Set bulb brightness
void lightBulb(int brightness) {
analogWrite(BULBPIN, brightness);
}
// Determine dominant color
int getColor(uint16_t r, uint16_t g, uint16_t b) {
if (r < 15 && g < 15 && b < 15) {
return -1; // too dark
}
else if (r > g && r > b) {
if (g < b) return 0; // red
else return 1; // orange
}
else if (g > r && g > b) {
if (r > b) return 2; // yellow-
else return 3; // green
}
else if (b > r && b > g) {
return 4; // blue
}
return 5; // purple
}
// Map color index to brightness
int getBrightnessFromColor(int colorIndex) {
if (colorIndex == -1) return 0;
else if (colorIndex == 0) return 26;
else if (colorIndex == 1) return 51;
else if (colorIndex == 2) return 77;
else if (colorIndex == 3) return 128;
else if (colorIndex == 4) return 179;
else if (colorIndex == 5) return 255;
return 0;
}
// Read temperature from thermistor
float readPrintTemp() {
//code taken from https://learn.adafruit.com/thermistor/using-a-thermistor
uint8_t i;
float average;
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(THERMISTORPIN);
delay(10);
}
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
float steinhart;
steinhart = average / THERMISTORNOMINAL;
steinhart = log(steinhart);
steinhart /= BCOEFFICIENT;
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15);
steinhart = 1.0 / steinhart;
steinhart -= 273.15;
return steinhart;
}
// Map temperature to servo angle
int setAngleFromTemp(float tempC) {
int angle = map(tempC, 30, 50, 0, 180);
angle = constrain(angle, 0, 180);
myServo.write(angle);
return angle;
}
// Update LCD
void displayInfo(int rgbVal, int bulbVal, int tempVal, int servVal) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("i:"); // intensity
lcd.print(rgbVal);
lcd.setCursor(6, 0);
lcd.print("m:"); // mapped bulb brightness
lcd.print(bulbVal);
lcd.setCursor(6, 1);
lcd.print(tempVal); // temperature
lcd.setCursor(12, 1);
lcd.print("o:"); // servo output
lcd.print(servVal);
}
void setup() {
Serial.begin(115200);
apds.begin();
apds.enableColor(true); // enable color sensor
pinMode(BULBPIN, OUTPUT);
myServo.attach(SERVOPIN);
lcd.init();
lcd.backlight();
lcd.home();
lcd.print("Hello World"); // startup message
delay(1000);
}
void loop() {
int buttonVal = digitalRead(2);
buttonPressed = (buttonVal != 0); // button pressed if HIGH
// Read RGB color values
uint16_t r, g, b, c;
apds.getColorData(&r, &g, &b, &c);
int rgbVal = rgbToDisplayValue(r, g, b);
int colorIndex = getColor(r, g, b);
int brightness = getBrightnessFromColor(colorIndex);
int bulbVal = map(brightness, 0, 255, 0, 99);
float tempC = readPrintTemp();
int tempVal = map((int)tempC, 0, 50, 0, 99);
int servAng;
if (buttonPressed) {
// Servo follows color
servAng = map(brightness, 0, 255, 0, 180);
servAng = constrain(servAng, 0, 180);
myServo.write(servAng);
lightBulb(brightness);
} else {
// Servo follows temperature
servAng = setAngleFromTemp(tempC);
lightBulb(brightness);
}
int servVal = map(servAng, 0, 180, 0, 99);
displayInfo(rgbVal, bulbVal, tempVal, servVal);
delay(300);
}