Now that fall semester is over and winter break has begun, I’m gonna start making more stuff! Building on to the color-crossfading ping pong ball, I decided to use the 38kHz infrared receiver module and keychain remote I bought awhile ago to make it remote-controlled. Each button on the remote corresponds to a color, except the power button which turns it off.
It’s a modified version of this RGB LED crossfader program combined with the sample code provided in the keychain remote item page.
#define RED_PIN 11 #define GRN_PIN 10 #define BLU_PIN 9 #define IR_PIN 17 /* The next two defines are only here because I'm too lazy to wire up the IR receiver module to power and ground, so I just stuck all three pins into the analog input pins and used digitalWrite() to set one to high and one to low */ #define IR_GROUND 18 #define IR_POWER 19 #define START_BIT 2200 //Start bit threshold (Microseconds) #define BIN0_THRES 400 //Binary 0 threshold (Microseconds) #define BIN1_THRES 1000 //Binary 1 threshold (Microseconds) boolean commonAnode = false; // Color arrays int black[3] = {0,0,0}; int white[3] = {255,255,255}; int red[3] = {255,0,0}; int orange[3] = {255,128,0}; int yellow[3] = {255,255,0}; int green1[3] = {128,255,0}; int green2[3] = {0,255,0}; int green3[3] = {0,255,128}; int cyan[3] = {0,255,255}; int blue1[3] = {0,128,255}; int blue2[3] = {0,0,255}; int purple[3] = {128,0,255}; int pink[3] = {255,0,255}; int magenta[3] = {255,0,128}; // Set initial color int redVal = black[0]; int grnVal = black[1]; int bluVal = black[2]; int wait = 1; // internal crossFade delay; increase for slower fades // Initialize color variables int prevR = redVal; int prevG = grnVal; int prevB = bluVal; boolean freeFade = true; // Set up the LED outputs void setup() { pinMode(RED_PIN, OUTPUT); // sets the pins as output pinMode(GRN_PIN, OUTPUT); pinMode(BLU_PIN, OUTPUT); pinMode(IR_PIN, INPUT); pinMode(IR_GROUND, OUTPUT); pinMode(IR_POWER, OUTPUT); digitalWrite(IR_GROUND, LOW); digitalWrite(IR_POWER, HIGH); Serial.begin(9600); crossFade(white); } // Main program: list the order of crossfades void loop() { checkIR(); if (0) { // Set to 1 for regular fading, comment out previous line crossFade(red); crossFade(orange); crossFade(yellow); crossFade(green1); crossFade(green2); crossFade(green3); crossFade(cyan); crossFade(blue1); crossFade(blue2); crossFade(purple); crossFade(pink); crossFade(magenta); } } /* To figure out how big a step there should be between one up- or * down-tick of one of the LED values, we call calculateStep(), * which calculates the absolute gap between the start and end values, * and then divides that gap by 1020 to determine the size of the step * between adjustments in the value. */ int calculateStep(int prevValue, int endValue) { int step = endValue - prevValue; // What's the overall gap? if (step) { // If its non-zero, step = 1020/step; // divide by 1020 } return step; } /* The next function is calculateVal. When the loop value, i, * reaches the step size appropriate for one of the * colors, it increases or decreases the value of that color by 1. * (R, G, and B are each calculated separately.) */ int calculateVal(int step, int val, int i) { if ((step) && i % step == 0) { // If step is non-zero and its time to change a value, if (step > 0) { // increment the value if step is positive... val += 1; } else if (step 255) { val = 255; } else if (val < 0) { val = 0; } return val; } /* changeColor() instantly changes the color, no fading*/ void changeColor(int color[3]) { redVal = color[0]; grnVal = color[1]; bluVal = color[2]; if (commonAnode) { analogWrite(RED_PIN, redVal); // Write current values to LED pins analogWrite(GRN_PIN, grnVal); analogWrite(BLU_PIN, bluVal); } else { analogWrite(RED_PIN, 255-redVal); // Write current values to LED pins analogWrite(GRN_PIN, 255-grnVal); analogWrite(BLU_PIN, 255-bluVal); } } /* crossFade() converts the percentage colors to a * 0-255 range, then loops 1020 times, checking to see if * the value needs to be updated each time, then writing * the color values to the correct pins. */ void crossFade(int color[3]) { // Convert to 0-255 int R = color[0]; int G = color[1]; int B = color[2]; int stepR = calculateStep(prevR, R); int stepG = calculateStep(prevG, G); int stepB = calculateStep(prevB, B); for (int i = 0; i <= 1020; i++) { redVal = calculateVal(stepR, redVal, i); grnVal = calculateVal(stepG, grnVal, i); bluVal = calculateVal(stepB, bluVal, i); if (commonAnode) { analogWrite(RED_PIN, redVal); // Write current values to LED pins analogWrite(GRN_PIN, grnVal); analogWrite(BLU_PIN, bluVal); } else { analogWrite(RED_PIN, 255-redVal); // Write current values to LED pins analogWrite(GRN_PIN, 255-grnVal); analogWrite(BLU_PIN, 255-bluVal); } delay(wait); // Pause for 'wait' milliseconds before resuming the loop } // Update current values for next loop prevR = redVal; prevG = grnVal; prevB = bluVal; } // Begin Infrared stuff void checkIR() { int key = getIRKey(); //Fetch the key if (key != 0) { //Ignore keys that are zero switch(key) { case 149: // Power changeColor(black); break; case 144: // CH Up crossFade(red); break; case 145: // CH Down crossFade(orange); break; case 148: // Mute crossFade(yellow); break; case 146: // VOL Right crossFade(blue2); break; case 147: // VOL Left crossFade(green2); break; case 165: // AV/TV crossFade(pink); break; } } } int getIRKey() { int data[12]; int i; while(pulseIn(IR_PIN, LOW) < START_BIT); //Wait for a start bit for(i = 0 ; i < 11 ; i++) data[i] = pulseIn(IR_PIN, LOW); //Start measuring bits, I only want low pulses for(i = 0 ; i BIN1_THRES) //is it a 1? data[i] = 1; else if(data[i] > BIN0_THRES) //is it a 0? data[i] = 0; else return -1; //Flag the data as invalid; I don't know what it is! Return -1 on invalid data } int result = 0; for(i = 0 ; i < 11 ; i++) //Convert data bits to integer if(data[i] == 1) result |= (1<<i); return result; //Return key number }
Cool 😀
Imagine a ping pong ball lightshow with multiple balls
LikeLike