Add power Modeling functions to all components

This commit is contained in:
2025-02-15 21:42:41 +01:00
parent 5cb25a412a
commit ff80ebe4db
13 changed files with 672 additions and 334 deletions

View File

@ -1,91 +1,103 @@
#include "ColorDetection.h" #include "ColorDetection.h"
void ColorDetection::begin(void){ void ColorDetection::begin(void) {
if(!Power::waitForCurrentAllowance( if (!Power::waitForCurrentAllowance(
PowerParameters::PowerConsumers::RGBW_SENSOR, PowerParameters::PowerConsumers::RGBW_SENSOR,
PowerParameters::CurrentConsumptions::CURRENT_SENSOR_RGBW, PowerParameters::CurrentConsumptions::CURRENT_SENSOR_RGBW,
COLOR_DETECTION_MAX_EXECUTION_DELAY_MS, NULL)){ COLOR_DETECTION_MAX_EXECUTION_DELAY_MS, NULL)) {
ESP_LOGE(TAG,"Could not get power for ColorDetection"); ESP_LOGE(TAG, "Could not get power for ColorDetection");
throw "Could not get power for ColorDetection"; throw "Could not get power for ColorDetection";
} }
ColorDetection::configure( ColorDetection::configure(
VEML_CONFIG{.mode = AUTO, .enabled = true, .exposureTime = MS40}); VEML_CONFIG{.mode = AUTO, .enabled = true, .exposureTime = MS40});
}; };
void ColorDetection::configure(VEML_CONFIG config){ void ColorDetection::configure(VEML_CONFIG config) {
uint8_t configRegister = 0; uint8_t configRegister = 0;
switch(config.exposureTime) switch (config.exposureTime) {
{ case MS40:
case MS40: configRegister = 0x00;
configRegister = 0x00;break; break;
case MS80: case MS80:
configRegister = 0x01;break; configRegister = 0x01;
case MS160: break;
configRegister = 0x02;break; case MS160:
case MS320: configRegister = 0x02;
configRegister = 0x03;break; break;
case MS640: case MS320:
configRegister = 0x04;break; configRegister = 0x03;
case MS1280: break;
configRegister = 0x05;break; case MS640:
} configRegister = 0x04;
configRegister = configRegister << 4; break;
if(config.mode == MANUAL) case MS1280:
{ configRegister = 0x05;
configRegister = configRegister | (0x01<<1); break;
} }
if(!config.enabled) configRegister = configRegister << 4;
{ if (config.mode == MANUAL) {
configRegister = configRegister | 1; configRegister = configRegister | (0x01 << 1);
} }
ColorDetection::writeDoubleRegister(CMD_CONFIG,(uint16_t)configRegister); if (!config.enabled) {
configRegister = configRegister | 1;
}
ColorDetection::writeDoubleRegister(CMD_CONFIG, (uint16_t)configRegister);
}; };
uint16_t ColorDetection::getColorValue(color color){ uint16_t ColorDetection::getColorValue(color color) {
switch(color) switch (color) {
{ case VEML_RED:
case VEML_RED: return readDoubleRegister(REG_RED);
return readDoubleRegister(REG_RED); break;
break; case VEML_GREEN:
case VEML_GREEN: return readDoubleRegister(REG_GREEN);
return readDoubleRegister(REG_GREEN); break;
break; case VEML_BLUE:
case VEML_BLUE: return readDoubleRegister(REG_BLUE);
return readDoubleRegister(REG_BLUE); break;
break; case VEML_WHITE:
case VEML_WHITE: return readDoubleRegister(REG_WHITE);
return readDoubleRegister(REG_WHITE); break;
break; default:
default: Serial.println("Color is not supported by the sensor");
Serial.println("Color is not supported by the sensor"); return 0;
return 0; }
}
}; };
uint16_t ColorDetection::readDoubleRegister(uint8_t regAddr){ uint16_t ColorDetection::readDoubleRegister(uint8_t regAddr) {
uint16_t result = 0; uint16_t result = 0;
Wire.beginTransmission(VEML_ADDR); Wire.beginTransmission(VEML_ADDR);
Wire.write(regAddr); Wire.write(regAddr);
if(Wire.endTransmission() != 0){ if (Wire.endTransmission() != 0) {
Serial.printf("Reading Register %d failed",regAddr); Serial.printf("Reading Register %d failed", regAddr);
} }
Wire.requestFrom(VEML_ADDR,2); Wire.requestFrom(VEML_ADDR, 2);
uint8_t offset = 0; uint8_t offset = 0;
while(Wire.available()){ while (Wire.available()) {
result = result << 8; result = result << 8;
result = result | (Wire.read()<<offset); result = result | (Wire.read() << offset);
offset = offset + 8; offset = offset + 8;
} }
return result; return result;
}; };
void ColorDetection::writeDoubleRegister(uint8_t regAddr, uint16_t data){ void ColorDetection::writeDoubleRegister(uint8_t regAddr, uint16_t data) {
//erst low dann high // erst low dann high
Wire.beginTransmission(VEML_ADDR); Wire.beginTransmission(VEML_ADDR);
Wire.write(regAddr); Wire.write(regAddr);
Wire.write((uint8_t)(data&0x00FF)); Wire.write((uint8_t)(data & 0x00FF));
Wire.write((uint8_t)((data>>8)&0x00FF)); Wire.write((uint8_t)((data >> 8) & 0x00FF));
if(Wire.endTransmission() != 0){ if (Wire.endTransmission() != 0) {
Serial.printf("Reading Register %d failed",regAddr); 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;
}

View File

@ -65,7 +65,28 @@ public:
void begin(void); void begin(void);
void configure(VEML_CONFIG config); void configure(VEML_CONFIG config);
uint16_t getColorValue(color color); 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); uint16_t readDoubleRegister(uint8_t regAddr);
void writeDoubleRegister(uint8_t regAddr, uint16_t data); void writeDoubleRegister(uint8_t regAddr, uint16_t data);
}; };

View File

@ -179,3 +179,11 @@ void Display::invertColor(void){
} }
this->colorInverted = !this->colorInverted; this->colorInverted = !this->colorInverted;
}; };
float modelCurrentConsumption() {
return PowerParameters::CurrentConsumptions::CURRENT_DISPLAY;
};
float modelChargeConsumptionOn(uint16_t durationMs) {
return PowerParameters::CurrentConsumptions::CURRENT_DISPLAY * durationMs * 10e6;
};

View File

@ -127,6 +127,19 @@ class Display{
* *
*/ */
void invertColor(void); 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);
}; };

View File

@ -4,6 +4,7 @@
#define IR_FRONT_PIN 14 #define IR_FRONT_PIN 14
#define IR_BOTTOM_PIN 13 #define IR_BOTTOM_PIN 13
#define DUTY_RESOLUTION LEDC_TIMER_10_BIT #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){ InfraredLED::InfraredLED(uint8_t pin,ledc_timer_t timer, ledc_channel_t channel){
this->ledPin = pin; this->ledPin = pin;
@ -78,27 +79,53 @@ void InfraredLED::setState(bool state){
}; };
void InfraredLED::sendFrequency(uint16_t frequency){ 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 // Float to force float division without casting
constexpr float resolution = 1 << DUTY_RESOLUTION; constexpr float resolution = 1 << DUTY_RESOLUTION;
if (this->ledPin == IR_BOTTOM_PIN) { if (this->ledPin == IR_BOTTOM_PIN) {
float currentConsumption =
(duty / resolution) *
PowerParameters::CurrentConsumptions::CURRENT_LED_IR_BOTTOM;
Power::waitForCurrentAllowance( Power::waitForCurrentAllowance(
PowerParameters::PowerConsumers::LED_IR_BOTTOM, PowerParameters::PowerConsumers::LED_IR_BOTTOM,
currentConsumption, this->modelCurrentConsumption(duty), IR_LED_MAX_EXECUTION_DELAY_MS,
IR_LED_MAX_EXECUTION_DELAY_MS, NULL); NULL);
} else if (this->ledPin == IR_FRONT_PIN) { } else if (this->ledPin == IR_FRONT_PIN) {
float currentConsumption =
(duty / resolution) *
PowerParameters::CurrentConsumptions::CURRENT_LED_IR_FRONT;
Power::waitForCurrentAllowance( Power::waitForCurrentAllowance(
PowerParameters::PowerConsumers::LED_IR_FRONT, PowerParameters::PowerConsumers::LED_IR_FRONT,
currentConsumption, this->modelCurrentConsumption(duty), IR_LED_MAX_EXECUTION_DELAY_MS,
IR_LED_MAX_EXECUTION_DELAY_MS, NULL); NULL);
} }
ledc_set_freq(pwmSpeedMode,timer,frequency); ledc_set_freq(pwmSpeedMode,timer,frequency);
ledc_set_duty(pwmSpeedMode,channel,duty); ledc_set_duty(pwmSpeedMode,channel,duty);
ledc_update_duty(pwmSpeedMode,channel); ledc_update_duty(pwmSpeedMode,channel);
}; };
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;
}

View File

@ -48,7 +48,32 @@ class InfraredLED{
* @param frequency * @param frequency
*/ */
void sendFrequency(uint16_t 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; uint8_t ledPin;
ledc_timer_t timer; ledc_timer_t timer;
ledc_channel_t channel; ledc_channel_t channel;

View File

@ -78,7 +78,23 @@ public:
* @return the average of all taken meaurments * @return the average of all taken meaurments
*/ */
static uint32_t getAverageValue(photoTransistors sensor, uint32_t measurments, uint32_t timeBetween); 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_FRONT_ADC = 3;
static const uint8_t IR_PT_LEFT_ADC = 4; static const uint8_t IR_PT_LEFT_ADC = 4;
static const uint8_t IR_PT_RIGHT_ADC = 5; static const uint8_t IR_PT_RIGHT_ADC = 5;

View File

@ -56,6 +56,24 @@ class Motor{
* @return current speedvalue of the motor * @return current speedvalue of the motor
*/ */
uint16_t getSpeed(void); 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: protected:
uint8_t pin; uint8_t pin;
ledc_timer_t timer; ledc_timer_t timer;

View File

@ -25,9 +25,7 @@ void Motor::begin(void) {
}; };
bool Motor::setSpeed(uint16_t duty) { bool Motor::setSpeed(uint16_t duty) {
const float dutyFactor = duty / static_cast<float>(1 << DUTY_RES); const float current = this->modelCurrentConsumption(duty);
const float current =
PowerParameters::CurrentConsumptions::CURRENT_MOTOR_T_ON * dutyFactor;
if (this->pin == MOTOR_LEFT_PIN) { if (this->pin == MOTOR_LEFT_PIN) {
if (!Power::waitForCurrentAllowance( if (!Power::waitForCurrentAllowance(
PowerParameters::PowerConsumers::MOTOR_LEFT, current, PowerParameters::PowerConsumers::MOTOR_LEFT, current,
@ -69,3 +67,12 @@ bool Motor::setSpeed(uint16_t duty) {
}; };
uint16_t Motor::getSpeed(void) { return this->duty; }; uint16_t Motor::getSpeed(void) { return this->duty; };
float modelCurrentConsumption(uint16_t duty) {
const float dutyFactor = duty / static_cast<float>(1 << DUTY_RES);
return PowerParameters::CurrentConsumptions::CURRENT_MOTOR_T_ON * dutyFactor;
}
float modelChargeConsumptionOn(uint16_t duty, uint16_t durationMs) {
return modelCurrentConsumption(duty) * durationMs * 10e6;
}

View File

@ -293,4 +293,13 @@ void MotionDetection::writeRegister(uint8_t reg, uint8_t value){
digitalWrite(34,HIGH); digitalWrite(34,HIGH);
delayMicroseconds(10); delayMicroseconds(10);
handler->endTransaction(); handler->endTransaction();
}; };
float MotionDetection::modelCurrentConsumption(){
return PowerParameters::CurrentConsumptions::CURRENT_IMU;
}
float MotionDetection::modelChargeConsumption(uint16_t durationMs){
return this->modelCurrentConsumption() * durationMs * 10e6;
}

View File

@ -187,5 +187,21 @@ public:
* @return the amount of acutally fetched packages * @return the amount of acutally fetched packages
*/ */
uint getDataFromFIFO(FIFO_Package* buffer); 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 #endif //MotionDetection

View File

@ -1,142 +1,245 @@
#include "MultiColorLight.h" #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){ void MultiColorLight::setLed(uint8_t index, uint32_t color) {
if(!Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_TOP_LEFT, PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL) && if (index > ledAmount - 1) {
Power::waitForCurrentAllowance(PowerParameters::PowerConsumers::LED_RGB_TOP_RIGHT, PowerParameters::CurrentConsumptions::CURRENT_LED_RGB_BASE, MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS, NULL) && // TODO: logging
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"); uint32_t normalizedColor = normalizeColor(color);
Serial.println("Could not get power for MultiColorLight"); 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(); break;
this->turnOffLed(); 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(leds leds, uint32_t color) {
void MultiColorLight::setLed(uint8_t index , uint32_t color){ switch (leds) {
if (index > ledAmount-1){ case TOP_LEFT:
//TODO: logging 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); break;
uint16_t colorComponentRed = (normalizedColor & 0x00FF0000) >> 16; case ALL:
uint16_t colorComponentGreen = (normalizedColor & 0x0000FF00) >> 8; for (int index = 0; index < ledAmount; index++) {
uint16_t colorComponentBlue = (normalizedColor & 0x000000FF); MultiColorLight::setLed(index, color);
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;
} }
rgbLeds.setPixelColor(index, normalizedColor); break;
rgbLeds.show(); default:
// TODO logging
break;
}
}; };
void MultiColorLight::setLed(leds leds, uint8_t red, uint8_t green,
void MultiColorLight::setLed(leds leds, uint32_t color){ uint8_t blue) {
switch (leds){ MultiColorLight::setLed(leds, MultiColorLight::color(red, green, blue));
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<ledAmount; index++){
MultiColorLight::setLed(index,color);
}break;
default:
//TODO logging
break;
}
}; };
void MultiColorLight::setLed(leds leds, uint8_t red, uint8_t green, uint8_t blue){ void MultiColorLight::setTopLeds(uint32_t color) {
MultiColorLight::setLed(leds, MultiColorLight::color(red,green,blue)); MultiColorLight::setLed(TOP, color);
}; };
void MultiColorLight::setTopLeds(uint8_t red, uint8_t green, uint8_t blue) {
void MultiColorLight::setTopLeds(uint32_t color){ MultiColorLight::setTopLeds(MultiColorLight::color(red, green, blue));
MultiColorLight::setLed(TOP,color);
};
void MultiColorLight::setTopLeds(uint8_t red, uint8_t green, uint8_t blue){
MultiColorLight::setTopLeds(MultiColorLight::color(red,green,blue));
};
void MultiColorLight::blink(uint16_t amount,uint32_t color, leds leds, uint32_t interval){
for(uint16_t index = 0; index < amount;index++){
MultiColorLight::setLed(leds, color);
vTaskDelay(interval);
MultiColorLight::turnOffLed(leds);
vTaskDelay(interval);
}
}; };
void MultiColorLight::turnOffLed(leds leds){ void MultiColorLight::blink(uint16_t amount, uint32_t color, leds leds,
switch (leds){ uint32_t interval) {
case TOP_LEFT: for (uint16_t index = 0; index < amount; index++) {
MultiColorLight::setLed(1,0);break; MultiColorLight::setLed(leds, color);
case TOP_RIGHT: vTaskDelay(interval);
MultiColorLight::setLed(0,0);break; MultiColorLight::turnOffLed(leds);
case BOTTOM: vTaskDelay(interval);
MultiColorLight::setLed(2,0);break; }
case TOP:
for (int index = 0; index<2; index++){
MultiColorLight::setLed(index,0);
}break;
case ALL:
for (int index = 0; index<3; index++){
MultiColorLight::setLed(index,0);
}break;
default:
//TODO logging
break;
}
}; };
uint32_t MultiColorLight::color(uint8_t r, uint8_t g, uint8_t b){ void MultiColorLight::turnOffLed(leds leds) {
return rgbLeds.Color(r,g,b); switch (leds) {
case TOP_LEFT:
MultiColorLight::setLed(1, 0);
break;
case TOP_RIGHT:
MultiColorLight::setLed(0, 0);
break;
case BOTTOM:
MultiColorLight::setLed(2, 0);
break;
case TOP:
for (int index = 0; index < 2; index++) {
MultiColorLight::setLed(index, 0);
}
break;
case ALL:
for (int index = 0; index < 3; index++) {
MultiColorLight::setLed(index, 0);
}
break;
default:
// TODO logging
break;
}
}; };
//PRIVATE uint32_t MultiColorLight::color(uint8_t r, uint8_t g, uint8_t b) {
uint32_t MultiColorLight::normalizeColor(uint32_t color,uint8_t maxBrightness){ return rgbLeds.Color(r, g, b);
uint8_t red = (color&0x00FF0000)>>16; };
uint8_t green = (color&0x0000FF00)>>8;
uint8_t blue = (color&0x000000FF); // PRIVATE
if (red > maxBrightness){ uint32_t MultiColorLight::normalizeColor(uint32_t color,
red = maxBrightness; 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){ break;
green = maxBrightness-70; case ALL:
for (int index = 0; index < ledAmount; index++) {
ledsConsumption +=
MultiColorLight::modelChargeConsumption(index, color, durationMs);
} }
if(blue > maxBrightness-50){ break;
blue = maxBrightness-50; default:
} // TODO logging
return MultiColorLight::color(red,green,blue); 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);
};

View File

@ -1,146 +1,209 @@
/** /**
* @file MultiColorLight.h * @file MultiColorLight.h
* @author Saskia Duebener, Hans Haupt * @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 * @version 0.2
* @date 2023-11-25 * @date 2023-11-25
* *
* @copyright Copyright (c) 2023 * @copyright Copyright (c) 2023
* *
*/ */
#ifndef MultiColorLight_h #ifndef MultiColorLight_h
#define MultiColorLight_h #define MultiColorLight_h
#include <Adafruit_NeoPixel.h>
#include "ColorConstants.h"
#include "../power/Power.h" #include "../power/Power.h"
#include "ColorConstants.h"
#include <Adafruit_NeoPixel.h>
#define MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS 20 #define MULTI_COLOR_LIGHT_MAX_EXECUTION_DELAY_MS 20
/** /**
* @brief Describes combinations of leds on the Dezibot. * @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 * With the Robot in Front of you, when the robot drives away from you, the left
* * LED is TOP_LEFT
*
*/ */
enum leds{ enum leds { TOP_LEFT, TOP_RIGHT, BOTTOM, TOP, ALL };
TOP_LEFT,
TOP_RIGHT,
BOTTOM,
TOP,
ALL
};
#define TAG "MultiColorLight" #define TAG "MultiColorLight"
class MultiColorLight{ class MultiColorLight {
protected: protected:
static const uint16_t ledAmount = 3; static const uint16_t ledAmount = 3;
static const int16_t ledPin = 48; static const int16_t ledPin = 48;
static const uint8_t maxBrightness = 150; static const uint8_t maxBrightness = 150;
Adafruit_NeoPixel rgbLeds; Adafruit_NeoPixel rgbLeds;
static constexpr int maximumExecutionDelayMs = 10; static constexpr int maximumExecutionDelayMs = 10;
public: public:
MultiColorLight();
MultiColorLight(); /**
/** * @brief initialize the multicolor component
* @brief initialize the multicolor component *
* */
*/ void begin(void);
void begin(void);
/** /**
* @brief Set the specified led to the passed color * @brief Set the specified led to the passed color
* @param index ranging from 0-2, 0: Right, 1: Left, 2: Bottom * @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 * @param color A 32-bit unsigned integer representing the color in the format
* 0x00RRGGBB, where RR is the red component, GG is the green * 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 * component, and BB is the blue component. Each color can range
*/ * between 0 to 100
void setLed(uint8_t index , uint32_t color); */
void setLed(uint8_t index, uint32_t color);
/** /**
* @brief Set the specified leds to the passed color value * @brief Set the specified leds to the passed color value
* *
* @param leds which leds should be updated * @param leds which leds should be updated
* @param color A 32-bit unsigned integer representing the color in the format * @param color A 32-bit unsigned integer representing the color in the format
* 0x00RRGGBB, where RR is the red component, GG is the green * 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 * component, and BB is the blue component. Each color can range
*/ * between 0 to 100
void setLed(leds leds, uint32_t color); */
void setLed(leds leds, uint32_t color);
/** /**
* @brief Set the specified leds to the passed color value * @brief Set the specified leds to the passed color value
* *
* @param leds which leds should be updated * @param leds which leds should be updated
* @param red brightness of red, is normalized in the function * @param red brightness of red, is normalized in the function
* @param green brightness of green, 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 * @param blue brightness of blue, is normalized in the function
*/ */
void setLed(leds leds, uint8_t red, uint8_t green, uint8_t blue); 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 sets the two leds on the top of the robot to the specified color * @brief calculates the current consumption of an LED with the given color
* *
* @param red brightness of red, is normalized in the function * @param color A 32-bit unsigned integer representing the color in the
* @param green brightness of green, is normalized in the function * format 0x00RRGGBB, where RR is the red component, GG is the green
* @param blue brightness of blue, is normalized in the function * component, and BB is the blue component.
*/ * @return float the current consumption in mA
void setTopLeds(uint8_t red, uint8_t green, uint8_t blue); */
float modelCurrentConsumption(uint32_t color);
/**
* @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 * @brief calculates the current consumption of an LED with the given color
* * @note color is not normalized in this function
* @param leds which leds should be turned off, defaults to ALL *
*/ * @param red brightness of red
void turnOffLed(leds leds=ALL); * @param green brightness of green
* @param blue brightness of blue
/** * @return float the current consumption in mA
* @brief wrapper to calulate the used colorformat from a rgb-value */
* float modelCurrentConsumption(uint8_t red, uint8_t green, uint8_t blue);
* @param r red (0-100)
* @param g green (0-100) /**
* @param b blue (0-100) * @brief Estimate the energy consumption of setting the specified led to the
* @return A 32-bit unsigned integer representing the color in the format * passed color
* 0x00RRGGBB, where RR is the red component, GG is the green * @param index ranging from 0-2, 0: Right, 1: Left, 2: Bottom
* component, and BB is the blue component. * @param color A 32-bit unsigned integer representing the color in the
*/ * format 0x00RRGGBB, where RR is the red component, GG is the green
uint32_t color(uint8_t r, uint8_t g, uint8_t b); * 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: private:
/** /**
* @brief normalizes every component of color to not exeed the 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 * @param color A 32-bit unsigned integer representing the color in the format
* 0x00RRGGBB, where RR is the red component, GG is the green * 0x00RRGGBB, where RR is the red component, GG is the green
* component, and BB is the blue component. * component, and BB is the blue component.
* @param maxBrigthness maximal level of brightness that is allowed for each color * @param maxBrigthness maximal level of brightness that is allowed for each
* @return uint32_t A 32-bit unsigned integer representing the color in the format * color
* 0x00RRGGBB, where RR is the red component, GG is the green * @return uint32_t A 32-bit unsigned integer representing the color in the
* component, and BB is the blue component. Where each component can be * format 0x00RRGGBB, where RR is the red component, GG is the green
* between 0 - maxBrightness * 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); */
uint32_t normalizeColor(uint32_t color,
uint8_t maxBrigthness = maxBrightness);
}; };
#endif //MultiColorLight_h #endif // MultiColorLight_h