espd

ESP32_EMU_BT_V.2.03

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