#include "display.hpp" extern "C"{ #include } //# //# SSD1306 Configuration //# #define GPIO_RANGE_MAX 33 #define I2C_INTERFACE y //# SSD1306_128x32 is not set #define SSD1306_128x64 y #define OFFSETX 0 //# FLIP is not set #define SCL_GPIO 22 #define SDA_GPIO 23 #define RESET_GPIO 15 //FIXME remove this #define I2C_PORT_0 y //# I2C_PORT_1 is not set //# end of SSD1306 Configuration #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){ 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 ======= //============================ #define VERY_SLOW_LOOP_INTERVAL 30000 #define SLOW_LOOP_INTERVAL 1000 #define FAST_LOOP_INTERVAL 200 //TODO: separate taks for each loop? void display_task( void * pvParameters ){ char buf[20]; char buf1[20]; int len, len1; int countFastloop = SLOW_LOOP_INTERVAL; int countSlowLoop = VERY_SLOW_LOOP_INTERVAL; 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); //update stats while(1){ if (countFastloop >= SLOW_LOOP_INTERVAL / FAST_LOOP_INTERVAL){ //---- very slow loop ---- if (countSlowLoop >= VERY_SLOW_LOOP_INTERVAL/SLOW_LOOP_INTERVAL){ //clear display - workaround for bugged line order after a few minutes countSlowLoop = 0; ssd1306_clear_screen(&dev, false); } //---- slow loop ---- countSlowLoop ++; countFastloop = 0; //--- battery stats --- //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); } //---- fast loop ---- //update speed/rpm float sLeft = speedLeft.getKmph(); float rLeft = speedLeft.getRpm(); float sRight = speedRight.getKmph(); float rRight = speedRight.getRpm(); len = snprintf(buf, sizeof(buf), "L:%.1f R:%.1fkm/h", fabs(sLeft), fabs(sRight)); ssd1306_display_text(&dev, 5, buf, len, false); len = snprintf(buf, sizeof(buf), "L:%4.0f R:%4.0fRPM", rLeft, rRight); ssd1306_display_text(&dev, 6, buf, len, false); //debug speed sensors ESP_LOGD(TAG, "%s", buf); //TODO show currentsensor values vTaskDelay(FAST_LOOP_INTERVAL / 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); //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;line0;contrast=contrast-0x20) { ssd1306_contrast(&dev, contrast); vTaskDelay(40); } #endif }