/*
This is my LED output and thermal management system.
Author: Mark Chester
Email: mark@chesterfamily.org
WWW: http://www.chesterfamily.org/Projects/BikeGenerator
- Adjust the PWM of the LEDs based on their temperature.
*/
// Analog input pins
#define ledTempInPin 1 // LED temperature on pin 1
// Digital IO pins
#define ledPWMUpIndPin 12 // Indicator LED for increasing LED brightness
#define ledPWMFlatIndPin 8 // Indicator LED for unchanging LED brightness
#define ledPWMDownIndPin 7 // Indicator LED for decreasing LED brightness
// PWM output pins
#define ledPWMOutPinL 9 // Control the left LED brightness via PWM on pin 9
#define ledPWMOutPinC 10 // Control the center LED brightness via PWM on pin 10
#define ledPWMOutPinR 11 // Control the right LED brightness via PWM on pin 11
#define alarmOutPin 13 // Piezo output for alarms (over voltage, overheating)
// LED temperature management
int ledTemp; // The latest temperature reading of the LED
int ledTempReadPer = 5000; // Milliseconds between LED temperature readings (this changes as necessary)
long ledTempReadTime = 0; // The last time the temperature was read (start at 5 seconds)
int ledTempOptimal = 640; // Optimal temperature of the LEDs (0-1023) NOT LINEAR
int ledTempOvLap = 10; // Temp thresholds set at ledTempOptimal +/- ledTempOvLap
int ledTempPrev; // The previous temperature reading
int ledMaxTempIncrease = 6; // The fastest allowable temperature increase during ledTempReadPerDefault
// Indicators
byte ledUpIndState; // Shows temperature is cool (and the PWM is increasing)
byte ledFlatIndState; // Shows temperature is OK (and/or PWM is not changing)
byte ledDownIndState; // Shows temperature is hot (and PWM is reducing)
// LED PWM management
float ledPWMStepUp = 0.15; // PWM step interval (%) when increasing the LED PWM
float ledPWMStepDown = 0.25; // PWM step interval (%) when decreasing the LED PWM
float ledPWM = 128.0; // Always start off at sub-maximum brightness
byte ledPWMMax = 255; // The max PWM value that can be set to allow tuning
byte ledPWMMin = 5; // The min PWM value that can be set to allow tuning
byte ledTempAlarm = 15; // If the LED is still too hot and the PWM is <=, then trigger the audible alarm
int ledTempAlarmTimeout = 30000; // How long to wait before triggering the over temp alarm.
long ledTempAlarmStart; // The time in millis() when the overtemp condition started
boolean alarmState;
void setup () {
TCCR1B = TCCR1B & 0b11111000 | 0x02; // Sets the PWM freq to about 3900 Hz on pins 9 and 10
TCCR2B = TCCR2B & 0b11111000 | 0x02; // Sets the PWM freq to about 3900 Hz on pins 9 and 10
pinMode(ledPWMOutPinL, OUTPUT); // Establish pin modes
pinMode(ledPWMOutPinC, OUTPUT); // Establish pin modes
pinMode(ledPWMOutPinR, OUTPUT); // Establish pin modes
pinMode(ledPWMUpIndPin, OUTPUT);
pinMode(ledPWMFlatIndPin, OUTPUT);
pinMode(ledPWMDownIndPin, OUTPUT);
// Serial.begin(115200); // Comment out for final build
ledTemp = analogRead(ledTempInPin); // Check the startup temp of the LEDs
ledTempPrev = ledTemp; // Shif to ledPrev so we have something to base the next reading on.
if (ledTemp >= (ledTempOptimal + ledTempOvLap)) { // If we're already too hot
ledPWM = ledPWMMin; // then shut down to min bright
}
if ( ledTemp >= (ledTempOptimal - ledTempOvLap) && ledTemp < (ledTempOptimal + ledTempOvLap)) { // If we're warm but not hot
ledPWM = ledPWM/2; // Then start up at half output
}
digitalWrite(ledPWMFlatIndPin, HIGH); // Light the flat indicator so _something_ is lit at startup
analogWrite(ledPWMOutPinL, 255-ledPWM); // Set startup PWM value
analogWrite(ledPWMOutPinC, 255-ledPWM); // Set startup PWM value
analogWrite(ledPWMOutPinR, 255-ledPWM); // Set startup PWM value
}
void setPWM() { // Function to set the PWM of the LEDs
if (ledPWM <= ledPWMMin) { // If we're at or below Min, then set to Min.
ledPWM = ledPWMMin;
}
if (ledPWM >= ledPWMMax) { // If we're at or above Max, then set to Max
ledPWM = ledPWMMax;
}
analogWrite(ledPWMOutPinL, 255-ledPWM); // Set LED PWM
analogWrite(ledPWMOutPinC, 255-ledPWM); // Set LED PWM
analogWrite(ledPWMOutPinR, 255-ledPWM); // Set LED PWM
}
void setIndLEDs() { // Function to set the indicators LEDs
digitalWrite(ledPWMUpIndPin, ledUpIndState); // The "cool and increasing" pin
digitalWrite(ledPWMFlatIndPin, ledFlatIndState); // The "OK and/or not chaning" pin
digitalWrite(ledPWMDownIndPin, ledDownIndState); // The "hot and reducing" pin
}
void reducePWM() { // Function to reduce the PWM to the LEDs
checkLEDTempAlarm(); // Run the over temp alarm function
if ( ledTemp >= ledTempPrev ) { // Look for rapid temp increase rate
ledPWM = ledPWM - (ledPWM * ledPWMStepDown); // Lower the LED PWM
setPWM(); // Set the PWM
if ( ledPWM == ledPWMMin ) { // Check for @Min condition and set states accordingly
ledUpIndState = 0;
ledFlatIndState = 1;
ledDownIndState = 1;
}
else { // If we're not at Min then set the states this way instead.
ledUpIndState = 0;
ledFlatIndState = 0;
ledDownIndState = 1;
}
}
else { // If no change
ledUpIndState = 0; // set the flat indicator.
ledFlatIndState = 1;
ledDownIndState = 0;
}
setIndLEDs(); // Set the indicators
}
void increasePWM() { // Function to increase the PWM to the LEDs
if ( ledTemp <= ledTempPrev ) {
ledPWM = ledPWM + (ledPWM * ledPWMStepUp); // Calc the new PWM value
setPWM(); // Run the setPWM() function
if ( ledPWM == ledPWMMax ) { // Check for @Max condition
ledUpIndState = 1; // and set the indicator states accordingly
ledFlatIndState = 1;
ledDownIndState = 0;
}
else { // If we're not at Max
ledUpIndState = 1; // set the indicator states this way instead.
ledFlatIndState = 0;
ledDownIndState = 0;
}
}
else { // If no change
ledUpIndState = 0; // set the indicator states this way instead.
ledFlatIndState = 1;
ledDownIndState = 0;
}
setIndLEDs(); // Set the indicators
}
void checkLEDTempAlarm() { // Function to watch for and fire the over temp alarm
if ( ledPWM < ledTempAlarm && ledTemp > (ledTempOptimal+ledTempOvLap)) { // If we're still too hot and the PWM is low
if ( alarmState ) { // Check if we've already set alarm condition
if ( millis() >= (ledTempAlarmStart + ledTempAlarmTimeout)) { // Look for elapsed time since alarm condition started
analogWrite(alarmOutPin, 127); // Sound the overtemp alarm
}
}
else {
ledTempAlarmStart = millis(); // Mark the beginning of the alarm condition
alarmState = 1; // Set alarm condition
}
}
else {
analogWrite(alarmOutPin, 0); // Otherwise shut off the alarm
alarmState = 0; // Clear alarm condition
ledTempAlarmStart = 0; // Clear timer
}
}
void loop() {
// LED temperature vs brightness management
if ( (millis() - ledTempReadTime) >= ledTempReadPer ) { // Check the time interval
ledTempPrev = ledTemp; // Shift last reading to ledTempPrev
ledTemp = analogRead(ledTempInPin); // Read the temp
if ( ledTemp > (ledTempPrev + ledMaxTempIncrease)) { // Check for too fast of temp rise
reducePWM(); // Run the reducePWM() function
}
else {
if ( ledTemp >= ledTempOptimal+ledTempOvLap ) { // Check for over temp
reducePWM(); // Run the reducePWM() function
}
else if ( ledTemp <= (ledTempOptimal-ledTempOvLap)) { // Check for under temp
increasePWM(); // Run the increasePWM() function
}
else { // If all is stable then just set the LED indicator states
ledUpIndState = 0;
ledFlatIndState = 1;
ledDownIndState = 0;
setIndLEDs(); // and run the setIndLEDs() function
}
}
ledTempReadTime = millis(); // Mark the last run time
// Serial.print("LED Temp: "); // Comment out for final build
// Serial.print(ledTemp);
// Serial.print("/1023\tLED PWM: ");
// Serial.println(ledPWM);
}
}
<- Previous | Contents
Photo Gallery