Nick Zhao
/
SmartLEDWindow
Smart LED window to mimic the sun
main.cpp@0:53cb5d7e5c36, 2019-12-08 (annotated)
- Committer:
- TCNoodleshop
- Date:
- Sun Dec 08 21:28:41 2019 +0000
- Revision:
- 0:53cb5d7e5c36
First commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
TCNoodleshop | 0:53cb5d7e5c36 | 1 | #include "mbed.h" |
TCNoodleshop | 0:53cb5d7e5c36 | 2 | #include <PwmOut.h> |
TCNoodleshop | 0:53cb5d7e5c36 | 3 | // **I/O INITIALIZATION** |
TCNoodleshop | 0:53cb5d7e5c36 | 4 | Serial pc(USBTX, USBRX); // tx, rx for Serial Port (Debugging) |
TCNoodleshop | 0:53cb5d7e5c36 | 5 | Serial Blue(p28,p27); // Bluetooh Initialization |
TCNoodleshop | 0:53cb5d7e5c36 | 6 | PwmOut bLED(p21); // Blue LEDS PWM pin assignment |
TCNoodleshop | 0:53cb5d7e5c36 | 7 | PwmOut rLED(p23); // Red LEDS PWM pin assignment |
TCNoodleshop | 0:53cb5d7e5c36 | 8 | AnalogIn bSliderIn(p20); // Slider in for blue |
TCNoodleshop | 0:53cb5d7e5c36 | 9 | AnalogIn rSliderIn(p19); // Slider in for red |
TCNoodleshop | 0:53cb5d7e5c36 | 10 | |
TCNoodleshop | 0:53cb5d7e5c36 | 11 | // **GLOBAL VARIABLES** |
TCNoodleshop | 0:53cb5d7e5c36 | 12 | int mode = 0; //Mode 0 = bluetooth; Mode 1 = slider; Mode 2 = RTC |
TCNoodleshop | 0:53cb5d7e5c36 | 13 | // These percentages are based off 0-100, |
TCNoodleshop | 0:53cb5d7e5c36 | 14 | // They do not correleate linearly with direct PwmOut. |
TCNoodleshop | 0:53cb5d7e5c36 | 15 | int bPercent=0; |
TCNoodleshop | 0:53cb5d7e5c36 | 16 | int rPercent=0; |
TCNoodleshop | 0:53cb5d7e5c36 | 17 | |
TCNoodleshop | 0:53cb5d7e5c36 | 18 | // **BLUETOOTH** |
TCNoodleshop | 0:53cb5d7e5c36 | 19 | // Variables |
TCNoodleshop | 0:53cb5d7e5c36 | 20 | volatile bool button_ready = 0; |
TCNoodleshop | 0:53cb5d7e5c36 | 21 | volatile int bnum = 0; |
TCNoodleshop | 0:53cb5d7e5c36 | 22 | volatile int bhit =0; |
TCNoodleshop | 0:53cb5d7e5c36 | 23 | // State used to remember previous characters read in a button message |
TCNoodleshop | 0:53cb5d7e5c36 | 24 | enum statetype {start = 0, got_exclm, got_B, got_num, got_hit}; |
TCNoodleshop | 0:53cb5d7e5c36 | 25 | statetype state = start; |
TCNoodleshop | 0:53cb5d7e5c36 | 26 | // Interrupt routine to parse message with one new character per serial RX interrupt |
TCNoodleshop | 0:53cb5d7e5c36 | 27 | void parse_message() |
TCNoodleshop | 0:53cb5d7e5c36 | 28 | { |
TCNoodleshop | 0:53cb5d7e5c36 | 29 | switch (state) { |
TCNoodleshop | 0:53cb5d7e5c36 | 30 | case start: |
TCNoodleshop | 0:53cb5d7e5c36 | 31 | if (Blue.getc()=='!') state = got_exclm; |
TCNoodleshop | 0:53cb5d7e5c36 | 32 | else state = start; |
TCNoodleshop | 0:53cb5d7e5c36 | 33 | break; |
TCNoodleshop | 0:53cb5d7e5c36 | 34 | case got_exclm: |
TCNoodleshop | 0:53cb5d7e5c36 | 35 | if (Blue.getc() == 'B') state = got_B; |
TCNoodleshop | 0:53cb5d7e5c36 | 36 | else state = start; |
TCNoodleshop | 0:53cb5d7e5c36 | 37 | break; |
TCNoodleshop | 0:53cb5d7e5c36 | 38 | case got_B: |
TCNoodleshop | 0:53cb5d7e5c36 | 39 | bnum = Blue.getc(); |
TCNoodleshop | 0:53cb5d7e5c36 | 40 | state = got_num; |
TCNoodleshop | 0:53cb5d7e5c36 | 41 | break; |
TCNoodleshop | 0:53cb5d7e5c36 | 42 | case got_num: |
TCNoodleshop | 0:53cb5d7e5c36 | 43 | bhit = Blue.getc(); |
TCNoodleshop | 0:53cb5d7e5c36 | 44 | state = got_hit; |
TCNoodleshop | 0:53cb5d7e5c36 | 45 | break; |
TCNoodleshop | 0:53cb5d7e5c36 | 46 | case got_hit: |
TCNoodleshop | 0:53cb5d7e5c36 | 47 | if (Blue.getc() == char(~('!' + ' B' + bnum + bhit))) button_ready = 1; |
TCNoodleshop | 0:53cb5d7e5c36 | 48 | state = start; |
TCNoodleshop | 0:53cb5d7e5c36 | 49 | break; |
TCNoodleshop | 0:53cb5d7e5c36 | 50 | default: |
TCNoodleshop | 0:53cb5d7e5c36 | 51 | Blue.getc(); |
TCNoodleshop | 0:53cb5d7e5c36 | 52 | state = start; |
TCNoodleshop | 0:53cb5d7e5c36 | 53 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 54 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 55 | |
TCNoodleshop | 0:53cb5d7e5c36 | 56 | // **FUNCTIONS** |
TCNoodleshop | 0:53cb5d7e5c36 | 57 | |
TCNoodleshop | 0:53cb5d7e5c36 | 58 | // setLight: Sets a specified color strip to an input (0-100) |
TCNoodleshop | 0:53cb5d7e5c36 | 59 | // then saves that input to the variables rPercent or bPercent. |
TCNoodleshop | 0:53cb5d7e5c36 | 60 | // |
TCNoodleshop | 0:53cb5d7e5c36 | 61 | // Input values are not linearly correlated with the PWM duty cycle, |
TCNoodleshop | 0:53cb5d7e5c36 | 62 | // instead they are translated with a cubic function, so the lights |
TCNoodleshop | 0:53cb5d7e5c36 | 63 | // *appear* to be acting linearly |
TCNoodleshop | 0:53cb5d7e5c36 | 64 | void setLight(int input, PwmOut *LED){ |
TCNoodleshop | 0:53cb5d7e5c36 | 65 | if (input >100){ //Correct input to 100 if input is somehow too high |
TCNoodleshop | 0:53cb5d7e5c36 | 66 | input = 100; |
TCNoodleshop | 0:53cb5d7e5c36 | 67 | } else if (input <0){ //Correct input to 0 if input is somehow too low |
TCNoodleshop | 0:53cb5d7e5c36 | 68 | input = 0; |
TCNoodleshop | 0:53cb5d7e5c36 | 69 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 70 | if (LED == &bLED){ //If input is the blue LEDs |
TCNoodleshop | 0:53cb5d7e5c36 | 71 | if (input >= bPercent){ // If input is HIGHER than current brightness |
TCNoodleshop | 0:53cb5d7e5c36 | 72 | for (int i = bPercent; i < input; i++){ //Loop to gradually increase brightness until reaches desired value |
TCNoodleshop | 0:53cb5d7e5c36 | 73 | float temp = i; |
TCNoodleshop | 0:53cb5d7e5c36 | 74 | *LED = (((temp*temp*temp)/1000000)); |
TCNoodleshop | 0:53cb5d7e5c36 | 75 | wait(.01); |
TCNoodleshop | 0:53cb5d7e5c36 | 76 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 77 | } else { // If input is LOWER than current brightness |
TCNoodleshop | 0:53cb5d7e5c36 | 78 | for (int i = bPercent; i > input; i--){ //Loop until reaches desired value |
TCNoodleshop | 0:53cb5d7e5c36 | 79 | float temp = i; |
TCNoodleshop | 0:53cb5d7e5c36 | 80 | *LED = (((temp*temp*temp)/1000000)); |
TCNoodleshop | 0:53cb5d7e5c36 | 81 | wait(.01); |
TCNoodleshop | 0:53cb5d7e5c36 | 82 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 83 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 84 | bPercent = (input); //Record input to current bPercent |
TCNoodleshop | 0:53cb5d7e5c36 | 85 | } else { //If input is the red LEDs |
TCNoodleshop | 0:53cb5d7e5c36 | 86 | if (input >= rPercent){ |
TCNoodleshop | 0:53cb5d7e5c36 | 87 | for (int i = rPercent; i < input; i++){ |
TCNoodleshop | 0:53cb5d7e5c36 | 88 | float temp = i; |
TCNoodleshop | 0:53cb5d7e5c36 | 89 | *LED = (((temp*temp*temp)/1000000)); |
TCNoodleshop | 0:53cb5d7e5c36 | 90 | wait(.01); |
TCNoodleshop | 0:53cb5d7e5c36 | 91 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 92 | } else { //if input < bPercent |
TCNoodleshop | 0:53cb5d7e5c36 | 93 | for (int i = rPercent; i > input; i--){ |
TCNoodleshop | 0:53cb5d7e5c36 | 94 | float temp = i; |
TCNoodleshop | 0:53cb5d7e5c36 | 95 | *LED = (((temp*temp*temp)/1000000)); |
TCNoodleshop | 0:53cb5d7e5c36 | 96 | wait(.01); |
TCNoodleshop | 0:53cb5d7e5c36 | 97 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 98 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 99 | rPercent = (input); |
TCNoodleshop | 0:53cb5d7e5c36 | 100 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 101 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 102 | |
TCNoodleshop | 0:53cb5d7e5c36 | 103 | |
TCNoodleshop | 0:53cb5d7e5c36 | 104 | // sliderSet: Nearly the same as setLight() but with built-in noise reduction |
TCNoodleshop | 0:53cb5d7e5c36 | 105 | // (Doesn't allow any changes greater than 2 at a time) |
TCNoodleshop | 0:53cb5d7e5c36 | 106 | void sliderSet(int input, PwmOut *LED){ |
TCNoodleshop | 0:53cb5d7e5c36 | 107 | float temp = input; |
TCNoodleshop | 0:53cb5d7e5c36 | 108 | if (input >100){ //Set LED to 1 if input is somehow >= 100 |
TCNoodleshop | 0:53cb5d7e5c36 | 109 | *LED = 1; |
TCNoodleshop | 0:53cb5d7e5c36 | 110 | return; |
TCNoodleshop | 0:53cb5d7e5c36 | 111 | } else if (input <0){ //Set LED to 0 if input is somehow <= 100 |
TCNoodleshop | 0:53cb5d7e5c36 | 112 | *LED = 0; |
TCNoodleshop | 0:53cb5d7e5c36 | 113 | return; |
TCNoodleshop | 0:53cb5d7e5c36 | 114 | } else { //Cubic Function with noise reduction |
TCNoodleshop | 0:53cb5d7e5c36 | 115 | int bDif = abs( bPercent - input); |
TCNoodleshop | 0:53cb5d7e5c36 | 116 | int rDif = abs( rPercent - input); |
TCNoodleshop | 0:53cb5d7e5c36 | 117 | if (LED == &bLED){ //IF BLUE LED |
TCNoodleshop | 0:53cb5d7e5c36 | 118 | if (bDif <2 && bDif > -2){ |
TCNoodleshop | 0:53cb5d7e5c36 | 119 | *LED = (((temp*temp*temp)/1000000)); |
TCNoodleshop | 0:53cb5d7e5c36 | 120 | bPercent = (input); |
TCNoodleshop | 0:53cb5d7e5c36 | 121 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 122 | } else { // IF RED LED |
TCNoodleshop | 0:53cb5d7e5c36 | 123 | if (rDif <2 && rDif > -2){ |
TCNoodleshop | 0:53cb5d7e5c36 | 124 | *LED = (((temp*temp*temp)/1000000)); |
TCNoodleshop | 0:53cb5d7e5c36 | 125 | rPercent = (input); |
TCNoodleshop | 0:53cb5d7e5c36 | 126 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 127 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 128 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 129 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 130 | |
TCNoodleshop | 0:53cb5d7e5c36 | 131 | // Returns the user percentage assigned to that LED. |
TCNoodleshop | 0:53cb5d7e5c36 | 132 | int getPercent(PwmOut *LED){ |
TCNoodleshop | 0:53cb5d7e5c36 | 133 | if (LED == &bLED){ |
TCNoodleshop | 0:53cb5d7e5c36 | 134 | return bPercent; |
TCNoodleshop | 0:53cb5d7e5c36 | 135 | } else return rPercent; |
TCNoodleshop | 0:53cb5d7e5c36 | 136 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 137 | |
TCNoodleshop | 0:53cb5d7e5c36 | 138 | // **MAIN** |
TCNoodleshop | 0:53cb5d7e5c36 | 139 | int main() { |
TCNoodleshop | 0:53cb5d7e5c36 | 140 | //attach interrupt function for each new Bluetooth serial character |
TCNoodleshop | 0:53cb5d7e5c36 | 141 | Blue.attach(&parse_message,Serial::RxIrq); |
TCNoodleshop | 0:53cb5d7e5c36 | 142 | bLED.period_ms (1); //Set LED freq to 1Khz |
TCNoodleshop | 0:53cb5d7e5c36 | 143 | rLED.period_ms (1); |
TCNoodleshop | 0:53cb5d7e5c36 | 144 | PwmOut *LEDToControl = &bLED; //bLED is default LEDToControl |
TCNoodleshop | 0:53cb5d7e5c36 | 145 | set_time(1574588800); //7:00am |
TCNoodleshop | 0:53cb5d7e5c36 | 146 | |
TCNoodleshop | 0:53cb5d7e5c36 | 147 | while(1) { |
TCNoodleshop | 0:53cb5d7e5c36 | 148 | if (mode == 1){ |
TCNoodleshop | 0:53cb5d7e5c36 | 149 | sliderSet(bSliderIn*100,&bLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 150 | sliderSet(rSliderIn*100,&rLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 151 | } else if (mode == 2){ |
TCNoodleshop | 0:53cb5d7e5c36 | 152 | time_t now = time(0); |
TCNoodleshop | 0:53cb5d7e5c36 | 153 | tm *ltm = localtime(&now); |
TCNoodleshop | 0:53cb5d7e5c36 | 154 | int cHour = ltm->tm_hour; |
TCNoodleshop | 0:53cb5d7e5c36 | 155 | int cMin = ltm->tm_min; |
TCNoodleshop | 0:53cb5d7e5c36 | 156 | if (cHour > 18 || cHour <7){ //If between 6pm and 7am, turn all lights off |
TCNoodleshop | 0:53cb5d7e5c36 | 157 | setLight(0, &bLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 158 | setLight(0, &rLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 159 | } else if (cHour >= 7 && cHour < 8) { //From 7-8, fade as sunrise |
TCNoodleshop | 0:53cb5d7e5c36 | 160 | int lightset = cHour*100+(cMin)/.6; |
TCNoodleshop | 0:53cb5d7e5c36 | 161 | setLight((lightset-710)*8,&bLED); //Blue LED fade in at 7:06 |
TCNoodleshop | 0:53cb5d7e5c36 | 162 | setLight((lightset-700)*8,&rLED); //Red LED fade in at 7-7:08 |
TCNoodleshop | 0:53cb5d7e5c36 | 163 | pc.printf("Lightset: %i \n", lightset); |
TCNoodleshop | 0:53cb5d7e5c36 | 164 | } else if (cHour >= 17 && cHour < 18) { //From 5-6, fade as sunset |
TCNoodleshop | 0:53cb5d7e5c36 | 165 | int lightset = cHour*100+(cMin)/.6; |
TCNoodleshop | 0:53cb5d7e5c36 | 166 | setLight(100-((lightset-1725)*8),&rLED); //Red LED fade out at 5:15-5:30 |
TCNoodleshop | 0:53cb5d7e5c36 | 167 | setLight(100-((lightset-1700)*8),&bLED); //Blue LED fade out at 5-5:15 |
TCNoodleshop | 0:53cb5d7e5c36 | 168 | } else { |
TCNoodleshop | 0:53cb5d7e5c36 | 169 | setLight(100, &bLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 170 | setLight(100, &rLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 171 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 172 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 173 | //check for a new button message ready |
TCNoodleshop | 0:53cb5d7e5c36 | 174 | if(button_ready) { // button changed |
TCNoodleshop | 0:53cb5d7e5c36 | 175 | if(bnum=='1' && bhit == '1'){ |
TCNoodleshop | 0:53cb5d7e5c36 | 176 | mode = 0; |
TCNoodleshop | 0:53cb5d7e5c36 | 177 | pc.printf("mode 0!\n"); |
TCNoodleshop | 0:53cb5d7e5c36 | 178 | } else if (bnum=='2' && bhit == '1'){ |
TCNoodleshop | 0:53cb5d7e5c36 | 179 | mode = 1; |
TCNoodleshop | 0:53cb5d7e5c36 | 180 | setLight(bSliderIn*100,&bLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 181 | setLight(rSliderIn*100,&rLED); |
TCNoodleshop | 0:53cb5d7e5c36 | 182 | pc.printf("mode 1!\n"); |
TCNoodleshop | 0:53cb5d7e5c36 | 183 | } else if (bnum=='3' && bhit == '1'){ |
TCNoodleshop | 0:53cb5d7e5c36 | 184 | mode = 2; |
TCNoodleshop | 0:53cb5d7e5c36 | 185 | pc.printf("mode 2!\n"); |
TCNoodleshop | 0:53cb5d7e5c36 | 186 | }else if (bnum=='4' && bhit == '1'){ |
TCNoodleshop | 0:53cb5d7e5c36 | 187 | if (mode == 0){ |
TCNoodleshop | 0:53cb5d7e5c36 | 188 | if (LEDToControl == &bLED){ |
TCNoodleshop | 0:53cb5d7e5c36 | 189 | LEDToControl = &rLED; |
TCNoodleshop | 0:53cb5d7e5c36 | 190 | } else { |
TCNoodleshop | 0:53cb5d7e5c36 | 191 | LEDToControl = &bLED; |
TCNoodleshop | 0:53cb5d7e5c36 | 192 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 193 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 194 | pc.printf("color!\n"); |
TCNoodleshop | 0:53cb5d7e5c36 | 195 | }else if (bnum=='5' && bhit == '1'){ |
TCNoodleshop | 0:53cb5d7e5c36 | 196 | if (mode == 0){ |
TCNoodleshop | 0:53cb5d7e5c36 | 197 | if (getPercent(LEDToControl) <= 95){ |
TCNoodleshop | 0:53cb5d7e5c36 | 198 | setLight((getPercent(LEDToControl)+10),LEDToControl); |
TCNoodleshop | 0:53cb5d7e5c36 | 199 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 200 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 201 | pc.printf("inc!\n"); |
TCNoodleshop | 0:53cb5d7e5c36 | 202 | }else if (bnum=='6' && bhit == '1'){ |
TCNoodleshop | 0:53cb5d7e5c36 | 203 | if (mode == 0){ |
TCNoodleshop | 0:53cb5d7e5c36 | 204 | if (getPercent(LEDToControl)>=5){ |
TCNoodleshop | 0:53cb5d7e5c36 | 205 | setLight((getPercent(LEDToControl)-10),LEDToControl); |
TCNoodleshop | 0:53cb5d7e5c36 | 206 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 207 | //time_t seconds = time(0); |
TCNoodleshop | 0:53cb5d7e5c36 | 208 | //pc.printf("Time as a basic string = %s", ctime(&seconds)); |
TCNoodleshop | 0:53cb5d7e5c36 | 209 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 210 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 211 | button_ready = 0; //reset flag after reading button message |
TCNoodleshop | 0:53cb5d7e5c36 | 212 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 213 | |
TCNoodleshop | 0:53cb5d7e5c36 | 214 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 215 | |
TCNoodleshop | 0:53cb5d7e5c36 | 216 | } |
TCNoodleshop | 0:53cb5d7e5c36 | 217 |