Advertisement
espd

esp32 - blurry text

Apr 9th, 2025 (edited)
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.43 KB | None | 0 0
  1. #include <Arduino.h>
  2. #include <lvgl.h>
  3. #include <TFT_eSPI.h>
  4. #include "BluetoothSerial.h"
  5. #include <string>
  6. #include <stdexcept>
  7. using namespace std;
  8.  
  9. //#define USE_NAME           // Comment this to use MAC address instead of a slaveName
  10. const char *pin = "1234";
  11.  
  12. #if !defined(CONFIG_BT_SPP_ENABLED)
  13. #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
  14. #endif
  15.  
  16. BluetoothSerial SerialBT;
  17.  
  18. #ifdef USE_NAME
  19. String slaveName = "EMUCANBT_SPP";
  20. #else
  21. String MACadd = "XX:XX:XX:XX:XX:XX";                          // This only for printing
  22. uint8_t address[6] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };  // Change this to reflect real MAC address of your slave BT device
  23. #endif
  24.  
  25. String myName = "ESP32-BT-Master";
  26.  
  27. const int buzzerPin = 22;
  28.  
  29. // Display & LVGL setup
  30. TFT_eSPI tft = TFT_eSPI();
  31. static lv_disp_draw_buf_t draw_buf;
  32. static lv_color_t buf[LV_HOR_RES_MAX * 10];
  33. lv_obj_t *table;
  34.  
  35. // LVGL Display Flush Callback
  36. void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  37.   uint16_t w = area->x2 - area->x1 + 1;
  38.   uint16_t h = area->y2 - area->y1 + 1;
  39.   tft.startWrite();
  40.   tft.setAddrWindow(area->x1, area->y1, w, h);
  41.   tft.pushColors((uint16_t *)&color_p->full, w * h, true);
  42.   tft.endWrite();
  43.   lv_disp_flush_ready(disp);
  44. }
  45.  
  46. // Initialize LVGL Table
  47. void create_table() {
  48.   table = lv_table_create(lv_scr_act());
  49.   lv_obj_align(table, LV_ALIGN_CENTER, 0, 0);
  50.  
  51.   lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE);
  52.  
  53.   lv_obj_set_style_bg_color(lv_scr_act(), lv_color_make(255, 255, 255), LV_PART_MAIN);
  54.  
  55.   lv_obj_set_style_text_color(table, lv_color_black(), LV_PART_ITEMS);
  56.  
  57.   lv_obj_set_style_bg_color(table, lv_color_white(), LV_PART_MAIN);
  58.  
  59.   // Set table properties
  60.   lv_table_set_col_cnt(table, 4);
  61.   lv_table_set_row_cnt(table, 6);
  62.  
  63.   lv_obj_set_style_border_width(table, 1, LV_PART_ITEMS);
  64.   lv_obj_set_style_border_color(table, lv_color_make(64, 64, 64), LV_PART_ITEMS);
  65.   lv_obj_set_style_border_side(table, LV_BORDER_SIDE_FULL, LV_PART_ITEMS);
  66.  
  67.   lv_table_set_col_width(table, 0, 60);
  68.   lv_table_set_col_width(table, 1, 100);
  69.   lv_table_set_col_width(table, 2, 60);
  70.   lv_table_set_col_width(table, 3, 100);
  71.  
  72.   lv_table_add_cell_ctrl(table, 5, 1, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  73.   lv_table_add_cell_ctrl(table, 5, 2, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  74.   lv_table_add_cell_ctrl(table, 5, 3, LV_TABLE_CELL_CTRL_MERGE_RIGHT);
  75.  
  76.   lv_table_set_cell_value(table, 0, 0, "RPM");
  77.   lv_table_set_cell_value(table, 0, 2, "SPD");
  78.   lv_table_set_cell_value(table, 1, 0, "AFR");
  79.   lv_table_set_cell_value(table, 1, 2, "CLT");
  80.   lv_table_set_cell_value(table, 2, 0, "TPS");
  81.   lv_table_set_cell_value(table, 2, 2, "BAT");
  82.   lv_table_set_cell_value(table, 3, 0, "MAP");
  83.   lv_table_set_cell_value(table, 3, 2, "BST");
  84.   lv_table_set_cell_value(table, 4, 0, "INJ");
  85.   lv_table_set_cell_value(table, 4, 2, "IGN");
  86.   lv_table_set_cell_value(table, 5, 0, "CEL");
  87.  
  88.   lv_obj_add_event_cb(table, my_table_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
  89.  
  90.   lv_obj_add_event_cb(table, table_event_cb_bg, LV_EVENT_DRAW_PART_BEGIN, NULL);
  91.  
  92.   lv_timer_handler();
  93. }
  94.  
  95. void setup() {
  96.   Serial.begin(1000000);
  97.  
  98.   pinMode(buzzerPin, OUTPUT);
  99.  
  100.   tft.begin();
  101.   tft.setRotation(1);
  102.  
  103.   // Initialize LVGL
  104.   lv_init();
  105.   lv_refr_now(NULL);
  106.   lv_disp_draw_buf_init(&draw_buf, buf, NULL, LV_HOR_RES_MAX * 10);
  107.  
  108.   // Setup LVGL Display Driver
  109.   static lv_disp_drv_t disp_drv;
  110.   lv_disp_drv_init(&disp_drv);
  111.   disp_drv.hor_res = 320;
  112.   disp_drv.ver_res = 240;
  113.   disp_drv.flush_cb = my_disp_flush;
  114.   disp_drv.draw_buf = &draw_buf;
  115.   lv_disp_drv_register(&disp_drv);
  116.  
  117.   create_table();
  118.   connectToBt();
  119. }
  120.  
  121. void connectToBt() {
  122.   bool connected;
  123.   SerialBT.begin(myName, true);
  124.  
  125. #ifndef USE_NAME
  126.   SerialBT.setPin(pin);
  127. #endif
  128.  
  129. #ifdef USE_NAME
  130.   connected = SerialBT.connect(slaveName);
  131. #else
  132.   connected = SerialBT.connect(address);
  133. #endif
  134.  
  135.   if (connected) {
  136.     Serial.println("Connected Successfully!");
  137.   } else {
  138.     Serial.println("Initial connect failed. Will retry in loop...");
  139.   }
  140. }
  141.  
  142. int rpm;
  143. int spd;
  144. float afr;
  145. float mapR;
  146. float boost;
  147. int tps;
  148. int clt;
  149. int ign;
  150. int inj;
  151. float bat;
  152. int cel;
  153.  
  154. unsigned long lastReconnectAttempt = 0;
  155. const unsigned long reconnectInterval = 5000;  // 5 seconds
  156.  
  157. void loop() {
  158.   uint8_t frame[5];
  159.   uint8_t channel;
  160.   uint16_t value;
  161.   int chData;
  162.  
  163.   if (!SerialBT.connected()) {
  164.     // Attempt reconnection every few seconds
  165.     if (millis() - lastReconnectAttempt > reconnectInterval) {
  166.       lastReconnectAttempt = millis();
  167.       connectToBt();
  168.     }
  169.   }
  170.  
  171.   // Wait until at least 5 bytes are available
  172.   while (SerialBT.available() >= 5) {
  173.     SerialBT.readBytes(frame, 5);  // Read exactly 5 bytes
  174.  
  175.     // Extract values
  176.     channel = frame[0];
  177.     value = (frame[2] << 8) | frame[3];  // Combine High and Low byte
  178.  
  179.     chData = static_cast<int>(channel);
  180.     if (chData == 1) {
  181.       rpm = static_cast<int>(value);
  182.       // Serial.println("RPM: " + String(rpm));
  183.       lv_table_set_cell_value(table, 0, 1, String(rpm).c_str());
  184.     } else if (chData == 28) {
  185.       spd = (static_cast<int>(value) / 2.8);
  186.       //Serial.println("SPD: " + String(spd) + " KM/H");
  187.       lv_table_set_cell_value(table, 0, 3, (String(spd) + " KM/H").c_str());
  188.     } else if (chData == 12) {
  189.       afr = (static_cast<float>(value) / 10);
  190.       //Serial.println("AFR: " + String(afr));
  191.       lv_table_set_cell_value(table, 1, 1, String(afr).c_str());
  192.     } else if (chData == 2) {
  193.       mapR = (static_cast<float>(value) / 100);
  194.       boost = (mapR - 1.0132f);
  195.       //Serial.println("MAP: " + String(mapR) + " BAR");
  196.       // Serial.println("BST: " + String(boost) + " BAR");
  197.       lv_table_set_cell_value(table, 3, 1, (String(mapR) + " BAR").c_str());
  198.       lv_table_set_cell_value(table, 3, 3, (String(boost) + " BAR").c_str());
  199.     } else if (chData == 3) {
  200.       tps = static_cast<int>(value);
  201.       //Serial.println("TPS: " + String(tps) + " %");
  202.       lv_table_set_cell_value(table, 2, 1, (String(tps) + " %").c_str());
  203.     } else if (chData == 24) {
  204.       clt = static_cast<int>(value);
  205.       //Serial.println("CLT: " + String(clt) + " °C");
  206.       lv_table_set_cell_value(table, 1, 3, (String(clt) + " °C").c_str());
  207.     } else if (chData == 6) {
  208.       ign = static_cast<int>(value);
  209.       //Serial.println("IGN: " + String(ign) + " °");
  210.       lv_table_set_cell_value(table, 4, 3, (String(ign) + " °").c_str());
  211.     } else if (chData == 19) {
  212.       inj =  static_cast<int>(value);
  213.       //Serial.println("INJ: " + String(inj) + " %");
  214.       lv_table_set_cell_value(table, 4, 1, (String(inj) + " %").c_str());
  215.     } else if (chData == 5) {
  216.       bat = (static_cast<float>(value) / 37);
  217.       //Serial.println("BAT: " + String(bat) + " V");
  218.       lv_table_set_cell_value(table, 2, 3, (String(bat) + " V").c_str());
  219.     } else if (chData == 255) {
  220.       cel = decodeCheckEngine(value);
  221.       //Serial.println("CEL: " + String(cel));
  222.     }
  223.   }
  224.  
  225.   if (cel > 0 || clt > 105 || rpm > 7200 || boost > 1.10 || (bat < 12.00 && bat > 1.00)) {
  226.     digitalWrite(buzzerPin, HIGH);  // Buzzer ON
  227.   } else {
  228.     digitalWrite(buzzerPin, LOW);   // Buzzer OFF
  229.   }
  230.  
  231.   lv_obj_invalidate(table);
  232.   lv_timer_handler();
  233.   // Run LVGL
  234.   //delay(10);
  235. }
  236.  
  237. int decodeCheckEngine(uint16_t value) {
  238.   int cel_codes = 0; string cel_names = "";
  239.   if (value == 0) {
  240.     return 0;
  241.   }
  242.   else {
  243.     //Serial.print("CEL Codes: ");
  244.     if (value & (1 << 0)) {
  245.       cel_codes++;  // Bit 0
  246.       //Serial.print("CLT ");
  247.       cel_names = "CLT ";
  248.     }
  249.     if (value & (1 << 1)) {
  250.       //  cel_codes++;  // Bit 1
  251.       //  Serial.print("IAT ");
  252.       //   cel_names += "IAT ";
  253.     }
  254.     if (value & (1 << 2)) {
  255.       cel_codes++;  // Bit 2
  256.       //Serial.print("MAP ");
  257.       cel_names += "MAP ";
  258.     }
  259.     if (value & (1 << 3)) {
  260.       cel_codes++;  // Bit 3
  261.       //Serial.print("WBO ");
  262.       cel_names += "WBO ";
  263.     }
  264.     if (value & (1 << 8)) {
  265.       cel_codes++;  // Bit 8
  266.       //Serial.print("FF SENSOR ");
  267.       cel_names += "FF SENSOR ";
  268.     }
  269.     if (value & (1 << 9)) {
  270.       cel_codes++;  // Bit 9
  271.       //Serial.print("DBW ");
  272.       cel_names += "DBW ";
  273.     }
  274.     if (value & (1 << 10)) {
  275.       cel_codes++;  // Bit 10
  276.       //Serial.print("FPR ");
  277.       cel_names += "FPR ";
  278.     }
  279.     //Serial.print("Total CEL Codes: " + cel_codes);
  280.     //Serial.println();
  281.  
  282.     lv_table_set_cell_value(table, 5, 1, cel_names.c_str());
  283.     return cel_codes;
  284.   }
  285. }
  286.  
  287. // Custom draw callback for right-aligned text in specific cells
  288. void my_table_event_cb(lv_event_t * e) {
  289.   lv_obj_t * table = lv_event_get_target(e);
  290.   lv_obj_draw_part_dsc_t * dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(e);
  291.  
  292.   if (dsc->part == LV_PART_ITEMS) {
  293.     uint16_t row = dsc->id / lv_table_get_col_cnt(table);
  294.     uint16_t col = dsc->id % lv_table_get_col_cnt(table);
  295.  
  296.     // Default Left Align
  297.     dsc->label_dsc->align = LV_TEXT_ALIGN_LEFT;
  298.  
  299.     // Right-align specific cells
  300.     if ((row == 0 && col == 1) || (row == 0 && col == 3) || (row == 1 && col == 1) || (row == 1 && col == 3) || (row == 2 && col == 1) || (row == 2 && col == 3) || (row == 3 && col == 1) || (row == 3 && col == 3) ||
  301.         (row == 4 && col == 1) || (row == 4 && col == 3)) {
  302.       dsc->label_dsc->align = LV_TEXT_ALIGN_RIGHT;
  303.     }
  304.     if (row == 5 && col == 1) {
  305.       dsc->label_dsc->align = LV_TEXT_ALIGN_CENTER;
  306.     }
  307.  
  308.   }
  309. }
  310.  
  311. static void table_event_cb_bg(lv_event_t *e) {
  312.   lv_obj_t *table = lv_event_get_target(e);
  313.   lv_obj_draw_part_dsc_t *dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(e);
  314.  
  315.   // Ensure dsc and rect_dsc are valid
  316.   if (!dsc || !dsc->rect_dsc) return;
  317.  
  318.   // Only modify table cell backgrounds
  319.   if (dsc->part == LV_PART_ITEMS) {
  320.     uint16_t row = dsc->id / lv_table_get_col_cnt(table);
  321.     uint16_t col = dsc->id % lv_table_get_col_cnt(table);
  322.  
  323.     const char *value_str = lv_table_get_cell_value(table, row, col);
  324.  
  325.     // Check if value_str is null or empty before conversion
  326.     float value = 0.0f;  // Default value
  327.     if (value_str != nullptr && value_str[0] != '\0') {
  328.       try {
  329.         value = std::stof(value_str);  // Convert string to float safely
  330.       } catch (...) {
  331.         value = 0.0f;  // Handle invalid conversions
  332.       }
  333.     }
  334.  
  335.     // Default cell color
  336.     lv_color_t bg_color = lv_color_white();
  337.     lv_color_t text_color = lv_color_black();
  338.  
  339.     if (row == 0 && col == 1 && value > 7200.00) {
  340.       bg_color = lv_color_make(0, 255, 0);
  341.       text_color = lv_color_white();
  342.     }
  343.     if (row == 1 && col == 3 && value > 100.00) {
  344.       bg_color = lv_color_make(0, 255, 0);
  345.       text_color = lv_color_white();
  346.     }
  347.     if (row == 1 && col == 3 && value < 55.00 && value > 01.00) {
  348.       bg_color = lv_color_make(0, 255, 255);
  349.     }
  350.     if (row == 2 && col == 3 && value < 12.00 && value > 01.00) {
  351.       bg_color = lv_color_make(0, 255, 0);
  352.       text_color = lv_color_white();
  353.     }
  354.     if (row == 3 && col == 3 && value > 1.10) {
  355.       bg_color = lv_color_make(0, 255, 0);
  356.       text_color = lv_color_white();
  357.     }
  358.     if (row == 5 && col == 1 && value_str != nullptr && value_str[0] != '\0') {
  359.       bg_color = lv_color_make(0, 255, 0);
  360.       text_color = lv_color_white();
  361.     }
  362.  
  363.     // Apply background color to the cell
  364.     dsc->rect_dsc->bg_color = bg_color;
  365.     dsc->rect_dsc->bg_opa = LV_OPA_COVER; // Ensure background is visible
  366.     dsc->label_dsc->color = text_color;
  367.   }
  368. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement