LEDs mounted with lenses to the old light housing
The charger port gets hidden when the top is closed.
Here is it in daylight from across the street.
Oh and I'm still able to program it since I added in a header for my FTDI cable.
UPDATE: Here is the full schematic, note Circuit labs doesn't have a decent facsimile to the TMP36 analog temperature sensor so i just used a Pot, kind of the same functionality when you think about it. just different input.
I'll be the first to admit that the code here is not the best. The debug function is nasty but serves a purpose and keeps things (in my mind) a bit cleaner and allows me to having different logging levels during troubleshooting. Now that the code is well tested I could probably remove it all but I'll bet it would mess up all my timing since the serial prints won't be there.
UPDATE: New Code for Rear Bike Light --> I've made a new post with all the serial debugging removed. It is cleaner but I'm still not sure about the timing and that is mostly to do with the button press durations. That is where a huge majority of my debugging was so the difference between a "long" press and a "short" one will be drastically quicker. I'll test this some time soon.
/*-------------------------------------------------------- Rear Bike Light Project Author: Chris Crumpacker Date: October 2012 Copyright (c) 2012 Chris Crumpacker. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. Sketch Notes: This version contains 6 modes of blinking with multiple speeds for some modes. This works off of a single button, with short presses the program steps thru the modes/speeds. When long pressed it goes into a "sleep" mode where the high powered LEDs are turned off. It also has the ablity to store the current mode so when leaving sleep mode or being brought back up from a power down it will return to the previous mode it was in. There is also an interal tempurature sensor that will put it into a hidden (at least from the mode scrolling) "limp home mode" during a certain temp range or evenshut the LEDs down if it gets any higher. --------------------------------------------------------*/ //------------------------- // Includes //------------------------- #include#include //------------------------- // Defines //------------------------- #define BUTTON_PIN 11 // Button #define LONGPRESS_LEN 10 // Min numberr of loops for a long press #define DELAY 10 // Delay per loop in ms #define CONFIG_VERSION "rbl1" // ID of the settings block #define memoryBase 32 // Tell it where to store your config data in EEPROM //Constructor for the Simple Timer enum { EV_NONE=0, EV_SHORTPRESS, EV_LONGPRESS }; //------------------------- // Pin Assignment //------------------------- int ledPinl = 9; // Left LED int ledPinr = 10; // Right LED int powerPin = 13; // Case LED to show that the circuit has power int tempSensorPin= A5; // Analog pin the case's Temp36 sensor is on //------------------------- // Variables //------------------------- boolean ok = true; // bool for the EEPROM's config setup int configAdress = 0; boolean currentButton = LOW; boolean button_was_pressed = false; int previousButton; int button_pressed_counter = 0; int longPress = LONGPRESS_LEN; int buttonCount = 0; long previousMillis = 0; boolean fromCheckTemp = false; long previousTempTime = 0; float tempLimp = 100; // In degrees (f) float tempShutdown = 120; // In degrees (f) int checkTempInterval = 30000; // In Milliseconds float freq; float freqInitial = .002; float freqChange = .002; float freqLimit = .006; int ledStep = 255; // How much to change the dimming (PWM) between each step for steps 6 to 9 and 10 to 13 int ledState = HIGH; int debugLevel = 1; // 0 = off, 1 = low, 2 = high, 3 = verbose // The struct for the config saved to the EEPROM struct StoreStruct { char* cVersion; // This is to detect if the settings stored in the EEPROM are for this config and sketch int bc; } storage = { CONFIG_VERSION, // Defaults 0 }; //------------------------- // Setup //------------------------- void setup() { Serial.begin(9600); // Sets up the serial port and speed pinMode(BUTTON_PIN, INPUT); // Setting the button pin to an input digitalWrite(BUTTON_PIN, HIGH); // Setting the button with a pull-up resistor, the button when grounded or "low" will be thought of as pressed pinMode(powerPin, OUTPUT); // Setting the pin for the LED on the board to show that power is on or will blink if in a sleep mode pinMode(ledPinl, OUTPUT); // External LED control pin 1 pinMode(ledPinr, OUTPUT); // External LED control pin 2 EEPROM.setMemPool(memoryBase, EEPROMSizeATmega328); // Set memorypool base to 32, assume Atmega328 configAdress = EEPROM.getAddress(sizeof(StoreStruct)); // Size of config object ok = loadConfig(); // Loads the config, and if it loads sets the bool "ok" to true buttonCount = storage.bc; // Sets the variable for the buttonCount to what is brought back from the storage checkTemp("setup"); // Checks the intial temp at start up freq = setFreq("setup"); // Sets the initial Frequency for the pulsing modes ledStep = setLEDStep("setup"); // Sets the initial LED PWM step value for the dimming modes digitalWrite(powerPin, ledState); // Turns on the on board LED } //------------------------- // Functions //------------------------- // Debug Function /* This function allows you to print valuable information from within each function. For each function that calls the debug you first need to set "debugFuncName" variable first for example: char* debugFuncName = "xyzFunction"; Now the function name is just a string so you can make it whatever you like but for consistancy I keep it the name of the function it's self. Now any time a new variable is set you can call the debug to print it to the serial monitor like so: debug(variable,"human readable yet short variable description",debugFuncName,fromFunc); The "fromFunc" part is needed when your base function is calling anothering function to do work. For example if you have multiple functions that repeat but you check a global button state monitor you would want to know that the variable is being set in the button monitor on behalf of each particular function. When calling the button monitor from each function I would pass the debugFuncName variable like this: buttonMonitor(debugFuncName); In that button monitor the sending fuction name variable is passed in like this: void buttonMonitor(char* fromFunc){...} If you don't intend to do this nested funtion calling you can remove the last part of the debug function decleration. or if just one debug trace doesn't need it you can just use an empty set like this: debug(variable,"human readable yet short variable description",debugFuncName,""); */ void debug(int msgLevel,float variable, char* message, char* inFunc, char* fromWhere){ boolean printToSerial; if (debugLevel == 3 && (msgLevel == 3 || msgLevel == 2 || msgLevel == 1)){ //Verbose logging printToSerial = true; } else if (debugLevel == 2 && (msgLevel == 2 || msgLevel == 1)) { //High logging printToSerial = true; }else if (debugLevel == 1 && msgLevel == 1) { //Low logging printToSerial = true; } else if (debugLevel == 0) { //Debugging disabled printToSerial = false; } else { //Debug level not high enough to trace out to serial printToSerial = false; } /*If the debug level is high enough for the msgLevel of the debug trace it will be printed to serial if not it will be ignored*/ if (printToSerial == true) { Serial.print(variable); Serial.print(" "); Serial.print(message); Serial.print(" in "); Serial.print(inFunc); Serial.print(" from "); Serial.println(fromWhere); } } // Loads the Config from EEPROM bool loadConfig() { EEPROM.readBlock(configAdress, storage); return (storage.cVersion == CONFIG_VERSION); } // Saves Config changes to the EEPROM void saveConfig() { EEPROM.writeBlock(configAdress, storage); } //--Button Handling-- // This function determines if the button press is short or long and is made to report back to a switch case void handle_button(int longPress, char* fromFunc,int modeType) { char* debugFuncName = "handle_button"; int button_now_pressed = !digitalRead(BUTTON_PIN); // pin low -> pressed if (!button_now_pressed && button_was_pressed) { //Short press if (button_pressed_counter < longPress) { debug(1,buttonCount,"Short Pressed",debugFuncName,fromFunc); debug(2,freq*100,"Frequence",debugFuncName,fromFunc); debug(2,ledStep,"LED step value",debugFuncName,fromFunc); debug(2,buttonCount,"buttonCount",debugFuncName,fromFunc); debug(1,button_pressed_counter,"Cycles - Button was Pressed for this many cycles",debugFuncName,fromFunc); if (modeType == 1){ /*Short press from one of the pulsing modes. This increments the button count, updates the Frequency and possibly the LEDStep and also stores the new buttonCount away in the EEPROM*/ previousButton = buttonCount; debug(2,previousButton,"PreviousButton should now be set to old button count",debugFuncName,fromFunc); ++buttonCount; debug(2,buttonCount,"buttonCount incremented by 1",debugFuncName,fromFunc); storage.bc = buttonCount; saveConfig(); setFreq(debugFuncName); setLEDStep(debugFuncName); debug(1,storage.bc,"storage.bc of buttonCount via short press",debugFuncName,fromFunc); debug(1,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); } else if (modeType == 2){ /*Short press from one of the dimming PWM modes. This increments the button count, updates the Frequency and the LEDStep and also stores the new buttonCount away in the EEPROM*/ previousButton = buttonCount; debug(2,previousButton,"PreviousButton should now be set to old button count",debugFuncName,fromFunc); ++buttonCount; debug(2,buttonCount,"buttonCount incremented by 1",debugFuncName,fromFunc); storage.bc = buttonCount; saveConfig(); setFreq(debugFuncName); setLEDStep(debugFuncName); debug(1,storage.bc,"storage.bc of buttonCount via short press",debugFuncName,fromFunc); debug(1,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); } else if (modeType == 3) { /*Short press for the sleep modes 14 and 15. This starts us back to the first mode (0) and sets the frequency and the LED step as well as store the button count to the EEPROM*/ debug(1,buttonCount,"Short button press",debugFuncName,fromFunc); buttonCount = 0; debug(2,buttonCount,"buttonCount should now be 0",debugFuncName,fromFunc); storage.bc = buttonCount; //Stores the buttonCount to EEPROM saveConfig(); debug(1,storage.bc,"storage.bc of buttonCount via Short press",debugFuncName,fromFunc); setFreq(debugFuncName); setLEDStep(debugFuncName); fromCheckTemp = false; debug(1,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); } //Long Press } else { debug(1,buttonCount,"Long Press",debugFuncName,fromFunc); debug(1,button_pressed_counter,"Cycles - Button was Pressed for this many cycles",debugFuncName,fromFunc); if (modeType == 1 || modeType == 2){ /*Long press for any of the "awake" modes. It puts the external LEDs to sleep in mode 14 or sleep mode. Also it sets the previous button so when exiting the sleep mode it knows what to go back to*/ previousButton = buttonCount; buttonCount = 14; debug(2,previousButton,"previous buttonCount",debugFuncName,fromFunc); debug(2,buttonCount,"new buttonCount should be 14 for Sleep",debugFuncName,fromFunc); debug(1,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); } else if (modeType == 3) { /*Long press from one of the sleep modes. This sets the button count back to the previous button, updates the Frequency and the LEDStep and also stores the new buttonCount away in the EEPROM*/ buttonCount = previousButton; debug(2,previousButton,"previous button",debugFuncName,fromFunc); debug(2,buttonCount,"buttonCount now should be set to previous button",debugFuncName,fromFunc); storage.bc = buttonCount; saveConfig(); setFreq(debugFuncName); setLEDStep(debugFuncName); debug(1,storage.bc,"storage.bc of buttonCount via Long press",debugFuncName,fromFunc); debug(1,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); fromCheckTemp = false; } } //No Press } else { debug(3,buttonCount,"No button was pressed",debugFuncName,fromFunc); } if (button_now_pressed) ++button_pressed_counter; else button_pressed_counter = 0; debug(3,button_pressed_counter,"--Button Pressed Counter--",debugFuncName,fromFunc); button_was_pressed = button_now_pressed; } //Checks the tempurature inside the circuit enclosure, void checkTemp(char* fromFunc) { char* debugFuncName = "checkTemp"; unsigned long currentTempTime = millis(); // Set the current time if(currentTempTime - previousTempTime > 20000){ previousTempTime = currentTempTime; float Vcc = readVcc(); // Calculating the Supply Voltage Vcc = Vcc / 1000; // Converting from mV to Volts debug(3,Vcc,"Vcc in V",debugFuncName,fromFunc); int reading = analogRead(tempSensorPin); // Reading the voltage from the sensor pin debug(3,reading,"Temp_Sensor_Pin_Reading",debugFuncName,fromFunc); // Converting that reading to voltage float voltage = reading * Vcc; voltage /= 1024.0; debug(3,voltage,"reading Voltage converted",debugFuncName,fromFunc); // Print out the temperature in Celcius float temperatureC = (voltage - 0.5) * 100 ; //converting from 10 mv per degree wit 500 mV offset to degrees ((volatge - 500mV) times 100) debug(2,temperatureC,"temp in C",debugFuncName,fromFunc); // Now convert to Fahrenheight float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0; debug(1,temperatureF,"temp in F",debugFuncName,fromFunc); if (temperatureF > tempLimp && temperatureF < tempShutdown) { buttonCount = 15; fromCheckTemp = true; debug(1,buttonCount,"Open a window! it's getting stuffy. I'll turn the lights down",debugFuncName,fromFunc); } else if (temperatureF >= tempShutdown && buttonCount != 14) { buttonCount = 14; fromCheckTemp = true; debug(1,buttonCount,"It's getting Hot in here, so take off all your clothes. I'll shut down the lights in the mean time",debugFuncName,fromFunc); } else if (fromCheckTemp) { fromCheckTemp = false; buttonCount = previousButton; debug(2,buttonCount,"buttonCount set back to previous",debugFuncName,fromFunc); debug(1,buttonCount,"Awwww yeahhhh! It's business time.",debugFuncName,fromFunc); } else { fromCheckTemp = false; debug(1,buttonCount,"Awwww yeahhhh! It's business time.",debugFuncName,fromFunc); } debug(1,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); } else { //Holder for stuff to do while waiting on the time to check temp again } debug(3,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); } //When starting up with a stored button count we need to find and set the appropriate Frequency "freq" for the button count float setFreq(char* fromFunc) { char* debugFuncName = "setFreq"; debug(3,buttonCount,"Setting Frequency",debugFuncName,fromFunc); if (buttonCount == 0 || buttonCount == 3) { freq = freqInitial; } else if (buttonCount == 1 || buttonCount == 4) { freq = freqInitial + freqChange; } else if (buttonCount == 2 || buttonCount == 5) { freq = freqInitial + freqChange + freqChange; } else { freq = freqInitial; } debug(3,freq*100,"Frequency set to",debugFuncName,fromFunc); debug(3,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); return freq; } //When starting up with a stored button count we need to find and set the appropriate LED brightness "ledStep" for the button count int setLEDStep(char* fromFunc) { char* debugFuncName = "setLEDStep"; debug(3,buttonCount,"Setting LEDStep",debugFuncName,fromFunc); if (buttonCount == 6 || buttonCount == 10){ ledStep = 255; } else if (buttonCount == 7 || buttonCount == 11) { ledStep = 191; } else if (buttonCount == 8 || buttonCount == 12) { ledStep = 127; } else if (buttonCount == 9 || buttonCount == 13) { ledStep = 64; } else { ledStep = 255; } debug(3,ledStep,"LED Step value",debugFuncName,fromFunc); debug(3,buttonCount,"------------------------------------------------------",debugFuncName,fromFunc); return ledStep; } //***************************// //******Blinking Modes*******// //***************************// //"bothFlipFlopPulse" The LEDs pulse back and forth (3 speeds) void bothFlipFlopPulse() { char* debugFuncName = "bothFlipFlopPulse"; float ledIn; float ledOutL; float ledOutR; longPress = 10; debug(3,buttonCount,"buttonCount ",debugFuncName,""); checkTemp(debugFuncName); setFreq(debugFuncName); for (ledIn = 4.712; ledIn < 10.995; ledIn = ledIn + freq) // This sets the start of the LED (ledOutL) pulse on the sin wave to the first zero crossing 4.712 and ends it on the next 10.995. { ledOutL = sin(ledIn) * 127.5 + 127.5; // Making the sin wave all positive numbers and setting it to a scale of 0-255 for the PWM range ledOutR = 255 - (sin(ledIn) * 127.5 + 127.5); // This inverts ledOutR so it pulses to the high as ledOutR pulses to the low analogWrite(ledPinl, ledOutL); analogWrite(ledPinr, ledOutR); } handle_button(longPress,debugFuncName,1); // Sets the Button function to run and read the button state, then returns the event, EV_SHORT, EV_LONG, or EV_NONE } //"bothPulse" Like "bothFlipFlopPulse" but with both LEDs on the same sin wave (3 speed) void bothPulse() { char* debugFuncName = "bothPulse"; float ledIn; float ledOutL; float ledOutR; longPress = 10; checkTemp(debugFuncName); setFreq(debugFuncName); for (ledIn = 4.712; ledIn < 10.995; ledIn = ledIn + freq) //This sets the start of the LED (ledOutL) pulse on the sin wave to the first zero crossing 4.712 and ends it on the next 10.995. { int out = sin(ledIn) * 127.5 + 127.5; //Both LEDs will follow the sin wave but we also have to make it all positive numbers and set to a scale of 0-255 for the PWM range analogWrite(ledPinl, out); analogWrite(ledPinr, out); } handle_button(longPress,debugFuncName,1); } //"bothStepped" - Both LEDs on, stepping down the brightness with each button press (4 settings from full bright to rather dim) void bothStepped() { char* debugFuncName = "bothStepped"; longPress = 75; checkTemp(debugFuncName); setLEDStep(debugFuncName); analogWrite(ledPinl, ledStep); //Turns them both on together analogWrite(ledPinr, ledStep); handle_button(longPress,debugFuncName,2); delay(DELAY); } //"singleStepped" - Just one LED on, stepping down the brightness with each button press (4 settings from full bright to rather dim) void singleStepped(){ char* debugFuncName = "singleStepped"; debug(3,buttonCount,"button Count",debugFuncName,""); longPress = 75; checkTemp(debugFuncName); setLEDStep(debugFuncName); analogWrite(ledPinl, ledStep); digitalWrite(ledPinr, LOW); handle_button(longPress,debugFuncName,2); delay(DELAY); } //"sleep" external LEDs off but blink the power led on the circuit board. void sleep() { char* debugFuncName = "sleep"; longPress = 75; debug(3,fromCheckTemp," = From Check Temp",debugFuncName,""); checkTemp(debugFuncName); digitalWrite(ledPinl, LOW); //Turns off both High Power LEDs digitalWrite(ledPinr, LOW); // Blinks the powerPin light by checking the current time vs. the last time it went thru, once it is over the 1000 ms limit it changes the light's state unsigned long currentMillis = millis(); if(currentMillis - previousMillis > 1000){ previousMillis = currentMillis; if (ledState == LOW){ ledState = HIGH; } else { ledState = LOW; } digitalWrite(powerPin, ledState); } handle_button(longPress,debugFuncName,3); delay(DELAY); } //"limpHome" The limp home mode, Like mode 1 the LEDs pulse back and forth, But slowly and only to half brightness. void limpHome() { char* debugFuncName = "limpHome"; float ledIn; float ledOutL; float ledOutR; debug(3,fromCheckTemp," = From Check Temp",debugFuncName,""); checkTemp(debugFuncName); longPress = 75; for (ledIn = 4.712; ledIn < 10.995; ledIn = ledIn + .002) // This sets the start of the LED (ledOutL) pulse on the sin wave to the first zero crossing 4.712 and ends it on the next 10.995. { ledOutL = sin(ledIn) * 100 + 127.5; // Making the sin wave all positive numbers and setting it to a scale of 0-255 for the PWM range ledOutR = 255 - (sin(ledIn) * 127.5 + 127.5); // This inverts ledOutR so it pulses to the high as ledOutR pulses to the low analogWrite(ledPinl, ledOutL); analogWrite(ledPinr, ledOutR); } unsigned long currentMillis = millis(); if(currentMillis - previousMillis > 1000){ previousMillis = currentMillis; if (ledState == LOW){ ledState = HIGH; } else { ledState = LOW; } digitalWrite(powerPin, ledState); } handle_button(longPress,debugFuncName,3); delay(DELAY); } //------------------------- // THE LOOP //------------------------- void loop() { char* debugFuncName = "loop"; //Set what mode the LEDs are in based on how many times the button is pressed. while (buttonCount < 3) { bothFlipFlopPulse(); } while (buttonCount >= 3 && buttonCount < 6) { bothPulse(); } while (buttonCount >= 6 && buttonCount < 10) { bothStepped(); } while (buttonCount >= 10 && buttonCount < 14) { singleStepped(); } while (buttonCount == 14) { sleep(); } while (buttonCount == 15) { limpHome(); } delay(DELAY); }
Very informative and impressive post you have written, this is quite interesting and i have went through it completely, an upgraded information is shared, keep sharing such valuable information. LED Dimmers
ReplyDeleteJUDI ONLINE TERPERCAYA
ReplyDeleteBET88
88BET
BOLA88
SLOT88
SBOBET88
SLOT ONLINE
BET88
88BET
SLOT ONLINE
SLOT ONLINE
SLOT ONLINE
BOS717
CASINO ONLINE
AGEN TOGEL TERLENGKAP
SLOT ONLINE
QQSLOT ONLINE
JUDI CASINO ONLINE
SBOBET WAP
SLOT ONLINE
CASINO ONLINE
BET88 ONLINE
BET88
BET88
CASINO SBOBET88
AGEN SBOBET88
SITUS JUDI ONLINE
JUDI SLOT ONLINE
AGEN TOGEL
SLOT ONLINE
CASINO ONLINE
AGEN BOLA
Tembak Ikan Online
TOGEL ONLINE
SLOT ONLINE
QQGO 368BET
BET88
SITUS JUDI DEPOSIT PULSA
AGEN BETTING ONLINE
AGEN JUDI CASINO ONLINE
BANDAR JUDI CASINO
BET88
BET88
88BET
BET88 ONLINE
88BET
88BET
BET88
88BET
BET88 ONLINE
Poker99
ReplyDelete