diff options
author | Mark Kriegsman <kriegsman@tr.org> | 2014-08-05 22:16:00 +0400 |
---|---|---|
committer | Mark Kriegsman <kriegsman@tr.org> | 2014-08-05 22:16:00 +0400 |
commit | 4a21223dc36253f7e798bd6ed9036e46edd1ad6f (patch) | |
tree | 20ae24034caba22ca51f4e4004c44eb6b1f42d9d /power_mgt.cpp | |
parent | 76840c0dfb92a8ce783abb87fbfe565f9dda26c5 (diff) |
Adding power management code, with global interfaces ONLY at this point.
Diffstat (limited to 'power_mgt.cpp')
-rw-r--r-- | power_mgt.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/power_mgt.cpp b/power_mgt.cpp new file mode 100644 index 00000000..edfb568d --- /dev/null +++ b/power_mgt.cpp @@ -0,0 +1,144 @@ +#include "FastLED.h" +#include "power_mgt.h" + +//// POWER MANAGEMENT + +// These power usage values were arrived at by actually measuing the power +// draw of a number of different LED strips, and a bunch of closed-loop-feedback +// testing to make sure that if we USE these values, we stay at or under +// the target power consumption. +// Actual power consumption is much, much more complicated and has +// to include things like voltage drop, etc., etc. +// However, this is good enough for most cases, and almost certainly better +// than no power management at all. +// You're welcome to adjust these values as needed; there may eventually be an API +// for changing these on the fly, but it saves codespace and RAM to have them +// be compile-time constants. +static const uint8_t gRed_mW = 16 * 5; // 16mA @ 5v +static const uint8_t gGreen_mW = 14 * 5; // 14mA @ 5v +static const uint8_t gBlue_mW = 14 * 5; // 14mA @ 5v +static const uint8_t gDark_mW = 1 * 5; // 1mA @ 5v + +// Power consumed by the MCU +static const uint8_t gMCU_mW = 25 * 5; // 25mA @ 5v + + +uint32_t gMaxPowerInMilliwatts = (uint32_t)(400) * (uint32_t)(5); // 400mA @ 5v default to avoid USB bricking +uint8_t gMaxPowerIndicatorLEDPinNumber = 13; // default = Arduino onboard LED pin. set to zero to skip this. + + + +uint32_t calculate_unscaled_power_mW( const CRGB* ledbuffer, uint16_t numLeds ) +{ + uint32_t red32 = 0, green32 = 0, blue32 = 0; + const CRGB* firstled = &(ledbuffer[0]); + uint8_t* p = (uint8_t*)(firstled); + + uint16_t count = numLeds; + + for( byte loop256 = (count >> 8) + 1; loop256; loop256--) { + uint16_t red16 = 0, green16 = 0, blue16 = 0; + while( count) { + red16 += *p++; + green16 += *p++; + blue16 += *p++; + count--; + } + red32 += red16; + green32 += green16; + blue32 += blue16; + } + + red32 *= gRed_mW; + green32 *= gGreen_mW; + blue32 *= gBlue_mW; + + red32 >>= 8; + green32 >>= 8; + blue32 >>= 8; + + uint32_t total = red32 + green32 + blue32 + (gDark_mW * numLeds); + + return total; +} + + + +#define POWER_LED 1 + +// sets brightness to +// - no more than target_brightness +// - no more than max_mW milliwatts +uint8_t calculate_max_brightness_for_power_mW( uint8_t target_brightness, uint32_t max_power_mW) +{ + uint32_t total_mW = gMCU_mW; + + CLEDController *pCur = CLEDController::head(); + while(pCur) { + total_mW += calculate_unscaled_power_mW( pCur->leds(), pCur->size()); + pCur = pCur->next(); + } + + uint32_t requested_power_mW = ((uint32_t)total_mW * target_brightness) / 256; + //Serial.print("requested scaled power mW = "); + //Serial.println( requested_power_mW); + //Serial.print("max power mW = "); + //Serial.println( max_power_mW); + + if( requested_power_mW < max_power_mW) { +#if POWER_LED > 0 + if( gMaxPowerIndicatorLEDPinNumber ) { + digitalWrite(gMaxPowerIndicatorLEDPinNumber, LOW); // turn the LED off + } +#endif + return target_brightness; + } + + uint8_t recommended_brightness = (uint32_t)((uint8_t)(target_brightness) * (uint32_t)(max_power_mW)) / ((uint32_t)(requested_power_mW)); + //Serial.print("recommended brightness = "); + //Serial.println( recommended_brightness); +#if POWER_LED > 0 + if( gMaxPowerIndicatorLEDPinNumber ) { + digitalWrite( gMaxPowerIndicatorLEDPinNumber, HIGH); // turn the LED on + } +#endif + + return recommended_brightness; +} + + +void set_max_power_indicator_LED( uint8_t pinNumber) +{ + gMaxPowerIndicatorLEDPinNumber = pinNumber; +} + +void set_max_power_in_volts_and_milliamps( uint8_t volts, uint32_t milliamps) +{ + gMaxPowerInMilliwatts = (uint32_t)((uint32_t)(volts) * milliamps); +} + +void set_max_power_in_milliwatts( uint32_t powerInmW) +{ + gMaxPowerInMilliwatts = powerInmW; +} + +void show_at_max_brightness_for_power() +{ + uint8_t targetBrightness = FastLED.getBrightness(); + uint8_t max = calculate_max_brightness_for_power_mW( targetBrightness, gMaxPowerInMilliwatts); + + FastLED.setBrightness( max ); + FastLED.show(); + FastLED.setBrightness( targetBrightness ); +} + +void delay_at_max_brightness_for_power( uint16_t ms) +{ + uint8_t targetBrightness = FastLED.getBrightness(); + uint8_t max = calculate_max_brightness_for_power_mW( targetBrightness, gMaxPowerInMilliwatts); + + FastLED.setBrightness( max ); + FastLED.delay( ms); + FastLED.setBrightness( targetBrightness ); +} + |