Silvia's Lightometer
Silvia's Lightometer
What I wanted to learn, and why it interested me: I wanted to experiment with more LEDs because I was inspired by the projects in the first project that utilized NeoPixel LEDs to create various effects. I was particularly interested in learning more about how to change the design of the LEDs, including pattern, color, and brightness, especially since the single LED I used in Project 1 had some limitations in this regard. I'm really just interested in the pretty lights!
Final outcome: I was pleased with the amount of customization there was when it came to the LED ring. They were a lot brighter than I expected. For the technical training sequence, I played around with different patterns such as a rainbow spectrum, a theater chase, and a color wipe, all along the ring of the 16-bit NeoPixel Ring, and I really enjoyed the wide range of colors it offered. For the creative/exploratory part, I wanted to include a potentiometer and find a creative way to show the input of it on the LED. The shape of the ring inspired me to go with a potentiometer because it had a similar shape to the motion of the potentiometer. I designed the lighting pattern like a gauge, where it would start with only one bit on the NeoPixel, but as you turn the potentiometer, more bits start to light up. I paired this with visual effects in the lighting, such as starting from cool colors (purple, blue), to warmer colors as the potentiometer is turned (yellow, red). I also included a continuous wipe effect to the colors so that as you turned the potentiometer, the wipe would get faster. I wanted to create the feeling that you were turning something up, making something hotter, or faster, as you turned the input, and add personality to the interaction.
Images of final creative/exploratory output
Final image of the lightometer
A picture of a 16-bit NeoPixel LED ring with wires, an Arduino Uno, and a white breadboard with a potentiometer wired up. There are 9/16 LED bits lit up in a blue hue.
Final video of the lightometer
A video of a 16-bit NeoPixel LED ring with wires, an Arduino Uno, and a white breadboard with a potentiometer wired up. As a hand turns the potentiometer from 0, the LED bits on the NeoPixel ring light up accordingly, changing color and speed from cool tone and slow to warm tone and fast, and vice versa.
Process images from development towards creative/exploratory output
My first attempt at soldering the LED ring :')
An image of a burnt NeoPixel Ring and wires thrown out.
Adding a 330 Ω resistor to the LED ring wiring.
A close-up image of a 330 Ω resistor and wires in a white breadboard.
Wiring up the potentiometer
A close-up image of a potentiometer and wires in a white breadboard.
Refining the lighting effects
An image of a NeoPixel ring fully lit up red, with an Arduino Uno, white breadboard, and wires in the background.
Process and reflection:
My process started off with soldering the wires to the NeoPixel ring. I learned about DI, DO, GND, and 5V on the LED, and making sure to carefully solder in the small holes. This was easier to do than soldering the protoboards in project 1 because the holes were more spaced apart, but my first attempt was unsuccessful, as the LEDs weren't working because I believe I fried one of the holes. After the second attempt, I finally got it to work. I added a 330 Ω for the LED just in case, as well as wired up the potentiometer. That was it for the wiring, and it ended up being really simple. As I started to choose the light pattern as I turn the potentiometer, I wanted to create something that gave the user the feeling of changing something drastically, and wanted to focus on those feelings as they turn the potentiometer. I was inspired by those gauges in cartoons that get really red and look like they're going to explode when they're turned up all the way. Initially, I made the rainbow spectrum move faster as the potentiometer was turned, but I wanted to utilize cool and warm colors to represent the potentiometer's inputs, while still incorporating the speed and brightness of the light animation to convey a sense of urgency. Overall, I'm happy with the way it turned out, and I'm excited to play with more LEDs in the future.
Technical details
Electrical Schematic
5V and GND were wired from the Arduino Uno to the power and GND rails on the white breadboard, where all of the power/GND wires were plugged in.
/*
60-223 Intro to Physical Computing, fall 2025
Domain-specific Skill Building exercise: Lightometer
This sketch drives a 16-LED NeoPixel ring from an Arduino, with a potentiometer on analog pin A0 as the
control. As you twist the knob, the number of LEDs that light up increases from one to all sixteen. When the
knob is low, only a few LEDs glow in cool tones (blue, purple) that shift slowly at a moderate brightness. As
you turn the knob higher, more LEDs are lit, and the colors change to warm tones (deep red/orange). At the same
time, the animation speeds up and the brightness increases, so the ring looks more intense.
Pin mapping:
Arduino pin | role | details
------------------------------
A0 input potentiometer
6 output 16-bit NeoPixel LED ring
Released to the public domain by the author, September 2025
Silvia Shin, seshin@andrew.cmu.edu
*/
#include <PololuLedStrip.h>
const uint8_t DATA_PIN = 6;
const uint16_t NUMLEDS = 16;
const uint8_t POT_PIN = A0;
PololuLedStrip<DATA_PIN> ledStrip;
rgb_color colors[NUMLEDS];
// customize the brightness/speed
const uint8_t MIN_BRIGHT = 70;
const uint8_t MAX_BRIGHT = 255;
const uint8_t MIN_SPEED = 1;
const uint8_t MAX_SPEED = 8;
// cool colors
const uint8_t COOL_HUE_START = 120; // blue
const uint8_t COOL_HUE_END = 210; // purple
// warm colors
const uint8_t WARM_HUE_START = 0; // red
const uint8_t WARM_HUE_END = 8; // redder
// provided by chatgpt
static inline rgb_color hsv(uint8_t h, uint8_t s, uint8_t v) {
if (s == 0) return rgb_color(v, v, v);
uint8_t region = h / 43;
uint8_t remainder = (h - (region * 43)) * 6;
uint16_t p = (uint16_t)v * (255 - s) / 255;
uint16_t q = (uint16_t)v * (255 - ((uint16_t)s * remainder) / 255) / 255;
uint16_t t = (uint16_t)v * (255 - ((uint16_t)s * (255 - remainder)) / 255) / 255;
switch (region) {
default:
case 0: return rgb_color(v, t, p);
case 1: return rgb_color(q, v, p);
case 2: return rgb_color(p, v, t);
case 3: return rgb_color(p, q, v);
case 4: return rgb_color(t, p, v);
case 5: return rgb_color(v, p, q);
}
}
// scale RGB by brightness
static inline rgb_color scale(rgb_color c, uint8_t b) {
uint16_t B = b;
return rgb_color((uint8_t)((c.red * B) / 255),
(uint8_t)((c.green * B) / 255),
(uint8_t)((c.blue * B) / 255));
}
static inline uint8_t lerp8(uint8_t a, uint8_t b, uint8_t f) {
return a + ((uint16_t)(b - a) * f) / 255;
}
void setup() { }
void loop() {
// read potentiometer
static float smoothed = 0;
int raw = analogRead(POT_PIN);
smoothed = 0.85f * smoothed + 0.15f * raw;
int s = (int)(smoothed + 0.5f);
s = constrain(s, 0, 1023);
// max turns on all LEDs
uint16_t litCount = (uint16_t)(((uint32_t)s * NUMLEDS + 1023) / 1023);
if (litCount > NUMLEDS) litCount = NUMLEDS;
// fraction of LEDs lit for scaling speed/brightness
float fracF = (NUMLEDS ? (float)litCount / (float)NUMLEDS : 0.0f);
uint8_t frac8 = (uint8_t)(fracF * 255.0f + 0.5f);
// adaptive speed & brightness
uint8_t speed = (uint8_t)(MIN_SPEED + (uint16_t)(MAX_SPEED - MIN_SPEED) * frac8 / 255);
uint8_t brightness = (uint8_t)(MIN_BRIGHT + (uint16_t)(MAX_BRIGHT - MIN_BRIGHT) * frac8 / 255);
uint8_t bandStart = lerp8(COOL_HUE_START, WARM_HUE_START, frac8);
uint8_t bandEnd = lerp8(COOL_HUE_END, WARM_HUE_END, frac8);
if (bandEnd < bandStart) {
uint8_t tmp = bandEnd;
bandEnd = bandStart;
bandStart = tmp;
}
uint8_t bandSpan = bandEnd - bandStart;
if (bandSpan == 0) bandSpan = 1;
// faster when more LEDs are lit
static uint16_t phase = 0;
phase += speed; // wraps naturally
for (uint16_t i = 0; i < NUMLEDS; i++) {
if (litCount == 0 || i >= litCount) {
colors[i] = rgb_color(0,0,0);
continue;
}
uint8_t idx = (uint8_t)((i * 256UL / litCount + (phase & 0xFF)) & 0xFF);
uint8_t hueInBand = bandStart + ((uint16_t)idx * bandSpan) / 255;
rgb_color c = hsv(hueInBand, 255, 255);
colors[i] = scale(c, brightness);
}
ledStrip.write(colors, NUMLEDS);
delay(8); // responsiveness vs CPU
}