Rework display: separate task, add battery percent

slightly rework hacked display test
- new code structure
- split code in several functions
- add task for display instead of running it in main()
- functions to convert voltage to battery percent charged
- show percentage and voltage on display
This commit is contained in:
jonny_jr9 2023-09-12 10:31:14 +02:00 committed by jonny_l480
parent 548b5b8d51
commit 47d7e9f3a4
3 changed files with 133 additions and 41 deletions

View File

@ -9,7 +9,6 @@ extern "C"{
//#
#define GPIO_RANGE_MAX 33
#define I2C_INTERFACE y
//# SPI_INTERFACE is not set
//# SSD1306_128x32 is not set
#define SSD1306_128x64 y
#define OFFSETX 0
@ -21,6 +20,9 @@ extern "C"{
//# I2C_PORT_1 is not set
//# end of SSD1306 Configuration
#define ADC_BATT_VOLTAGE ADC1_CHANNEL_6
#define BAT_CELL_COUNT 7
@ -28,6 +30,7 @@ extern "C"{
//--------------------------
//------- getVoltage -------
//--------------------------
//TODO duplicate code: getVoltage also defined in currentsensor.cpp -> outsource this
//local function to get average voltage from adc
float getVoltage1(adc1_channel_t adc, uint32_t samples){
//measure voltage
@ -41,42 +44,141 @@ float getVoltage1(adc1_channel_t adc, uint32_t samples){
void startDisplayTest(){
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //max voltage
//==========================
//======= variables ========
//==========================
SSD1306_t dev;
//int center, top, bottom;
char lineChar[20];
//top = 2;
//center = 3;
//bottom = 8;
//tag for logging
static const char * TAG = "display";
SSD1306_t dev;
int center, top, bottom;
char lineChar[20];
//=================
//===== init ======
//=================
void display_init(){
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //max voltage
ESP_LOGW("display", "INTERFACE is i2c");
ESP_LOGW("display", "SDA_GPIO=%d",SDA_GPIO);
ESP_LOGW("display", "SCL_GPIO=%d",SCL_GPIO);
ESP_LOGW("display", "RESET_GPIO=%d",RESET_GPIO);
i2c_master_init(&dev, SDA_GPIO, SCL_GPIO, RESET_GPIO);
#if FLIP
dev._flip = true;
ESP_LOGW("display", "Flip upside down");
#endif
ESP_LOGI("display", "Panel is 128x64");
ssd1306_init(&dev, 128, 64);
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
}
float getBatteryVoltage(){
#define BAT_VOLTAGE_CONVERSION_FACTOR 11.9
float voltageRead = getVoltage1(ADC_BATT_VOLTAGE, 1000);
float battVoltage = voltageRead * 11.9; //note: factor comes from simple test with voltmeter
ESP_LOGD(TAG, "batteryVoltage - voltageAdc=%f, voltageConv=%f, factor=%.2f", voltageRead, battVoltage, BAT_VOLTAGE_CONVERSION_FACTOR);
return battVoltage;
}
//----------------------------------
//------- getBatteryPercent --------
//----------------------------------
//TODO find better/more accurate table?
//configure discharge curve of one cell with corresponding known voltage->chargePercent values
const float voltageLevels[] = {3.00, 3.45, 3.68, 3.74, 3.77, 3.79, 3.82, 3.87, 3.92, 3.98, 4.06, 4.20};
const float percentageLevels[] = {0.0, 5.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0};
float getBatteryPercent(float voltage){
float cellVoltage = voltage/BAT_CELL_COUNT;
int size = sizeof(voltageLevels) / sizeof(voltageLevels[0]);
int sizePer = sizeof(percentageLevels) / sizeof(percentageLevels[0]);
//check if configured correctly
if (size != sizePer) {
ESP_LOGE(TAG, "getBatteryPercent - count of configured percentages do not match count of voltages");
return 0;
}
if (cellVoltage <= voltageLevels[0]) {
return 0.0;
} else if (cellVoltage >= voltageLevels[size - 1]) {
return 100.0;
}
//scale voltage linear to percent in matched range
for (int i = 1; i < size; ++i) {
if (cellVoltage <= voltageLevels[i]) {
float voltageRange = voltageLevels[i] - voltageLevels[i - 1];
float voltageOffset = cellVoltage - voltageLevels[i - 1];
float percentageRange = percentageLevels[i] - percentageLevels[i - 1];
float percentageOffset = percentageLevels[i - 1];
float percent = percentageOffset + (voltageOffset / voltageRange) * percentageRange;
ESP_LOGD(TAG, "getBatPercent - cellVoltage=%.3f => percentage=%.3f", cellVoltage, percent);
ESP_LOGD(TAG, "getBatPercent - matched range: %.2fV-%.2fV => %.1f%%-%.1f%%", voltageLevels[i-1], voltageLevels[i], percentageLevels[i-1], percentageLevels[i]);
return percent;
}
}
ESP_LOGE(TAG, "getBatteryPercent - unknown voltage range");
return 0.0; //unknown range
}
float getBatteryPercent(){
float voltage = getBatteryVoltage();
return getBatteryPercent(voltage);
}
//============================
//======= display task =======
//============================
void display_task( void * pvParameters ){
char buf[20];
char buf1[20];
int len, len1;
int countFastloop = 0;
int countSlowLoop = 0;
display_init();
//todo check if successfully initialized
//welcome msg
strcpy(buf, "Hello");
ssd1306_display_text_x3(&dev, 0, buf, 5, false);
vTaskDelay(1000 / portTICK_PERIOD_MS);
top = 2;
center = 3;
bottom = 8;
//update stats
while(1){
//--- battery ---
//TODO update only when no load (currentsensors = ~0A)
float battVoltage = getBatteryVoltage();
float battPercent = getBatteryPercent(battVoltage);
len = snprintf(buf, sizeof(buf), "Bat:%.1fV %.2fV", battVoltage, battVoltage/BAT_CELL_COUNT);
len1 = snprintf(buf1, sizeof(buf1), "B:%02.0f%%", battPercent);
ssd1306_display_text_x3(&dev, 0, buf1, len1, false);
ssd1306_display_text(&dev, 3, buf, len, false);
ssd1306_display_text(&dev, 4, buf, len, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
countFastloop++;
}
//TODO add pages and menus
//-----------------------------------
//---- text-related example code ----
//-----------------------------------
//ssd1306_display_text(&dev, 0, "SSD1306 128x64", 14, false);
//ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false);
//ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false);
@ -89,24 +191,7 @@ adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //max voltage
//ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true);
//ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true);
//ssd1306_display_text(&dev, 7, "Hello World!!", 13, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
while(1){
float voltage = getVoltage1( ADC1_CHANNEL_6, 1000);
float battVoltage = voltage * 11.9;
char buf[20];
char buf1[20];
int len = snprintf(buf, sizeof(buf), "Batt: %.3fV", battVoltage);
int len1 = snprintf(buf1, sizeof(buf1), "%.1fV", battVoltage);
ESP_LOGD("display", "voltageAdc=%f, voltageConv=%f", voltage, battVoltage);
ssd1306_display_text_x3(&dev, 0, buf1, len1, false);
ssd1306_display_text(&dev, 3, buf, len, false);
ssd1306_display_text(&dev, 4, buf, len, true);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
//
//// Display Count Down
//uint8_t image[24];
//memset(image, 0, sizeof(image));
@ -194,7 +279,7 @@ adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //max voltage
//// Fade Out
//ssd1306_fadeout(&dev);
#if 0
// Fade Out
for(int contrast=0xff;contrast>0;contrast=contrast-0x20) {

View File

@ -11,4 +11,6 @@ extern "C" {
}
void startDisplayTest();
//task that inititialized the display, displays welcome message
//and releatedly updates the display with certain content
void display_task( void * pvParameters );

View File

@ -143,7 +143,7 @@ void setLoglevels(void){
esp_log_level_set("buzzer", ESP_LOG_ERROR);
//esp_log_level_set("motordriver", ESP_LOG_ERROR);
//esp_log_level_set("motor-control", ESP_LOG_INFO);
esp_log_level_set("evaluatedJoystick", ESP_LOG_DEBUG);
//esp_log_level_set("evaluatedJoystick", ESP_LOG_DEBUG);
//esp_log_level_set("joystickCommands", ESP_LOG_DEBUG);
esp_log_level_set("button", ESP_LOG_INFO);
esp_log_level_set("control", ESP_LOG_INFO);
@ -151,6 +151,7 @@ void setLoglevels(void){
esp_log_level_set("wifi", ESP_LOG_INFO);
esp_log_level_set("http", ESP_LOG_INFO);
esp_log_level_set("automatedArmchair", ESP_LOG_DEBUG);
esp_log_level_set("display", ESP_LOG_DEBUG);
//esp_log_level_set("current-sensors", ESP_LOG_INFO);
}
@ -205,6 +206,13 @@ extern "C" void app_main(void) {
xTaskCreate(&task_fans, "task_fans", 2048, NULL, 1, NULL);
//-----------------------------------
//----- create task for display -----
//-----------------------------------
//task that handles the display
xTaskCreate(&display_task, "display_task", 2048, NULL, 1, NULL);
//beep at startup
buzzer.beep(3, 70, 50);
@ -236,9 +244,6 @@ extern "C" void app_main(void) {
//========== display test ============
startDisplayTest();
//--- main loop ---
//does nothing except for testing things
while(1){