From ff80ebe4db1dd4ae053a79efde8424e8612e88c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phillip=20K=C3=BChne?= Date: Sat, 15 Feb 2025 21:42:41 +0100 Subject: [PATCH] Add power Modeling functions to all components --- src/colorDetection/ColorDetection.cpp | 172 ++++++------ src/colorDetection/ColorDetection.h | 23 +- src/display/Display.cpp | 8 + src/display/Display.h | 13 + src/infraredLight/InfraredLED.cpp | 51 +++- src/infraredLight/InfraredLight.h | 27 +- src/lightDetection/LightDetection.h | 18 +- src/motion/Motion.h | 18 ++ src/motion/Motor.cpp | 13 +- src/motionDetection/MotionDetection.cpp | 11 +- src/motionDetection/MotionDetection.h | 16 ++ src/multiColorLight/MultiColorLight.cpp | 339 +++++++++++++++--------- src/multiColorLight/MultiColorLight.h | 297 +++++++++++++-------- 13 files changed, 672 insertions(+), 334 deletions(-) diff --git a/src/colorDetection/ColorDetection.cpp b/src/colorDetection/ColorDetection.cpp index b350760..eddbaf2 100644 --- a/src/colorDetection/ColorDetection.cpp +++ b/src/colorDetection/ColorDetection.cpp @@ -1,91 +1,103 @@ -#include "ColorDetection.h" +#include "ColorDetection.h" -void ColorDetection::begin(void){ - if(!Power::waitForCurrentAllowance( - PowerParameters::PowerConsumers::RGBW_SENSOR, - PowerParameters::CurrentConsumptions::CURRENT_SENSOR_RGBW, - COLOR_DETECTION_MAX_EXECUTION_DELAY_MS, NULL)){ - ESP_LOGE(TAG,"Could not get power for ColorDetection"); - throw "Could not get power for ColorDetection"; +void ColorDetection::begin(void) { + if (!Power::waitForCurrentAllowance( + PowerParameters::PowerConsumers::RGBW_SENSOR, + PowerParameters::CurrentConsumptions::CURRENT_SENSOR_RGBW, + COLOR_DETECTION_MAX_EXECUTION_DELAY_MS, NULL)) { + ESP_LOGE(TAG, "Could not get power for ColorDetection"); + throw "Could not get power for ColorDetection"; } ColorDetection::configure( VEML_CONFIG{.mode = AUTO, .enabled = true, .exposureTime = MS40}); }; -void ColorDetection::configure(VEML_CONFIG config){ - uint8_t configRegister = 0; - switch(config.exposureTime) - { - case MS40: - configRegister = 0x00;break; - case MS80: - configRegister = 0x01;break; - case MS160: - configRegister = 0x02;break; - case MS320: - configRegister = 0x03;break; - case MS640: - configRegister = 0x04;break; - case MS1280: - configRegister = 0x05;break; - } - configRegister = configRegister << 4; - if(config.mode == MANUAL) - { - configRegister = configRegister | (0x01<<1); - } - if(!config.enabled) - { - configRegister = configRegister | 1; - } - ColorDetection::writeDoubleRegister(CMD_CONFIG,(uint16_t)configRegister); +void ColorDetection::configure(VEML_CONFIG config) { + uint8_t configRegister = 0; + switch (config.exposureTime) { + case MS40: + configRegister = 0x00; + break; + case MS80: + configRegister = 0x01; + break; + case MS160: + configRegister = 0x02; + break; + case MS320: + configRegister = 0x03; + break; + case MS640: + configRegister = 0x04; + break; + case MS1280: + configRegister = 0x05; + break; + } + configRegister = configRegister << 4; + if (config.mode == MANUAL) { + configRegister = configRegister | (0x01 << 1); + } + if (!config.enabled) { + configRegister = configRegister | 1; + } + ColorDetection::writeDoubleRegister(CMD_CONFIG, (uint16_t)configRegister); }; -uint16_t ColorDetection::getColorValue(color color){ - - switch(color) - { - case VEML_RED: - return readDoubleRegister(REG_RED); - break; - case VEML_GREEN: - return readDoubleRegister(REG_GREEN); - break; - case VEML_BLUE: - return readDoubleRegister(REG_BLUE); - break; - case VEML_WHITE: - return readDoubleRegister(REG_WHITE); - break; - default: - Serial.println("Color is not supported by the sensor"); - return 0; - } +uint16_t ColorDetection::getColorValue(color color) { + + switch (color) { + case VEML_RED: + return readDoubleRegister(REG_RED); + break; + case VEML_GREEN: + return readDoubleRegister(REG_GREEN); + break; + case VEML_BLUE: + return readDoubleRegister(REG_BLUE); + break; + case VEML_WHITE: + return readDoubleRegister(REG_WHITE); + break; + default: + Serial.println("Color is not supported by the sensor"); + return 0; + } }; -uint16_t ColorDetection::readDoubleRegister(uint8_t regAddr){ - uint16_t result = 0; - Wire.beginTransmission(VEML_ADDR); - Wire.write(regAddr); - if(Wire.endTransmission() != 0){ - Serial.printf("Reading Register %d failed",regAddr); - } - Wire.requestFrom(VEML_ADDR,2); - uint8_t offset = 0; - while(Wire.available()){ - result = result << 8; - result = result | (Wire.read()<>8)&0x00FF)); - if(Wire.endTransmission() != 0){ - Serial.printf("Reading Register %d failed",regAddr); - } -}; \ No newline at end of file +void ColorDetection::writeDoubleRegister(uint8_t regAddr, uint16_t data) { + // erst low dann high + Wire.beginTransmission(VEML_ADDR); + Wire.write(regAddr); + Wire.write((uint8_t)(data & 0x00FF)); + Wire.write((uint8_t)((data >> 8) & 0x00FF)); + if (Wire.endTransmission() != 0) { + Serial.printf("Reading Register %d failed", regAddr); + } +}; + + +float ColorDetection::modelCurrentConsumption() { + return PowerParameters::CurrentConsumptions::CURRENT_SENSOR_RGBW; +}; + +float ColorDetection::modelChargeConsumption(uint16_t durationMs) { + return PowerParameters::CurrentConsumptions::CURRENT_SENSOR_RGBW * + durationMs * 10e6; +} \ No newline at end of file diff --git a/src/colorDetection/ColorDetection.h b/src/colorDetection/ColorDetection.h index 4030432..4829e79 100644 --- a/src/colorDetection/ColorDetection.h +++ b/src/colorDetection/ColorDetection.h @@ -65,7 +65,28 @@ public: void begin(void); void configure(VEML_CONFIG config); uint16_t getColorValue(color color); -protected: + + /** + * @brief Current consumtion of the sensor + * @note May not be accurate, as it is not known if the consumption is + * constant, or only if sensor is active. Could not be measured. + * + * @return + */ + float modelCurrentConsumption(); + + + /** + * @brief Estimates charge consumption of the sensor for the given duration + * @note May not be accurate, as it is not known if the consumption is + * constant, or only if sensor is active. Could not be measured. + * + * @param durationMs + * @return float + */ + float modelChargeConsumption(uint16_t durationMs); + + protected: uint16_t readDoubleRegister(uint8_t regAddr); void writeDoubleRegister(uint8_t regAddr, uint16_t data); }; diff --git a/src/display/Display.cpp b/src/display/Display.cpp index 9451758..ef906d9 100644 --- a/src/display/Display.cpp +++ b/src/display/Display.cpp @@ -179,3 +179,11 @@ void Display::invertColor(void){ } this->colorInverted = !this->colorInverted; }; + +float modelCurrentConsumption() { + return PowerParameters::CurrentConsumptions::CURRENT_DISPLAY; +}; + +float modelChargeConsumptionOn(uint16_t durationMs) { + return PowerParameters::CurrentConsumptions::CURRENT_DISPLAY * durationMs * 10e6; +}; \ No newline at end of file diff --git a/src/display/Display.h b/src/display/Display.h index f9b439b..387cc35 100644 --- a/src/display/Display.h +++ b/src/display/Display.h @@ -127,6 +127,19 @@ class Display{ * */ void invertColor(void); + + /** + * @brief Estimate the current consumption of the display + * @return consumed current in milliamperes + */ + float modelCurrentConsumption(); + + /** + * @brief Estimate the energy consumption of the display + * @param durationMs time the display will be on + * @return consumed energy in coloumbs + */ + float modelChargeConsumptionOn(uint16_t durationMs); }; diff --git a/src/infraredLight/InfraredLED.cpp b/src/infraredLight/InfraredLED.cpp index 3819a35..53473a0 100644 --- a/src/infraredLight/InfraredLED.cpp +++ b/src/infraredLight/InfraredLED.cpp @@ -4,6 +4,7 @@ #define IR_FRONT_PIN 14 #define IR_BOTTOM_PIN 13 #define DUTY_RESOLUTION LEDC_TIMER_10_BIT +#define DUTY_CYCLE_FREQUENCY 512 InfraredLED::InfraredLED(uint8_t pin,ledc_timer_t timer, ledc_channel_t channel){ this->ledPin = pin; @@ -78,27 +79,53 @@ void InfraredLED::setState(bool state){ }; void InfraredLED::sendFrequency(uint16_t frequency){ - constexpr uint32_t duty = 512; + constexpr uint32_t duty = DUTY_CYCLE_FREQUENCY; // Float to force float division without casting constexpr float resolution = 1 << DUTY_RESOLUTION; if (this->ledPin == IR_BOTTOM_PIN) { - float currentConsumption = - (duty / resolution) * - PowerParameters::CurrentConsumptions::CURRENT_LED_IR_BOTTOM; Power::waitForCurrentAllowance( PowerParameters::PowerConsumers::LED_IR_BOTTOM, - currentConsumption, - IR_LED_MAX_EXECUTION_DELAY_MS, NULL); + this->modelCurrentConsumption(duty), IR_LED_MAX_EXECUTION_DELAY_MS, + NULL); } else if (this->ledPin == IR_FRONT_PIN) { - float currentConsumption = - (duty / resolution) * - PowerParameters::CurrentConsumptions::CURRENT_LED_IR_FRONT; Power::waitForCurrentAllowance( PowerParameters::PowerConsumers::LED_IR_FRONT, - currentConsumption, - IR_LED_MAX_EXECUTION_DELAY_MS, NULL); + this->modelCurrentConsumption(duty), IR_LED_MAX_EXECUTION_DELAY_MS, + NULL); } ledc_set_freq(pwmSpeedMode,timer,frequency); ledc_set_duty(pwmSpeedMode,channel,duty); ledc_update_duty(pwmSpeedMode,channel); -}; \ No newline at end of file +}; + +float InfraredLED::modelCurrentConsumption(uint32_t duty){ + // Float to force float division without casting + constexpr float max_value = 1 << DUTY_RESOLUTION; + const float duty_factor = duty / max_value; + if (this->ledPin == IR_BOTTOM_PIN) { + return duty_factor * PowerParameters::CurrentConsumptions::CURRENT_LED_IR_BOTTOM; + } else if (this->ledPin == IR_FRONT_PIN) { + return duty_factor * PowerParameters::CurrentConsumptions::CURRENT_LED_IR_FRONT; + } + return NAN; +}; + +float InfraredLED::modelChargeConsumptionOn(uint16_t durationMs) { + // Float to force float division without casting + constexpr float resolution = 1 << DUTY_RESOLUTION; + if (this->ledPin == IR_BOTTOM_PIN) { + return durationMs * + PowerParameters::CurrentConsumptions::CURRENT_LED_IR_BOTTOM * 10e6; + } else if (this->ledPin == IR_FRONT_PIN) { + return durationMs * + PowerParameters::CurrentConsumptions::CURRENT_LED_IR_FRONT * 10e6; + } + return NAN; +} + +float InfraredLED::modelChargeConsumptionSendFrequency(uint16_t durationMs) { + // Float to force float division without casting + + return durationMs * this->modelCurrentConsumption(DUTY_CYCLE_FREQUENCY) * + 10e6; +} diff --git a/src/infraredLight/InfraredLight.h b/src/infraredLight/InfraredLight.h index 56ac538..fae6df3 100644 --- a/src/infraredLight/InfraredLight.h +++ b/src/infraredLight/InfraredLight.h @@ -48,7 +48,32 @@ class InfraredLED{ * @param frequency */ void sendFrequency(uint16_t frequency); - protected: + + /** + * @brief Estimate the current consumption of setting the specified led to the + * passed duty cycle + * @param duty the duty cycle of the led + * @return consumed current in milliamperes + */ + float modelCurrentConsumption(uint32_t duty); + + /** + * @brief Estimate the energy consumption of turning the infrared led on + * @param durationMs time the led will be on + * @return consumed energy in coloumbs + */ + float modelChargeConsumptionOn(uint16_t durationMs); + + /** + * @brief Estimate the energy consumption of sending a frequency on the + * infrared led + * @param durationMs time the led will be on + * @param frequency the frequency the led will be flashing + * @return consumed energy in coloumbs + */ + float modelChargeConsumptionSendFrequency(uint16_t durationMs); + + protected: uint8_t ledPin; ledc_timer_t timer; ledc_channel_t channel; diff --git a/src/lightDetection/LightDetection.h b/src/lightDetection/LightDetection.h index 5c64027..49f02bc 100644 --- a/src/lightDetection/LightDetection.h +++ b/src/lightDetection/LightDetection.h @@ -78,7 +78,23 @@ public: * @return the average of all taken meaurments */ static uint32_t getAverageValue(photoTransistors sensor, uint32_t measurments, uint32_t timeBetween); -protected: + + /** + * @brief Get current consumption of the selected PTs + * + * @return float the current consumption of the PTs + */ + static float modelCurrentConsumption(void); + + /** + * @brief Estimate the energy consumption of setting the specified led to + * the passed color + * @param durationMs time the led will be on + * @return consumed energy in coloumbs + */ + float modelChargeConsumptionOn(uint16_t durationMs); + + protected: static const uint8_t IR_PT_FRONT_ADC = 3; static const uint8_t IR_PT_LEFT_ADC = 4; static const uint8_t IR_PT_RIGHT_ADC = 5; diff --git a/src/motion/Motion.h b/src/motion/Motion.h index 2c7c0bd..33650b5 100644 --- a/src/motion/Motion.h +++ b/src/motion/Motion.h @@ -56,6 +56,24 @@ class Motor{ * @return current speedvalue of the motor */ uint16_t getSpeed(void); + + /** + * @brief Get the current consumption of the motor at specified speed + * + * @param duty the duty cyle that should be considered, can be between 0-8192 + * + * @return current consumption in milliamperes + */ + float modelCurrentConsumption(uint16_t duty); + + /** + * @brief Estimate the energy consumption of the display + * @param durationMs time the display will be on + * @return consumed energy in coloumbs + */ + float modelChargeConsumptionOn(uint16_t duty, uint16_t durationMs); + + protected: uint8_t pin; ledc_timer_t timer; diff --git a/src/motion/Motor.cpp b/src/motion/Motor.cpp index 54b5bf6..e58ca95 100644 --- a/src/motion/Motor.cpp +++ b/src/motion/Motor.cpp @@ -25,9 +25,7 @@ void Motor::begin(void) { }; bool Motor::setSpeed(uint16_t duty) { - const float dutyFactor = duty / static_cast(1 << DUTY_RES); - const float current = - PowerParameters::CurrentConsumptions::CURRENT_MOTOR_T_ON * dutyFactor; + const float current = this->modelCurrentConsumption(duty); if (this->pin == MOTOR_LEFT_PIN) { if (!Power::waitForCurrentAllowance( PowerParameters::PowerConsumers::MOTOR_LEFT, current, @@ -69,3 +67,12 @@ bool Motor::setSpeed(uint16_t duty) { }; uint16_t Motor::getSpeed(void) { return this->duty; }; + +float modelCurrentConsumption(uint16_t duty) { + const float dutyFactor = duty / static_cast(1 << DUTY_RES); + return PowerParameters::CurrentConsumptions::CURRENT_MOTOR_T_ON * dutyFactor; +} + +float modelChargeConsumptionOn(uint16_t duty, uint16_t durationMs) { + return modelCurrentConsumption(duty) * durationMs * 10e6; +} diff --git a/src/motionDetection/MotionDetection.cpp b/src/motionDetection/MotionDetection.cpp index 9d83420..e3844f4 100644 --- a/src/motionDetection/MotionDetection.cpp +++ b/src/motionDetection/MotionDetection.cpp @@ -293,4 +293,13 @@ void MotionDetection::writeRegister(uint8_t reg, uint8_t value){ digitalWrite(34,HIGH); delayMicroseconds(10); handler->endTransaction(); -}; \ No newline at end of file +}; + +float MotionDetection::modelCurrentConsumption(){ + return PowerParameters::CurrentConsumptions::CURRENT_IMU; +} + + +float MotionDetection::modelChargeConsumption(uint16_t durationMs){ + return this->modelCurrentConsumption() * durationMs * 10e6; +} \ No newline at end of file diff --git a/src/motionDetection/MotionDetection.h b/src/motionDetection/MotionDetection.h index 4b5b3e6..6b87df7 100644 --- a/src/motionDetection/MotionDetection.h +++ b/src/motionDetection/MotionDetection.h @@ -187,5 +187,21 @@ public: * @return the amount of acutally fetched packages */ uint getDataFromFIFO(FIFO_Package* buffer); + + /** + * @brief Current consumtion of the sensor + * + * @return + */ + float modelCurrentConsumption(); + + + /** + * @brief Estimates charge consumption of the sensor for the given duration + * + * @param durationMs + * @return float + */ + float modelChargeConsumption(uint16_t durationMs); }; #endif //MotionDetection \ No newline at end of file diff --git a/src/multiColorLight/MultiColorLight.cpp b/src/multiColorLight/MultiColorLight.cpp index 03759be..b4ec24c 100644 --- a/src/multiColorLight/MultiColorLight.cpp +++ b/src/multiColorLight/MultiColorLight.cpp @@ -1,142 +1,245 @@ #include "MultiColorLight.h" -MultiColorLight::MultiColorLight():rgbLeds(ledAmount,ledPin){ +MultiColorLight::MultiColorLight() + : rgbLeds(ledAmount, ledPin) { + }; + +void MultiColorLight::begin(void) { + if (!Power::waitForCurrentAllowance( + PowerParameters::PowerConsumers::LED_RGB_TOP_LEFT, + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, + MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL) && + Power::waitForCurrentAllowance( + PowerParameters::PowerConsumers::LED_RGB_TOP_RIGHT, + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, + MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL) && + Power::waitForCurrentAllowance( + PowerParameters::PowerConsumers::LED_RGB_BOTTOM, + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, + MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL)) { + ESP_LOGE(TAG, "Could not get power for MultiColorLight"); + Serial.println("Could not get power for MultiColorLight"); + } + rgbLeds.begin(); + this->turnOffLed(); }; -void MultiColorLight::begin(void){ - if(!Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_TOP_LEFT, PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL) && - Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_TOP_RIGHT, PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL) && - Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_BOTTOM, PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL) ){ - ESP_LOGE(TAG, "Could not get power for MultiColorLight"); - Serial.println("Could not get power for MultiColorLight"); +void MultiColorLight::setLed(uint8_t index, uint32_t color) { + if (index > ledAmount - 1) { + // TODO: logging + } + uint32_t normalizedColor = normalizeColor(color); + float totalConsumption = modelCurrentConsumption(normalizedColor); + switch (index) { + case 0: + if (!Power::waitForCurrentAllowance( + PowerParameters::PowerConsumers::LED_RGB_TOP_RIGHT, + totalConsumption, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL)) { + ESP_LOGW(TAG, + "Power to set LED RGB TOP RIGHT to color 0x%.8X not granted in " + "time. Skipping.", + normalizedColor); + return; } - rgbLeds.begin(); - this->turnOffLed(); + break; + case 1: + if (!Power::waitForCurrentAllowance( + PowerParameters::PowerConsumers::LED_RGB_TOP_LEFT, totalConsumption, + MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL)) { + ESP_LOGW(TAG, + "Power to set LED RGB TOP LEFT to color 0x%.8X not granted in " + "time. Skipping.", + normalizedColor); + return; + } + break; + case 2: + if (!Power::waitForCurrentAllowance( + PowerParameters::PowerConsumers::LED_RGB_BOTTOM, totalConsumption, + MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL)) { + ESP_LOGW(TAG, + "Power to set LED RGB BOTTOM to color 0x%.8X not granted in " + "time. Skipping.", + normalizedColor); + return; + } + break; + } + rgbLeds.setPixelColor(index, normalizedColor); + rgbLeds.show(); }; - -void MultiColorLight::setLed(uint8_t index , uint32_t color){ - if (index > ledAmount-1){ - //TODO: logging +void MultiColorLight::setLed(leds leds, uint32_t color) { + switch (leds) { + case TOP_LEFT: + MultiColorLight::setLed(1, color); + break; + case TOP_RIGHT: + MultiColorLight::setLed(0, color); + break; + case BOTTOM: + MultiColorLight::setLed(2, color); + break; + case TOP: + for (int index = 0; index < 2; index++) { + MultiColorLight::setLed(index, color); } - uint32_t normalizedColor = normalizeColor(color); - uint16_t colorComponentRed = (normalizedColor & 0x00FF0000) >> 16; - uint16_t colorComponentGreen = (normalizedColor & 0x0000FF00) >> 8; - uint16_t colorComponentBlue = (normalizedColor & 0x000000FF); - float redChannelConsumption = (colorComponentRed/255.0) * PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_CHAN_T_ON; - float greenChannelConsumption = (colorComponentGreen/255.0) * PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_CHAN_T_ON; - float blueChannelConsumption = (colorComponentBlue/255.0) * PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_CHAN_T_ON; - float totalConsumption = redChannelConsumption + greenChannelConsumption + blueChannelConsumption + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE; - switch (index) { - case 0: - if(!Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_TOP_RIGHT, totalConsumption, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL)){ - ESP_LOGW(TAG, "Power to set LED RGB TOP RIGHT to color %d not granted in time. Skipping.", color); - return; - } - break; - case 1: - if(!Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_TOP_LEFT, totalConsumption, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL)){ - ESP_LOGW(TAG, "Power to set LED RGB TOP LEFT to color %d not granted in time. Skipping.", color); - return; - } - break; - case 2: - if(!Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_BOTTOM, totalConsumption, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL)){ - ESP_LOGW(TAG, "Power to set LED RGB BOTTOM to color %d not granted in time. Skipping.", color); - return; - } - break; + break; + case ALL: + for (int index = 0; index < ledAmount; index++) { + MultiColorLight::setLed(index, color); } - rgbLeds.setPixelColor(index, normalizedColor); - rgbLeds.show(); + break; + default: + // TODO logging + break; + } }; - -void MultiColorLight::setLed(leds leds, uint32_t color){ - switch (leds){ - case TOP_LEFT: - MultiColorLight::setLed(1,color);break; - case TOP_RIGHT: - MultiColorLight::setLed(0,color);break; - case BOTTOM: - MultiColorLight::setLed(2,color);break; - case TOP: - for (int index = 0; index<2; index++){ - MultiColorLight::setLed(index,color); - }break; - case ALL: - for (int index = 0; index>16; - uint8_t green = (color&0x0000FF00)>>8; - uint8_t blue = (color&0x000000FF); - if (red > maxBrightness){ - red = maxBrightness; +uint32_t MultiColorLight::color(uint8_t r, uint8_t g, uint8_t b) { + return rgbLeds.Color(r, g, b); +}; + +// PRIVATE +uint32_t MultiColorLight::normalizeColor(uint32_t color, + uint8_t maxBrightness) { + uint8_t red = (color & 0x00FF0000) >> 16; + uint8_t green = (color & 0x0000FF00) >> 8; + uint8_t blue = (color & 0x000000FF); + if (red > maxBrightness) { + red = maxBrightness; + } + if (green > maxBrightness - 70) { + green = maxBrightness - 70; + } + if (blue > maxBrightness - 50) { + blue = maxBrightness - 50; + } + return MultiColorLight::color(red, green, blue); +}; + +float MultiColorLight::modelCurrentConsumption(uint32_t color) { + uint32_t normalizedColor = normalizeColor(color); + uint16_t colorComponentRed = (normalizedColor & 0x00FF0000) >> 16; + uint16_t colorComponentGreen = (normalizedColor & 0x0000FF00) >> 8; + uint16_t colorComponentBlue = (normalizedColor & 0x000000FF); + float redChannelConsumption = + (colorComponentRed / 255.0) * + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_CHAN_T_ON; + float greenChannelConsumption = + (colorComponentGreen / 255.0) * + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_CHAN_T_ON; + float blueChannelConsumption = + (colorComponentBlue / 255.0) * + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_CHAN_T_ON; + return redChannelConsumption + greenChannelConsumption + + blueChannelConsumption + + PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE; +}; + +float MultiColorLight::modelCurrentConsumption(uint8_t red, uint8_t green, + uint8_t blue) { + return modelCurrentConsumption(MultiColorLight::color(red, green, blue)); +}; + +float MultiColorLight::modelChargeConsumption(uint8_t index, uint32_t color, + uint16_t durationMs) { + if (index > ledAmount - 1) { + // TODO: logging + } + uint32_t normalizedColor = normalizeColor(color); + float ledConsumption = modelCurrentConsumption(normalizedColor); + return ledConsumption * durationMs * 10e6; +}; + +float MultiColorLight::modelChargeConsumption(leds leds, uint32_t color, + uint16_t durationMs) { + float ledsConsumption = 0; + switch (leds) { + case TOP_LEFT: + ledsConsumption = + MultiColorLight::modelChargeConsumption(1, color, durationMs); + break; + case TOP_RIGHT: + ledsConsumption = + MultiColorLight::modelChargeConsumption(0, color, durationMs); + break; + case BOTTOM: + ledsConsumption = + MultiColorLight::modelChargeConsumption(2, color, durationMs); + break; + case TOP: + for (int index = 0; index < 2; index++) { + ledsConsumption += + MultiColorLight::modelChargeConsumption(index, color, durationMs); } - if(green > maxBrightness-70){ - green = maxBrightness-70; + break; + case ALL: + for (int index = 0; index < ledAmount; index++) { + ledsConsumption += + MultiColorLight::modelChargeConsumption(index, color, durationMs); } - if(blue > maxBrightness-50){ - blue = maxBrightness-50; - } - return MultiColorLight::color(red,green,blue); -} \ No newline at end of file + break; + default: + // TODO logging + break; + } +}; + +float MultiColorLight::modelChargeConsumption(leds leds, uint8_t red, + uint8_t green, uint8_t blue, + uint16_t durationMs) { + return MultiColorLight::modelChargeConsumption( + leds, MultiColorLight::color(red, green, blue), durationMs); +}; \ No newline at end of file diff --git a/src/multiColorLight/MultiColorLight.h b/src/multiColorLight/MultiColorLight.h index 562958a..76ba711 100644 --- a/src/multiColorLight/MultiColorLight.h +++ b/src/multiColorLight/MultiColorLight.h @@ -1,146 +1,209 @@ /** * @file MultiColorLight.h * @author Saskia Duebener, Hans Haupt - * @brief This component controls the ability to show multicolored light, using the RGB-LEDs + * @brief This component controls the ability to show multicolored light, using + * the RGB-LEDs * @version 0.2 * @date 2023-11-25 - * + * * @copyright Copyright (c) 2023 - * + * */ #ifndef MultiColorLight_h #define MultiColorLight_h -#include -#include "ColorConstants.h" #include "../power/Power.h" +#include "ColorConstants.h" +#include #define MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS 20 /** - * @brief Describes combinations of leds on the Dezibot. - * With the Robot in Front of you, when the robot drives away from you, the left LED is TOP_LEFT - * + * @brief Describes combinations of leds on the Dezibot. + * With the Robot in Front of you, when the robot drives away from you, the left + * LED is TOP_LEFT + * */ -enum leds{ - TOP_LEFT, - TOP_RIGHT, - BOTTOM, - TOP, - ALL -}; +enum leds { TOP_LEFT, TOP_RIGHT, BOTTOM, TOP, ALL }; #define TAG "MultiColorLight" -class MultiColorLight{ +class MultiColorLight { protected: - static const uint16_t ledAmount = 3; - static const int16_t ledPin = 48; - static const uint8_t maxBrightness = 150; - Adafruit_NeoPixel rgbLeds; - static constexpr int maximumExecutionDelayMs = 10; + static const uint16_t ledAmount = 3; + static const int16_t ledPin = 48; + static const uint8_t maxBrightness = 150; + Adafruit_NeoPixel rgbLeds; + static constexpr int maximumExecutionDelayMs = 10; + public: - - MultiColorLight(); - /** - * @brief initialize the multicolor component - * - */ - void begin(void); + MultiColorLight(); + /** + * @brief initialize the multicolor component + * + */ + void begin(void); - /** - * @brief Set the specified led to the passed color - * @param index ranging from 0-2, 0: Right, 1: Left, 2: Bottom - * @param color A 32-bit unsigned integer representing the color in the format - * 0x00RRGGBB, where RR is the red component, GG is the green - * component, and BB is the blue component. Each color can range between 0 to 100 - */ - void setLed(uint8_t index , uint32_t color); + /** + * @brief Set the specified led to the passed color + * @param index ranging from 0-2, 0: Right, 1: Left, 2: Bottom + * @param color A 32-bit unsigned integer representing the color in the format + * 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. Each color can range + * between 0 to 100 + */ + void setLed(uint8_t index, uint32_t color); - /** - * @brief Set the specified leds to the passed color value - * - * @param leds which leds should be updated - * @param color A 32-bit unsigned integer representing the color in the format - * 0x00RRGGBB, where RR is the red component, GG is the green - * component, and BB is the blue component. Each color can range between 0 to 100 - */ - void setLed(leds leds, uint32_t color); + /** + * @brief Set the specified leds to the passed color value + * + * @param leds which leds should be updated + * @param color A 32-bit unsigned integer representing the color in the format + * 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. Each color can range + * between 0 to 100 + */ + void setLed(leds leds, uint32_t color); - /** - * @brief Set the specified leds to the passed color value - * - * @param leds which leds should be updated - * @param red brightness of red, is normalized in the function - * @param green brightness of green, is normalized in the function - * @param blue brightness of blue, is normalized in the function - */ - void setLed(leds leds, uint8_t red, uint8_t green, uint8_t blue); - - /** - * @brief sets the two leds on the top of the robot to the specified color - * - * @param color A 32-bit unsigned integer representing the color in the format - * 0x00RRGGBB, where RR is the red component, GG is the green - * component, and BB is the blue component. Each color can range between 0 to 100 - */ - void setTopLeds(uint32_t color); + /** + * @brief Set the specified leds to the passed color value + * + * @param leds which leds should be updated + * @param red brightness of red, is normalized in the function + * @param green brightness of green, is normalized in the function + * @param blue brightness of blue, is normalized in the function + */ + void setLed(leds leds, uint8_t red, uint8_t green, uint8_t blue); - /** - * @brief sets the two leds on the top of the robot to the specified color - * - * @param red brightness of red, is normalized in the function - * @param green brightness of green, is normalized in the function - * @param blue brightness of blue, is normalized in the function - */ - void setTopLeds(uint8_t red, uint8_t green, uint8_t blue); - - /** - * @brief Let LEDs blink, returns after all blinks were executed - * - * @param amount how often should the leds blink - * @param color A 32-bit unsigned integer representing the color in the format - * 0x00RRGGBB, where RR is the red component, GG is the green - * component, and BB is the blue component. - * Each color can range between 0 to 100 - * Defaults to blue - * @param leds which LEDs should blink, default is TOP - * @param interval how many miliseconds the led is on, defaults to 1s - */ - void blink(uint16_t amount,uint32_t color = 0x00006400,leds leds=TOP, uint32_t interval=1000); + /** + * @brief calculates the current consumption of an LED with the given color + * + * @param color A 32-bit unsigned integer representing the color in the + * format 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. + * @return float the current consumption in mA + */ + float modelCurrentConsumption(uint32_t color); - /** - * @brief turn off the given leds - * - * @param leds which leds should be turned off, defaults to ALL - */ - void turnOffLed(leds leds=ALL); - - /** - * @brief wrapper to calulate the used colorformat from a rgb-value - * - * @param r red (0-100) - * @param g green (0-100) - * @param b blue (0-100) - * @return A 32-bit unsigned integer representing the color in the format - * 0x00RRGGBB, where RR is the red component, GG is the green - * component, and BB is the blue component. - */ - uint32_t color(uint8_t r, uint8_t g, uint8_t b); + /** + * @brief calculates the current consumption of an LED with the given color + * @note color is not normalized in this function + * + * @param red brightness of red + * @param green brightness of green + * @param blue brightness of blue + * @return float the current consumption in mA + */ + float modelCurrentConsumption(uint8_t red, uint8_t green, uint8_t blue); + + /** + * @brief Estimate the energy consumption of setting the specified led to the + * passed color + * @param index ranging from 0-2, 0: Right, 1: Left, 2: Bottom + * @param color A 32-bit unsigned integer representing the color in the + * format 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. Each color can + * range between 0 to 100 + * @return consumed energy in coloumbs + */ + float modelChargeConsumption(uint8_t index, uint32_t color, + uint16_t durationMs); + + /** + * @brief Estimate the energy consumption of setting the specified leds to the + * passed color value + * + * @param leds which leds should be considered + * @param color A 32-bit unsigned integer representing the color in the + * format 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. Each color can + * range between 0 to 100 + * @return consumed energy in coloumbs + */ + float modelChargeConsumption(leds leds, uint32_t color, + uint16_t durationMs); + + /** + * @brief Estimate the energy consumption of setting the specified leds to the + * passed color value + * + * @param leds which leds should be considered + * @param red brightness of red, is normalized in the function + * @param green brightness of green, is normalized in the function + * @param blue brightness of blue, is normalized in the function + * @return consumed energy in coloumbs + */ + float modelChargeConsumption(leds leds, uint8_t red, uint8_t green, + uint8_t blue, uint16_t durationMs); + + /** + * @brief sets the two leds on the top of the robot to the specified color + * + * @param color A 32-bit unsigned integer representing the color in the format + * 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. Each color can range + * between 0 to 100 + */ + void setTopLeds(uint32_t color); + + /** + * @brief sets the two leds on the top of the robot to the specified color + * + * @param red brightness of red, is normalized in the function + * @param green brightness of green, is normalized in the function + * @param blue brightness of blue, is normalized in the function + */ + void setTopLeds(uint8_t red, uint8_t green, uint8_t blue); + + /** + * @brief Let LEDs blink, returns after all blinks were executed + * + * @param amount how often should the leds blink + * @param color A 32-bit unsigned integer representing the color in the format + * 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. + * Each color can range between 0 to 100 + * Defaults to blue + * @param leds which LEDs should blink, default is TOP + * @param interval how many miliseconds the led is on, defaults to 1s + */ + void blink(uint16_t amount, uint32_t color = 0x00006400, leds leds = TOP, + uint32_t interval = 1000); + + /** + * @brief turn off the given leds + * + * @param leds which leds should be turned off, defaults to ALL + */ + void turnOffLed(leds leds = ALL); + + /** + * @brief wrapper to calulate the used colorformat from a rgb-value + * + * @param r red (0-100) + * @param g green (0-100) + * @param b blue (0-100) + * @return A 32-bit unsigned integer representing the color in the format + * 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. + */ + uint32_t color(uint8_t r, uint8_t g, uint8_t b); private: - /** - * @brief normalizes every component of color to not exeed the maxBrightness - * - * @param color A 32-bit unsigned integer representing the color in the format - * 0x00RRGGBB, where RR is the red component, GG is the green - * component, and BB is the blue component. - * @param maxBrigthness maximal level of brightness that is allowed for each color - * @return uint32_t A 32-bit unsigned integer representing the color in the format - * 0x00RRGGBB, where RR is the red component, GG is the green - * component, and BB is the blue component. Where each component can be - * between 0 - maxBrightness - */ - uint32_t normalizeColor(uint32_t color, uint8_t maxBrigthness=maxBrightness); + /** + * @brief normalizes every component of color to not exeed the maxBrightness + * + * @param color A 32-bit unsigned integer representing the color in the format + * 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. + * @param maxBrigthness maximal level of brightness that is allowed for each + * color + * @return uint32_t A 32-bit unsigned integer representing the color in the + * format 0x00RRGGBB, where RR is the red component, GG is the green + * component, and BB is the blue component. Where each component + * can be between 0 - maxBrightness + */ + uint32_t normalizeColor(uint32_t color, + uint8_t maxBrigthness = maxBrightness); }; -#endif //MultiColorLight_h \ No newline at end of file +#endif // MultiColorLight_h \ No newline at end of file