#include "display.hpp" extern "C"{ #include #include "esp_ota_ops.h" } #include "menu.hpp" //==== display config ==== #define I2C_INTERFACE y #define SCL_GPIO 22 #define SDA_GPIO 23 #define RESET_GPIO 15 // FIXME remove this // the following options are set in menuconfig: (see sdkconfig) // #define CONFIG_OFFSETX 2 //note: the larger display (actual 130x64) needs 2 pixel offset (prevents bugged column) // #define CONFIG_I2C_PORT_0 y //=== content config === #define STARTUP_MSG_TIMEOUT 2000 #define ADC_BATT_VOLTAGE ADC1_CHANNEL_6 #define BAT_CELL_COUNT 7 //-------------------------- //------- 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 int measure = 0; for (int j=0; jchargePercent 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 = getBatteryVoltage(); 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 } //----------------------- //----- showScreen1 ----- //----------------------- //shows overview on entire display: //percentage, voltage, current, mode, rpm, speed void showScreen1() { char buf[20]; char buf1[20]; int len, len1; //-- battery percentage -- // TODO update when no load (currentsensors = ~0A) only len1 = snprintf(buf1, sizeof(buf1), "B:%02.0f%%", getBatteryPercent()); ssd1306_display_text_x3(&dev, 0, buf1, len1, false); //-- voltage and current -- len = snprintf(buf, sizeof(buf), "%04.1fV %04.1f:%04.1fA", getBatteryVoltage(), fabs(motorLeft.getCurrentA()), fabs(motorRight.getCurrentA())); ssd1306_display_text(&dev, 3, buf, len, false); //-- control state -- len = snprintf(buf, sizeof(buf), "%s ", control.getCurrentModeStr()); ssd1306_display_text_x3(&dev, 4, buf, len, false); //-- speed and RPM -- len = snprintf(buf, sizeof(buf), "%3.1fkm/h %03.0f:%03.0fR", fabs((speedLeft.getKmph() + speedRight.getKmph()) / 2), speedLeft.getRpm(), speedRight.getRpm()); ssd1306_display_text(&dev, 7, buf, len, false); // debug speed sensors ESP_LOGD(TAG, "%s", buf); } //------------------------ //---- showStartupMsg ---- //------------------------ //shows welcome message and information about current version void showStartupMsg(){ char buf[20]; int len; const esp_app_desc_t * desc = esp_ota_get_app_description(); //show message len = snprintf(buf, 20, "START"); ssd1306_display_text_x3(&dev, 0, buf, len, false); //show git-tag len = snprintf(buf, 20, "%s", desc->version); ssd1306_display_text(&dev, 4, buf, len, false); //show build-date (note: date,time of last clean build) len = snprintf(buf, 20, "%s", desc->date); ssd1306_display_text(&dev, 6, buf, len, false); //show build-time len = snprintf(buf, 20, "%s", desc->time); ssd1306_display_text(&dev, 7, buf, len, false); } //============================ //======= display task ======= //============================ #define STATUS_SCREEN_UPDATE_INTERVAL 500 // TODO: separate task for each loop? void display_task(void *pvParameters) { // initialize display display_init(); // TODO check if successfully initialized // show startup message showStartupMsg(); vTaskDelay(STARTUP_MSG_TIMEOUT / portTICK_PERIOD_MS); // repeatedly update display with content while (1) { if (control.getCurrentMode() == controlMode_t::MENU) { //uses encoder events to control menu and updates display handleMenu(&dev); } else //show status screen in any other mode { showScreen1(); vTaskDelay(STATUS_SCREEN_UPDATE_INTERVAL / portTICK_PERIOD_MS); } // 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); //ssd1306_display_text(&dev, 3, "Hello World!!", 13, false); ////ssd1306_clear_line(&dev, 4, true); ////ssd1306_clear_line(&dev, 5, true); ////ssd1306_clear_line(&dev, 6, true); ////ssd1306_clear_line(&dev, 7, true); //ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true); //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); // //// Display Count Down //uint8_t image[24]; //memset(image, 0, sizeof(image)); //ssd1306_display_image(&dev, top, (6*8-1), image, sizeof(image)); //ssd1306_display_image(&dev, top+1, (6*8-1), image, sizeof(image)); //ssd1306_display_image(&dev, top+2, (6*8-1), image, sizeof(image)); //for(int font=0x39;font>0x30;font--) { // memset(image, 0, sizeof(image)); // ssd1306_display_image(&dev, top+1, (7*8-1), image, 8); // memcpy(image, font8x8_basic_tr[font], 8); // if (dev._flip) ssd1306_flip(image, 8); // ssd1306_display_image(&dev, top+1, (7*8-1), image, 8); // vTaskDelay(1000 / portTICK_PERIOD_MS); //} // //// Scroll Up //ssd1306_clear_screen(&dev, false); //ssd1306_contrast(&dev, 0xff); //ssd1306_display_text(&dev, 0, "---Scroll UP---", 16, true); ////ssd1306_software_scroll(&dev, 7, 1); //ssd1306_software_scroll(&dev, (dev._pages - 1), 1); //for (int line=0;line