////////////////////// MOTOR ////////////////////// #define EN 8 //Negative Enable pin #define X_DIR 5 //Direction pin , of 5 of 6 #define X_STP 2 //Step pin #define pin_END 12 //End stop of motor //How many steps away from the "total open" state is the total closed state const long closed_position = 62000; //The total open state (which I'll set to be 0 steps) const long open_position = 0; //Important variable that will keep track of how many steps the hex plateau is actually away from the "total open" state long total_steps = 0; //End stop sensor value, 1 = open, 0 = closed int value_END = 1; //These two will keep track if the lamp is fully opened or full closed at any point int flower_full_open = false; int flower_full_close = false; //Motor const int delayTime = 50; //Delay between each pause (uS) //versnellen en langzamer laten lopen const int stps = 6400;// Steps to move microsteps 1/32 (200*32 = 6400) //Will be set to true at the start of the program, to make the lamp move up until it reaches the end stop //and thereby I can set the total_steps to 0 at that point bool first_activate; ////////////////////// NEOPIXELS ////////////////////// #include #define pin_NEO 13 #define ledCount 60 Adafruit_NeoPixel strip = Adafruit_NeoPixel(ledCount, pin_NEO, NEO_GRB + NEO_KHZ800); int oldR[ledCount]; int oldG[ledCount]; int oldB[ledCount]; int newR[ledCount]; int newG[ledCount]; int newB[ledCount]; uint32_t currentColor[ledCount]; //Keeps track of the current color of each NeoPixel const int nmax = 255; //Max number of steps for the twinkling //Keep track of which light state is currently active //Not really used in the end int current_light = 0; //0 - none //1 - hexLights //2 - blueFlower //3 - pinkSparkles //Used for the fade in and fade out int fade_counter = 0; int fade_amount = 5; ////////////////////// EL WIRE ////////////////////// #define pin_WIRE 2 bool wire_on = false; //////////////////////// LDR //////////////////////// #define pin_PHOTO A0 int sensor_value; ///////////////////// PROGRAMS ////////////////////// void setup(){ //Be able to print statements - only use for testing Serial.begin(9600); //Motor pinMode(X_DIR, OUTPUT); //direction pin = output pinMode(X_STP, OUTPUT); //step pin = output pinMode(EN, OUTPUT); //negative enable pin = output digitalWrite(EN, LOW); //start negative enable pin at low //EndStop pinMode(pin_END, INPUT); //Neopixels strip.begin(); //strip.setBrightness(10); //Set the overall brightness 0 - 255 strip.show(); // Initialize all pixels to 'off' randomSeed(analogRead(0)); //EXTRA RANDOMNESS!!!!! //Photo sensor pinMode(pin_PHOTO, INPUT); //EL Wire pinMode(pin_WIRE, OUTPUT); //Set the EL Wire to on digitalWrite(pin_WIRE, LOW); //on //Wait a bit for the relay to respond and get enough power delay(100); first_activate = true; }//void setup void loop(){ //Get value from the end stop value_END = digitalRead(pin_END); //0 = activated // Serial.print("End stop: "); // Serial.println(value_END); //Get value from LDR (light sensor) sensor_value = analogRead(pin_PHOTO); // Serial.print("Photo value: "); // Serial.println(sensor_value); //base ±550, dark ±600, light ±900 //////// CONDITIONALA TO CHECK WHICH LAMP STATE TO RUN //////// if(first_activate == true) { //Serial.println("first open"); //Open the lamp openLamp(); //Show colorful hex pattern hexLights(); } else if(sensor_value < 700 && flower_full_open == false) { //open //Serial.println("rise"); flower_full_close = false; //In case it was fully closed, make sure to set it to false lampStateRise(); } else if(sensor_value > 800 && flower_full_close == false) { //close //Serial.println("close"); flower_full_open = false; //In case it was fully opened, make sure to set it to false lampStateClose(); } else { //Serial.println("else"); }//else // Serial.print("Steps: "); // Serial.println(total_steps); //////// FUNCTIONS TO CHECK IF FULL OPEN OR CLOSED IS REACHED FOR THE FIRST TIME //////// //If the end stop is reached, the lamp is fully opened //Therefore, set some variables if(value_END == 0) { //Set total_steps to be 0 at this point total_steps = 0; flower_full_open = true; first_activate = false; //To be sure, set the fade_counter to fully on, so it can count down again for a NeoPixel fade out later fade_counter = 255; //Move the lamp down a bit so it doesn't interfere with the end stop anymore for(int i = 0; i < 10; i++) { closeLamp(); }//for i Serial.println("Lamp full open"); } else if(total_steps >= closed_position && flower_full_close == false) { //If the total_steps becomes equal or bigger to what I've set the closed_position to be //and the flower_full_close is still set to false (meaning that this is the first time that `total_steps >= closed_position` //set some variables flower_full_close = true; //To be sure, reset the fade counter so the NeoPixels can fade in again from scratch fade_counter = 0; Serial.println("Lamp full close"); }//if //////// FUNCTIONS TO RUN WHEN THE LAMP IF FULLY OPEN OR CLOSED //////// if(flower_full_open == true) { //Continuously run this on open lamp pinkSparkles(); }//if if(flower_full_close == true) { //Turn the lamp off if it's fully closed lampOff(); }//if }//void loop //////////////////////// CLOSE THE LAMP //////////////////////// void lampStateClose() { //Turn on the EL wire // if(wire_on == false) { // digitalWrite(pin_WIRE, LOW); //on // wire_on = true; // delay(10); // }//if //Close the lamp with the motor closeLamp(); //After a while, fade out the Neopixels //Otherwise show the blueFlower if(total_steps > 35000) { //Fade out the lamp fadeOut(-10); } else if(total_steps <= 35000) { blueFlower(); }//else if }//void lampStateClose //////////////////////// OPEN THE LAMP //////////////////////// void lampStateRise() { // Turn on the EL wire // if(wire_on == false) { // digitalWrite(pin_WIRE, LOW); //on // wire_on = true; // delay(100); // }//if //Open the lamp with the motor openLamp(); //After a while, fade in the NeoPixels //Before that, keep them off so you see only the EL Wire if(total_steps > 40000) { lampOff(); } else if(total_steps <= 40000) { fadeIn(255, 255, 0, 5); }//else if }//void lampStateRise /////////////////////////////////////////////////////// //////////////////////// MOTOR //////////////////////// /////////////////////////////////////////////////////// void step(boolean dir, byte dirPin, byte stepperPin, int steps) { digitalWrite(dirPin, dir); // for (int i = 0; i < steps; i++) { digitalWrite(stepperPin, HIGH); delayMicroseconds(delayTime); digitalWrite(stepperPin, LOW); delayMicroseconds(delayTime); }//for i }//void step //Close the lamp by 800 microsteps void closeLamp() { step(true, X_DIR, X_STP, 800); //Keep track of how many steps we are along the metal rod total_steps = total_steps + 800; }//void closeLamp //Open the lamp by 800 microsteps void openLamp() { step(false, X_DIR, X_STP, 800); //Keep track of how many steps we are along the metal rod total_steps = total_steps - 800; //delay(0); }//void openLamp /////////////////////////////////////////////////////// ////////////////////// NEOPIXELS ////////////////////// /////////////////////////////////////////////////////// void lampOff() { if(current_light == 0) return; //Turn all the NeoPixels off one_color_RGB(0,0,0); strip.show(); //Save the last color of each NeoPixel current_light = 0; //Save the last color of each NeoPixel currentColorAllLED(); }//void lampOff ////////////////////// FADE IN ////////////////////// void fadeIn(byte R, byte G, byte B, int fade_amount) { //If the NeoPixels are already fully on, don't continue this function if(fade_counter > 255) return; int s = fade_counter; //for ease of using "s" instead of "fade_counter" in the functions below int tmpR = (R * 0.5 * s) / 255; // Multiply first to avoid truncation errors int tmpG = (G * 0.5 * s) / 255; int tmpB = (B * s) / 255; //Loop over each NeoPixel and set it's R, G & B value, //which will get brighter and brighter the more often this function is called for (int i = 0; i < ledCount; i++) { strip.setPixelColor(i,tmpR,tmpG,tmpB); }//for i strip.show(); //Increase the fade_counter a little so the next time this function is called //each NeoPixel is dimmed more fade_counter = fade_counter + fade_amount; //Save these colors for possible other functions (e.g. pinkSparkles) //Silly to save them for each time this function is called, but I didn't //have time to do it smarter for(int i = 0; i< ledCount; i++){ oldR[i] = R; oldG[i] = G; oldB[i] = B; }//for i }//void fadeIn /////////////////// FADE OUT /////////////////// //Fade out the last truly set color of each LED void fadeOut(int fade_amount) { //If the NeoPixels are already fully faded, don't continue this function if(fade_counter < 0) return; int s = fade_counter; //for ease of using "s" instead of "fade_counter" in the functions below int tmpR; int tmpG; int tmpB; //Loop over each NeoPixel and dim the last color it had (in the R, G & B) more and //more the more as fade_counter increases for (int i = 0; i < ledCount; i++) { tmpR = (Red(currentColor[i]) * 0.5 * s) / 255; // Multiply first to avoid truncation errors tmpG = (Green(currentColor[i]) * 0.5 * s) / 255; tmpB = (Blue(currentColor[i]) * s) / 255; strip.setPixelColor(i,tmpR,tmpG,tmpB); }//for i strip.show(); //Change the fade_counter a little so the next time this function is called //each NeoPixel is dimmed more (fade_amount is negative here) fade_counter = fade_counter + fade_amount; }//void fadeOut /////////////////// BLUE FLOWER /////////////////// void blueFlower() { for(int i = 0; i < ledCount; i++) { int baseColor = 180; int N10 = (ledCount/6); int N20 = (ledCount/3); int N30 = (ledCount/2); int N40 = (ledCount-N20); int N50 = (ledCount-N10); setHSV(i, baseColor, 255, 255); if(i == 0) baseColor = 220; if(i == N10) baseColor = 220; if(i == N20) baseColor = 220; if(i == N30) baseColor = 220; if(i == N40) baseColor = 220; if(i == N50) baseColor = 220; setHSV(i, baseColor, 255, 255); if(i == 0 + ledCount/9) baseColor = 0; if(i == N10 + ledCount/9) baseColor = 160; if(i == N20 + ledCount/9) baseColor = 160; if(i == N30 + ledCount/9) baseColor = 160; if(i == N40 + ledCount/9) baseColor = 160; if(i == N50 + ledCount/9) baseColor = 160; setHSV(i, baseColor, 100, 255); }//for i strip.show(); //Save the last color of each NeoPixel currentColorAllLED(); //Keep track of which NeoPixel state is active current_light = 2; }//void blueFlower /////////////////// PINK SPARKLES /////////////////// void pinkSparkles() { //Randomly assign a yellow-orange-pink-ish color to each NeoPixel for(int i = 0; i < ledCount; i++){ int shade = random(20, 120); //random(10,255); newR[i] = 255 - shade/4; //shade-50; newG[i] = 255 - shade*2; newB[i] = shade/4; }//for i //In 256 steps, make each NeoPixel switch colors from their old color to the new one for(int n = 0; n < 256; n++){ //256 update over time for(int i=0; i < ledCount; i++){ //update each pixel int thisR = map(n,0,nmax,oldR[i],newR[i]); int thisG = map(n,0,nmax,oldG[i],newG[i]); int thisB = map(n,0,nmax,oldB[i],newB[i]); strip.setPixelColor(i,thisR,thisG,thisB); }//for i strip.show(); delay(5); }//for n //Replace the previous old colors with the ones that are new //which will be the old colors the next time this function is called for(int i = 0; i< ledCount; i++){ oldR[i] = newR[i]; oldG[i] = newG[i]; oldB[i] = newB[i]; }//for i //Save the last color of each NeoPixel currentColorAllLED(); //Keep track of which NeoPixel state is active current_light = 3; }//void pinkSparkles ////////////////////// HEX LIGHTS ///////////////////// void hexLights(){ int num_sections = 6; int zero_led = 6; //Split the NeoPixels into 6 groups and give each group a different hue from a 360 degrees wheel //Using the fact that it's NeoPixel with index 6 that is in a corner, I'm therefore using //a modulo function (%) to cycle through ledCount and make led 6 = 0, 7 = 1, etc, 59 = 53, 0 = 54, 1 = 55, etc. for(int i = 0; i < ledCount; i++) { int Hue = (floor(((i-zero_led+ledCount)%ledCount)/(ledCount/num_sections))) * 360/num_sections; setHSV(i, Hue, 255, 255); }//for i strip.show(); //Save the last color of each NeoPixel currentColorAllLED(); //Keep track of which NeoPixel state is active current_light = 1; }//void hexLights /////////////////////////////////////////////////////// ///////////// NEOPIXELS - HELPER FUNCTIONS //////////// /////////////////////////////////////////////////////// //Save the last color of each NeoPixel separately void currentColorAllLED() { for(int i = 0; i< ledCount; i++){ currentColor[i] = strip.getPixelColor(i); }//for i }//void currentColorAllLED //Get the R,G,B parts of the getPixelColor() function //https://learn.adafruit.com/multi-tasking-the-arduino-part-3/utility-functions // Returns the Red component of a 32-bit color uint8_t Red(uint32_t color) { return (color >> 16) & 0xFF; } // Returns the Green component of a 32-bit color uint8_t Green(uint32_t color) { return (color >> 8) & 0xFF; } // Returns the Blue component of a 32-bit color uint8_t Blue(uint32_t color) { return color & 0xFF; } //set all NeoPixels to one RGB color void one_color_RGB(char R, char G, char B){ for(int i = 0; i < ledCount; i++){ strip.setPixelColor(i,R,G,B); }//for i strip.show(); }//void one_color_RGB void setHSV(int led, unsigned int hue, byte sat, byte val) { //Set led by hue, saturation, value unsigned char r,g,b; unsigned int H_accent = hue/60; unsigned int bottom = ((255 - sat) * val)>>8; unsigned int top = val; unsigned char rising = ((top-bottom) *(hue%60 ) ) / 60 + bottom; unsigned char falling = ((top-bottom) *(60-hue%60) ) / 60 + bottom; switch(H_accent) { case 0: r = top; g = rising; b = bottom; break; case 1: r = falling; g = top; b = bottom; break; case 2: r = bottom; g = top; b = rising; break; case 3: r = bottom; g = falling; b = top; break; case 4: r = rising; g = bottom; b = top; break; case 5: r = top; g = bottom; b = falling; break; } strip.setPixelColor(led, r, g, b); }//void setHSV