Introduction: Sensing Light - Determining Exact RGBW Values

About: Student interested in electrical engineering and robotics

Light is emitted in various colors based on the wavelength of the light. Each wavelength has a corresponding frequency, where c(speed of light) = (Frequency) * (Wavelength). Using a TAOS230 Programmable Color Light-to-Frequency Convertor (and later the TAOS3200), the colors of light were converted into their corresponding frequencies. A frequency value of red, green, blue, and clear light is read by an ATMEGA328 microcontroller that uses an Arduino code to convert the values of red, green, blue, and clear to a number between 0 and 255 and display it to an attached LCD (Liquid Crystal Display). The value can then easily be reproduced with an RGB (red, green, blue) LED (light emitting diode). Any light can be analyzed with the device, but a Neopixel (an RGB LED) is built on the board. The Neopixel is controlled by three slide potentiometers that change the red, green, and blue values of the Neopixel. Students can use the device, dubbed the Donatello during a lab to understand the perception of light


  • Arduino Uno (or any similar)
  • TCS3200D-TR (1)
  • Standard LCD 16x2 with contrast potentiometer (1)
  • ATMega328 (1)
  • SparkFun AVR Pocket Programmer
  • NeoPixel (at least 1)
  • Slide potentiometers (3)
  • 330 ohm resistor (2)
  • 220 ohm resistor (1)
  • Mini Pushbutton Switch (1)
  • Breadboard (2)
  • 5v power supply (either computer or external)
  • USB to mini and micro
  • Wires, assorted


  • Basic green LED (1)
  • 0.1 uF Ceramic Capacitor (2)
  • 1000uF Electrolytic Capacitor (1)

Step 1: Lighting the Neopixel

The Adafruit Neopixel with a Trinket5v. The Neopixel needed a wire soldered to each of the 5v, ground, and Din (data in) surfaces. The color of the Neopixel changes based on the Arduino code uploaded to the Neopixel via the Trinket. Using a breadboard to easily move wires around, the 5v of the Trinket was attached to the 5v of the Neopixel, the GND to GND, and used a 300-ohm resistor to attach the #0 digital pin of the Trinket to the Din (digital input) of the Neopixel. A 1000-microfarad electrolytic capacitor was attached between the positive and negative terminals to prevent a burnout of the Neopixel. The “Adafruit_Neopixel” Arduino library is necessary to light up the Neopixel. The “strandtest” program was able to successfully light up an array of colors on the Neopixel.

To send an analog signal of the color to the Neopixel, three 5000-ohm slide potentiometers were added, attaching the 3 pin to 5v, the 2 pin to analog inputs 2, 3, and 4 respectively on the Trinket, and the 1 pin to GND.

The code (download below) enables the potentiometers to change the color of the Neopixel. The code varies the resistance, changing the intensity of the colors red, green, and blue. However, the library code as written did not allow more than one potentiometer to be used at once. Adjusting a second one caused the Neopixel to flicker through both colors briefly before turning off.

The slide potentiometers are not breadboard friendly. The potentiometers could not fit into the breadboard because there was metal that would prop up the potentiometers, not allowing the pins to go into the board. Soldering headers to the pins attempted to solve the problem. However, when slid, the Neopixel would flicker, signaling that there was not a secure connection to the potentiometers. The pins also broke off no matter how well soldered. Instead, using pliers, the metal that was in the way of properly securing the potentiometer in the breadboard was bent out of the way. With a little brute force, the potentiometers were almost always secure once pushed into the breadboard. There still is occasional flickering, but the Donatello could be tested and used.

Step 2: Receiving RGBW Values

Since the three potentiometers and the Neopixel took up all the pins on the Trinket, all future prototyping was done with an Arduino Leonardo or an Arduino Uno. Both can be used interchangeably. The Neopixel Din pin was changed to digital pin 11. The red potentiometer was changed to A2 (analog pin 2). The green potentiometer was changed to A1. The blue potentiometer was changed to A0.

A TAOS230 Programmable Color Light-to-Frequency Convertor was soldered to a PCB from the ELEN 4193 lab that would allow easy manipulation of the unit on a breadboard. The ELEN 4193 Perception lab had a breakout board that allowed the light sensor pins to go straight into an Arduino board. Six header pins were soldered to the breakout board’s pins D2-D7. The VDD (power, 5v) and ground pins were separately spaced and corresponded to pins D9 and D8 respectively. D2 is the OUT (output) pin, D3 is the S2 pin, D4 is the S3 pin, D5 is the S0 pin, D6 is the S1 pin, and D7 is the OE pin. S0 is connected to digital pin 0. S1 is connected to digital pin 1. S2 is connected to digital pin 3. S3 is connected to digital pin 10. OE is connected to ground. The OUT pin is connected to digital pin 5, which is the 16-bit counter on the microcontroller (See Appendix F).

The light sensor is made of an 8x8 array of photodiodes. Each filtered sensor, red, green, blue, and clear/white, use a quarter of the photodiodes to detect light color. Pins S2 and S3 are attached to the photodiode array and pins S0 and S1 are attached to the current-to-frequency converter. Color is based on low or high readings from S2 and S3. When S2 and S3 are low, the sensor detects using the red photodiode. When S2 and S3 are high, the sensor detects using the green photodiode. When S2 is low and S3 is high, the sensor detects using the blue photodiode. When S2 is high and S3 is low, the sensor detects using the clear/white photodiode. Similarly, the output frequency is determined based on whether S0 and S1 are low or high.

Since the light sensor is programmable, the Arduino code can set the high and low values for the pins so that the user can match the frequency value and light color. The light sensor code was created consulting Arduino open-source forums as a guide. All frequencies are read next to their corresponding light color (red, blue, green, or white/clear) on the serial monitor in the Arduino application. The first code read the light sensor frequencies without converting it to the 0-255 scale. After adding some mathematical functions (the code was overwritten and no record of it currently exists) to divide the average frequencies (it was in the 20,000s) to attempt to scale it down, the numbers were between 220 and 256.

After discovering that one of the pins was unplugged, the value of the colors was between 0 and 255, but lower numbers were higher (The opposite of what was standard). After subtracting those values from 255, the code produced numbers much higher than 255 for no discernable reason.

The Arduino Liquid Crystal Display guide guided the entire LCD setup. The parts used were a 16x2 LCD screen with backlight, a 10k ohm “knob” potentiometer, and a 220-ohm resistor. The potentiometer was connected in between with its output on V0 or the third pin on the LCD to adjust the contrast of the backlight. The 220-ohm resistor is attached to the fifteenth pin on the LCD or the LED+ to provide the proper current to the backlight. The LCD was added using its sixteen-pin header to the breadboard prototype. The RS or reset pin was attached to digital pin 4, the EN pin was attached to digital pin 2, the D4 pin was attached to digital pin 6, the D5 pin was attached to digital pin 7, the D6 pin was attached to digital pin 8, and the D7 pin was attached to digital pin 9. All digital pins are located on the microcontroller and correspond to the number used to represent the pin in the code. The “LiquidCrystal” Arduino library is necessary to use the LCD. Displaying “Hello World” on screen with an example code that is built into Arduino tested the LCD.

Step 3: Combining

Both the NeoPixel Circuit and Light Sensor Circuit were combined with the same microcontroller.

The code automatically “white-balances” the light sensor by creating a scale factor for the RGBW values. The other codes were combined to create a single code that controls all function. The scale-factor is automatically created from the first light exposed to the light sensor after applying power. For the purpose of the project, the microcontroller automatically sets the Neopixel turn white/clear (RGB value (255, 255, 255)) before sending signals to the light sensor to “white-balance.” The Neopixel is placed right next to the light sensor for this use. After testing the code with the serial monitor, the RGBW values are reasonable. A button was added between the reset on the microcontroller and ground to manually reset the “white-balance.” It is necessary to reset the “white-balance” every time the position of the light sensor or light changes. The change in position changes the intensity of the light. The light sensor presumes these changes mean a change in light color and alter the values. To ensure accuracy, the “white-balance” reset button must be pressed.

The code was changed from outputting the RGBW values on the serial monitor to the LCD (see Appendix B). Red is printed as “R:XXX.XX” at position (0, 0). Green is printed as “G:XXX.XX” at position (0,1). Blue is printed as “B:XXX.XX” at position (8,0). White/clear is printed as “W:XXX.XX” at position (8,1). “XXX.XX” represents the value of the light color.

Step 4: Aesthetics and Removing Arduino

In order to cut costs of a final board, the Arduino Leonardo was swapped out for an ATMEGA328 microcontroller. The microcontroller needs a bootloader burned from Arduino or the code cannot be uploaded. The “Arduino/Genuino Uno” board can be bootloaded or a custom board can be downloaded from Arduino forums for an “ATMega328 on a breadboard (8 MHz internal clock)” board. Our project used the latter. The microcontroller is programmed using an AVR Pocket Programmer. A USB mini cord connects to the AVR Pocket Programmer, which connects to an ISP breakout board, which connects to the MOSI, Reset, SCK, MISO, 5v, and GND pins on the microcontroller. The microcontroller was wired up to the same pins as it was on the Leonardo.

The potentiometers were taken off the breadboard and put between empty space between the positive terminals and the breadboard with pin 3 of the potentiometers hooked up the positive terminal, saving space on the breadboard. The potentiometers are easily manipulated without any connection issues.

A decoupling (ceramic) capacitor of 0.1 microfarads was added at the closest point possible to the 5v and GND of the ISP breakout board (and later to the DC power jack) to prevent voltage spikes. Voltage spikes can occur when the power is connected and may burn out the parts. An LED was wired up with a 330 ohm resistor between 5v and GND to notify the user as to whether the device is running.

Step 5: Creating Custom PCB

Above a block diagram and schematic shows the inner workings of the connections and functions.

A schematic and board design for the custom PCB using the application Eagle (See Appendix C and Appendix H). The design uses a ATMEGA328 microcontroller to control the TSL230, LCD, and Neopixel. The 3.3v output of the Arduino Leonardo was tested with the prototype. However, all the devices did not have enough power to run correctly on 3.3v so the use of a battery to power the board was scrapped. Originally a 3 volt battery would power the board, but all the equipment required five volts, so a DC power jack at supplying five volts will power the entire board. Six ISP pins are on the board so that the microcontroller can be programmed once and then powered solely from a DC power jack. The AVR pocket programmer is used to burn the code to the flash memory found in the microcontroller.

When making the parts list, it was discovered that the TAOS230 Programmable Color Light-to-Frequency Convertor was discontinued. Instead a TAOS3200D-TR light sensor (1) will be used. The rest of the items needed to make the Donatello are (1) 1000uF/6.3V Electrolytic Capacitor, (1) Standard LCD 16x2 with contrast potentiometer, (1) ATMega328P-AU, (1) Basic Green LED, (3) slide potentiometers, (2) NeoPixel 5050 RGB LED with Integrated Driver Chip, (2) 0.1uF Ceramic Capacitor, (2) 330-ohm resistor, (1) 220-ohm resistor, and (1) Mini Pushbutton switch (See Appendix A).

Step 6: Testing Device

Due to external light, error persisted, but the overall color was still the strongest.

Microcontroller Contest 2017

Participated in the
Microcontroller Contest 2017