PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.6KB

  1. #define FASTLED_INTERNAL
  2. #include "FastLED.h"
  3. #include "power_mgt.h"
  4. FASTLED_NAMESPACE_BEGIN
  5. //// POWER MANAGEMENT
  6. // These power usage values are approximate, and your exact readings
  7. // will be slightly (10%?) different from these.
  8. //
  9. // They were arrived at by actually measuing the power draw of a number
  10. // of different LED strips, and a bunch of closed-loop-feedback testing
  11. // to make sure that if we USE these values, we stay at or under
  12. // the target power consumption.
  13. // Actual power consumption is much, much more complicated and has
  14. // to include things like voltage drop, etc., etc.
  15. // However, this is good enough for most cases, and almost certainly better
  16. // than no power management at all.
  17. //
  18. // You're welcome to adjust these values as needed; there may eventually be an API
  19. // for changing these on the fly, but it saves codespace and RAM to have them
  20. // be compile-time constants.
  21. static const uint8_t gRed_mW = 16 * 5; // 16mA @ 5v = 80mW
  22. static const uint8_t gGreen_mW = 11 * 5; // 11mA @ 5v = 55mW
  23. static const uint8_t gBlue_mW = 15 * 5; // 15mA @ 5v = 75mW
  24. static const uint8_t gDark_mW = 1 * 5; // 1mA @ 5v = 5mW
  25. // Alternate calibration by RAtkins via pre-PSU wattage measurments;
  26. // these are all probably about 20%-25% too high due to PSU heat losses,
  27. // but if you're measuring wattage on the PSU input side, this may
  28. // be a better set of calibrations. (WS2812B)
  29. // static const uint8_t gRed_mW = 100;
  30. // static const uint8_t gGreen_mW = 48;
  31. // static const uint8_t gBlue_mW = 100;
  32. // static const uint8_t gDark_mW = 12;
  33. #define POWER_LED 1
  34. #define POWER_DEBUG_PRINT 0
  35. // Power consumed by the MCU
  36. static const uint8_t gMCU_mW = 25 * 5; // 25mA @ 5v = 125 mW
  37. static uint8_t gMaxPowerIndicatorLEDPinNumber = 0; // default = Arduino onboard LED pin. set to zero to skip this.
  38. uint32_t calculate_unscaled_power_mW( const CRGB* ledbuffer, uint16_t numLeds ) //25354
  39. {
  40. uint32_t red32 = 0, green32 = 0, blue32 = 0;
  41. const CRGB* firstled = &(ledbuffer[0]);
  42. uint8_t* p = (uint8_t*)(firstled);
  43. uint16_t count = numLeds;
  44. // This loop might benefit from an AVR assembly version -MEK
  45. while( count) {
  46. red32 += *p++;
  47. green32 += *p++;
  48. blue32 += *p++;
  49. count--;
  50. }
  51. red32 *= gRed_mW;
  52. green32 *= gGreen_mW;
  53. blue32 *= gBlue_mW;
  54. red32 >>= 8;
  55. green32 >>= 8;
  56. blue32 >>= 8;
  57. uint32_t total = red32 + green32 + blue32 + (gDark_mW * numLeds);
  58. return total;
  59. }
  60. uint8_t calculate_max_brightness_for_power_vmA(const CRGB* ledbuffer, uint16_t numLeds, uint8_t target_brightness, uint32_t max_power_V, uint32_t max_power_mA) {
  61. return calculate_max_brightness_for_power_mW(ledbuffer, numLeds, target_brightness, max_power_V * max_power_mA);
  62. }
  63. uint8_t calculate_max_brightness_for_power_mW(const CRGB* ledbuffer, uint16_t numLeds, uint8_t target_brightness, uint32_t max_power_mW) {
  64. uint32_t total_mW = calculate_unscaled_power_mW( ledbuffer, numLeds);
  65. uint32_t requested_power_mW = ((uint32_t)total_mW * target_brightness) / 256;
  66. uint8_t recommended_brightness = target_brightness;
  67. if(requested_power_mW > max_power_mW) {
  68. recommended_brightness = (uint32_t)((uint8_t)(target_brightness) * (uint32_t)(max_power_mW)) / ((uint32_t)(requested_power_mW));
  69. }
  70. return recommended_brightness;
  71. }
  72. // sets brightness to
  73. // - no more than target_brightness
  74. // - no more than max_mW milliwatts
  75. uint8_t calculate_max_brightness_for_power_mW( uint8_t target_brightness, uint32_t max_power_mW)
  76. {
  77. uint32_t total_mW = gMCU_mW;
  78. CLEDController *pCur = CLEDController::head();
  79. while(pCur) {
  80. total_mW += calculate_unscaled_power_mW( pCur->leds(), pCur->size());
  81. pCur = pCur->next();
  82. }
  83. #if POWER_DEBUG_PRINT == 1
  84. Serial.print("power demand at full brightness mW = ");
  85. Serial.println( total_mW);
  86. #endif
  87. uint32_t requested_power_mW = ((uint32_t)total_mW * target_brightness) / 256;
  88. #if POWER_DEBUG_PRINT == 1
  89. if( target_brightness != 255 ) {
  90. Serial.print("power demand at scaled brightness mW = ");
  91. Serial.println( requested_power_mW);
  92. }
  93. Serial.print("power limit mW = ");
  94. Serial.println( max_power_mW);
  95. #endif
  96. if( requested_power_mW < max_power_mW) {
  97. #if POWER_LED > 0
  98. if( gMaxPowerIndicatorLEDPinNumber ) {
  99. Pin(gMaxPowerIndicatorLEDPinNumber).lo(); // turn the LED off
  100. }
  101. #endif
  102. #if POWER_DEBUG_PRINT == 1
  103. Serial.print("demand is under the limit");
  104. #endif
  105. return target_brightness;
  106. }
  107. uint8_t recommended_brightness = (uint32_t)((uint8_t)(target_brightness) * (uint32_t)(max_power_mW)) / ((uint32_t)(requested_power_mW));
  108. #if POWER_DEBUG_PRINT == 1
  109. Serial.print("recommended brightness # = ");
  110. Serial.println( recommended_brightness);
  111. uint32_t resultant_power_mW = (total_mW * recommended_brightness) / 256;
  112. Serial.print("resultant power demand mW = ");
  113. Serial.println( resultant_power_mW);
  114. Serial.println();
  115. #endif
  116. #if POWER_LED > 0
  117. if( gMaxPowerIndicatorLEDPinNumber ) {
  118. Pin(gMaxPowerIndicatorLEDPinNumber).hi(); // turn the LED on
  119. }
  120. #endif
  121. return recommended_brightness;
  122. }
  123. void set_max_power_indicator_LED( uint8_t pinNumber)
  124. {
  125. gMaxPowerIndicatorLEDPinNumber = pinNumber;
  126. }
  127. void set_max_power_in_volts_and_milliamps( uint8_t volts, uint32_t milliamps)
  128. {
  129. FastLED.setMaxPowerInVoltsAndMilliamps(volts, milliamps);
  130. }
  131. void set_max_power_in_milliwatts( uint32_t powerInmW)
  132. {
  133. FastLED.setMaxPowerInMilliWatts(powerInmW);
  134. }
  135. void show_at_max_brightness_for_power()
  136. {
  137. // power management usage is now in FastLED.show, no need for this function
  138. FastLED.show();
  139. }
  140. void delay_at_max_brightness_for_power( uint16_t ms)
  141. {
  142. FastLED.delay(ms);
  143. }
  144. FASTLED_NAMESPACE_END