Arduino Code

/*
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);
  }
}

<- PreviousContents
Photo Gallery