// simple project using Arduino UNO, NeoPixel ring and Rotary Encoder to fill the ring with colors
// created by upir, 2024
// youtube channel: https://www.youtube.com/upir_upir
// YOUTUBE VIDEO: https://youtu.be/JK3KePYrkYY
// Source Files: https://github.com/upiir/arduino_neopixel_rings
// Links from the video:
// Wokwi starting sketch: https://wokwi.com/projects/374907938100932609
// Adafruit NeoPixel guide: https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-use
// NeoPixel ring(s): https://s.click.aliexpress.com/e/_DdIyIgl
// Rotary Encoder Module: https://s.click.aliexpress.com/e/_DETznkv
// Solid Aluminium Knob: https://s.click.aliexpress.com/e/_DFPuloh
// Breadboard wires: https://s.click.aliexpress.com/e/_Dkbngin
// Arduino UNO R3: https://s.click.aliexpress.com/e/_AXDw1h
// Arduino breadboard prototyping shield: https://s.click.aliexpress.com/e/_DlxEfPX
// Related videos:
// Pimp My Potentiometer! - https://youtu.be/tHL4RYGSvg4
// Pimp My Potentiometer (again) - https://youtu.be/sE3LSYoCqLQ
// Pimp my Potentiometer -CHEAPER- - https://youtu.be/Bot865qmdsM
// Your 1st CNC-ed Part - https://youtu.be/EB8PISr4m4g
// My First CNCed part --EVER-- - https://youtu.be/e2UNsZPjHkk
// My First PCB --EVER-- - https://youtu.be/6cqvTHCuDto
// DIY Volume Control - https://youtu.be/jvHRfsgw4l8
// Knob over OLED Display - https://youtu.be/SmbcNx7tbX8
#include <Adafruit_NeoPixel.h> // library for NeoPixels
#include <Encoder.h> // library for rotary encoder
#define PIN_NEO_PIXEL 6 // Arduino pin that connects to NeoPixel
#define NUM_PIXELS 16 // The number of LEDs (pixels) on NeoPixel
#define ENCODER_BTN 4 // rotary encoder button pin
Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800); // set the NeoPixel ring initialization
Encoder myEnc(2, 3); // initialize the rotary encoder
byte color_blue_RGB[3] = {0, 0, 255}; // blue color in RGB color space
byte color_red_RGB[3] = {255, 0, 0}; // red color in RGB color space
byte color_blend_RGB[3]; // variable to store blended RGB color
byte color_blue_HSV[3] = {170, 255, 255}; // blue color in HSV color space
byte color_red_HSV[3] = {0, 255, 255}; // red color in HSV color space
byte color_blend_HSV[3]; // variable to store blended HSV color
int encoder_value_old = 0; // previous value of rotary encoder
int encoder_value_new = 0; // current value of rotary encoder
int percentage_value = 50; // percentage value to fill the ring: 0 - 100%
int mode = 0; // 0 = white, 1 = blue to red RGB, 2 = blue to red HSV
// function to blend between two colors
void blend_colors (byte color_start[3], byte color_end[3], byte color_blended[3], float percentage /*0-100*/) {
for (int i = 0; i < 3; i ++) {
// linear interpolation between two values
color_blended[i] = round((float)color_start[i] + (((float)color_end[i] - (float)color_start[i]) * (percentage / 100.0)));
}
}
void setup() {
NeoPixel.begin(); // initialize the NeoPixel strip object
pinMode(ENCODER_BTN, INPUT_PULLUP); // set pin for rotary encoder button
}
void loop() {
// read the new value of rotary encoder
encoder_value_new = myEnc.read(); // read the encoder value
if (encoder_value_new != encoder_value_old) { // if the old value does not equal the new value
percentage_value = constrain(percentage_value - (encoder_value_new - encoder_value_old), 0, 100); // set the percentage value between 0-100%
encoder_value_old = encoder_value_new; // update the old encoder value
}
if (digitalRead(ENCODER_BTN) == LOW) {
// switch the mode
mode++;
if (mode > 2) {
mode = 0;
}
delay(500); // add a small delay
}
NeoPixel.clear(); // set all pixel colors to 'off'. It only takes effect if pixels.show() is called
// go over every single pixel on the neopixel ring
for (int pixel = 0; pixel < NUM_PIXELS; pixel++) { // for each pixel
if ((pixel * (100 / (NUM_PIXELS - 1))) < percentage_value) { // fill pixels based on the rotary encoder value
if (mode == 0) { // draw white pixels
// set pixels to WHITE color
NeoPixel.setPixelColor(pixel, NeoPixel.Color(255, 255, 255)); // set all pixels to white color
} else if (mode == 1) { // blend between blue and red in RGB
// blend two colors in RGB color space
blend_colors(color_blue_RGB, color_red_RGB, color_blend_RGB, pixel * (100.0 / (NUM_PIXELS - 1)));
// set the pixel to the blended color
NeoPixel.setPixelColor(pixel, NeoPixel.Color(color_blend_RGB[0], color_blend_RGB[1], color_blend_RGB[2]));
} else if (mode == 2) { // blend between blue and red in HSV
// blend two colors in HSV color space
blend_colors(color_blue_HSV, color_red_HSV, color_blend_HSV, pixel * (100.0 / (NUM_PIXELS - 1)));
// set the pixel to the blended color
NeoPixel.setPixelColor(pixel, NeoPixel.ColorHSV((unsigned int)color_blend_HSV[0] * 256, color_blend_HSV[1], color_blend_HSV[2]));
}
}
}
//NeoPixel.setBrightness(50); // don´t forget to uncomment this line for real Arduino to make it less bright
NeoPixel.show(); // show all the set pixels on neopixel ring
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
ring1:GND
ring1:VCC
ring1:DIN
ring1:DOUT
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND