espd

esp32 full code - 20250405 with colors

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