diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..37e738a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# PlatformIO build output and IDE files +.pio/ +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/10-OBD-Display-2024/README.md b/10-OBD-Display-2024/README.md index fb09509..f0037b6 100644 --- a/10-OBD-Display-2024/README.md +++ b/10-OBD-Display-2024/README.md @@ -7,23 +7,38 @@ Because the ESP32-S3 has no Bluetooth Classic, the design used a second (classic ELM327 --(BT Classic SPP)--> classic ESP32 (elm327_wifi_bridge) --(WiFi AP, HTTP /speed)--> JC3636W518 (display_speed_wifi) ``` -Split out of `2-Program Example/Demo_Arduino/ST77916_LVGL_DEMO/` on 2026-10-22. History is in git. +Split out of `2-Program Example/Demo_Arduino/ST77916_LVGL_DEMO/` on 2026-10-22 and converted to PlatformIO. History is in git. -## Sketches +## Projects (all PlatformIO) | Folder | Runs on | What it does | Was | |---|---|---|---| | `display_speed_wifi/` | JC3636W518 | GIF background from SD (`A:wallpaper.gif`) + joins AP `ESP32-Access-Point`, polls `http://192.168.4.1/speed`, shows it in a label | `ST77916_LVGL_DEMO/8.4/` | | `display_gif_sd/` | JC3636W518 | GIF from SD (`A:wallpaper.gif`) + static text label | `ST77916_LVGL_DEMO/working version/` | -| `display_gif_embedded/` | JC3636W518 | GIF compiled into firmware (`loligod.c`, 13.9 MB source). WiFi code commented out. Stops in `setup()` if no SD card | `ST77916_LVGL_DEMO/` (top level) | -| `elm327_wifi_bridge/` | **classic ESP32** (not S3) | BT Classic → ELM327 named `OBDII` (PIN 1234), WiFi AP `ESP32-Access-Point` / `123456789`, serves `/speed` (kph). Needs esp32 core 2.0.x, ESPAsyncWebServer, ELMduino | `ST77916_LVGL_DEMO/esp23_elm327_to_wifi/` | -| `elmulator/` | classic ESP32 | ELMulator library + examples: fake ELM327 over BT/WiFi for testing without a car | `ST77916_LVGL_DEMO/ELMulator-master/` | +| `display_gif_embedded/` | JC3636W518 | GIF compiled into firmware (`src/loligod.c`, 2.2 MB GIF → 3.4 MB firmware, uses `default_16MB.csv` with 6.25 MB app slots). WiFi code commented out. Stops in `setup()` if no SD card | `ST77916_LVGL_DEMO/` (top level) | +| `elm327_wifi_bridge/` | **classic ESP32** (not S3) | BT Classic → ELM327 named `OBDII` (PIN 1234), WiFi AP `ESP32-Access-Point` / `123456789`, serves `/speed` (kph) | `ST77916_LVGL_DEMO/esp23_elm327_to_wifi/` | +| `elmulator/` | classic ESP32 | Fake ELM327 for testing without a car. Library in `lib/ELMulator`, envs `simple`, `custom`, `wifi` (BT name `OBDII`) | `ST77916_LVGL_DEMO/ELMulator-master/` | | `assets/gifs/` | — | GIF files (`dump/` = unused collection) | `ST77916_LVGL_DEMO/gifs/` | -| `_archive/lvgl9_broken/` | — | Unfinished LVGL 9 port, does not compile | `ST77916_LVGL_DEMO/9.1/` | +| `_archive/lvgl9_broken/` | — | Unfinished LVGL 9 port, does not compile, not converted | `ST77916_LVGL_DEMO/9.1/` | -## Notes -- Each display sketch carries its own `pincfg.h`, `scr_st77916.h` and `lv_conf.h`. The Arduino LVGL library does **not** read the sketch's `lv_conf.h` — the one used is `Documents\Arduino\libraries\lv_conf.h`. Copy the sketch's version there before building: +## Build / upload +Open a project folder in VS Code with the PlatformIO extension, or from a terminal: +``` +pio run -d display_speed_wifi # build +pio run -d display_speed_wifi -t upload # flash (COM21) +pio device monitor -d display_speed_wifi # serial monitor +pio run -d elmulator -e wifi -t upload --upload-port COMxx +``` +(`pio` = `%USERPROFILE%\.platformio\penv\Scripts\pio.exe` if not on PATH.) + +## Configuration +- **JC3636W518 projects:** pioarduino platform `51.03.05` (= Arduino core 3.0.5), board `esp32-s3-devkitc-1` with 16 MB QIO flash, OPI PSRAM, `huge_app.csv` (3 MB app), USB-CDC on boot, COM21. + Libraries come from the vendor folder via `lib_extra_dirs = ../../2-Program Example/Demo_Arduino/library`. + Each project uses its **own `include/lv_conf.h`** (`-DLV_CONF_INCLUDE_SIMPLE -Iinclude`): - `display_speed_wifi`: LVGL heap 4 MB in PSRAM (`ps_malloc`) - `display_gif_sd`: LVGL heap 7 MB in PSRAM -- `montserrat_100.c` (100 px digits font) is present but not referenced by any sketch yet. -- `display_gif_embedded` will not fit the 3 MB "Huge APP" partition with `loligod.c`; needs a custom partition table or the GIF on SD. -- SD-based GIFs use LVGL drive letter `A:`, which needs an LVGL filesystem driver configured in `lv_conf.h`. +- **Classic ESP32 projects:** official `espressif32@6.10.0` (Arduino core 2.0.17), board `esp32dev`, `huge_app.csv`. Set `upload_port` to the classic ESP32's COM port. + Bridge libraries: `powerbroker2/ELMduino@3.4.1`, `esphome/ESPAsyncWebServer-esphome@3.4.0`. + +## Notes +- `src/montserrat_100.c` (100 px digits font) is present but not referenced by any sketch yet. +- SD-based GIFs use LVGL drive `A:` = `LV_USE_FS_FATFS` (reads through ESP-IDF FatFS on the SD_MMC mount). Not yet verified on hardware. diff --git a/10-OBD-Display-2024/display_gif_embedded/lv_conf.h b/10-OBD-Display-2024/display_gif_embedded/include/lv_conf.h similarity index 100% rename from 10-OBD-Display-2024/display_gif_embedded/lv_conf.h rename to 10-OBD-Display-2024/display_gif_embedded/include/lv_conf.h diff --git a/10-OBD-Display-2024/display_gif_embedded/pincfg.h b/10-OBD-Display-2024/display_gif_embedded/include/pincfg.h similarity index 100% rename from 10-OBD-Display-2024/display_gif_embedded/pincfg.h rename to 10-OBD-Display-2024/display_gif_embedded/include/pincfg.h diff --git a/10-OBD-Display-2024/display_gif_embedded/scr_st77916.h b/10-OBD-Display-2024/display_gif_embedded/include/scr_st77916.h similarity index 100% rename from 10-OBD-Display-2024/display_gif_embedded/scr_st77916.h rename to 10-OBD-Display-2024/display_gif_embedded/include/scr_st77916.h diff --git a/10-OBD-Display-2024/display_gif_embedded/platformio.ini b/10-OBD-Display-2024/display_gif_embedded/platformio.ini new file mode 100644 index 0000000..a306284 --- /dev/null +++ b/10-OBD-Display-2024/display_gif_embedded/platformio.ini @@ -0,0 +1,29 @@ +; JC3636W518 — ESP32-S3R8, 16 MB QIO flash, 8 MB OPI PSRAM, 360x360 ST77916 QSPI + CST816S +; Settings mirror the vendor Arduino IDE setup (2-Program Example/Demo_Arduino/docs/Arduino set up.png) + +[env:jc3636w518] +; pioarduino = Arduino core 3.0.5 (ESP32_Display_Panel 0.1.4 needs core 3.x) +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip +board = esp32-s3-devkitc-1 +framework = arduino + +board_build.arduino.memory_type = qio_opi +board_build.flash_mode = qio +board_upload.flash_size = 16MB +; GIF compiled into firmware -> 3.4 MB, too big for huge_app (3 MB); 6.25 MB app slots +board_build.partitions = default_16MB.csv + +build_flags = + -DBOARD_HAS_PSRAM + -DARDUINO_USB_CDC_ON_BOOT=1 + ; LVGL (also when compiled as a library) picks up include/lv_conf.h of this project + -DLV_CONF_INCLUDE_SIMPLE + -Iinclude + +; vendor-bundled libraries: ESP32_Display_Panel 0.1.4, ESP32_IO_Expander 0.0.2, lvgl 8.3.11 +lib_extra_dirs = ../../2-Program Example/Demo_Arduino/library + +upload_port = COM21 +monitor_port = COM21 +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder diff --git a/10-OBD-Display-2024/display_gif_embedded/loligod.c b/10-OBD-Display-2024/display_gif_embedded/src/loligod.c similarity index 100% rename from 10-OBD-Display-2024/display_gif_embedded/loligod.c rename to 10-OBD-Display-2024/display_gif_embedded/src/loligod.c diff --git a/10-OBD-Display-2024/display_gif_embedded/display_gif_embedded.ino b/10-OBD-Display-2024/display_gif_embedded/src/main.cpp similarity index 96% rename from 10-OBD-Display-2024/display_gif_embedded/display_gif_embedded.ino rename to 10-OBD-Display-2024/display_gif_embedded/src/main.cpp index bc0ea6e..6c4be7a 100644 --- a/10-OBD-Display-2024/display_gif_embedded/display_gif_embedded.ino +++ b/10-OBD-Display-2024/display_gif_embedded/src/main.cpp @@ -1,192 +1,194 @@ -#include "scr_st77916.h" -#include "SD_MMC.h" - -#include "loligod.c" - -// https://randomnerdtutorials.com/esp32-client-server-wi-fi/ -#include -#include - -const char* ssid = "ESP32-Access-Point"; -const char* password = "123456789"; - - -void my_print(const char* buf) { - Serial.println(buf); // Print logs to the serial monitor -} - -void display_animation() { - lv_obj_t* img; - - LV_IMG_DECLARE(loligod); - - img = lv_gif_create(lv_scr_act()); - - Serial.print("Available Heap before: "); - Serial.println(esp_get_free_heap_size()); - - lv_mem_monitor_t mem_mon; - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - // lv_fs_file_t file; - // if (lv_fs_open(&file, "A:wallpaper.gif", LV_FS_MODE_RD) == LV_FS_RES_OK) { - // lv_fs_close(&file); // File exists, proceed with loading - // lv_gif_set_src(img, "A:wallpaper.gif"); - // Serial.println("GIF Loaded Successfully"); - // } else { - // Serial.println("Failed to Load GIF: File not found or inaccessible"); - // } - lv_gif_set_src(img, &loligod); - - Serial.print("Available Heap after: "); - Serial.println(esp_get_free_heap_size()); - - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); -} - -lv_obj_t* label1; - -void display_text() { - // Create a style for the text - static lv_style_t style_text; - lv_style_init(&style_text); - - // Set the text color to white - lv_style_set_text_color(&style_text, lv_color_white()); - - // // Set the shadow color to black (this will simulate the outline) - // lv_style_set_shadow_color(&style_text, lv_color_black()); - - // // Set the shadow width to create the outline effect - // lv_style_set_shadow_width(&style_text, 2); // Adjust for desired outline thickness - - // // Set the shadow offset to 0 so it surrounds the text evenly - // lv_style_set_shadow_ofs_x(&style_text, 0); - // lv_style_set_shadow_ofs_y(&style_text, 0); - - label1 = lv_label_create(lv_scr_act()); - - // Apply the style to the label - lv_obj_add_style(label1, &style_text, LV_PART_MAIN); - - // lv_style_set_text_font(&label1, &Montserrat); /*Set a larger font*/ - lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/ - lv_label_set_text(label1, "0"); - lv_obj_set_width(label1, 150); /*Set smaller width to make the lines wrap*/ - lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0); - lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0); - // lv_obj_set_style_transform_zoom(label1, 256 * 2, 0); // Zoom: 256 = 1x scale (default) -} - -void connectToWifi() { - WiFi.begin(ssid, password); - Serial.println("Connecting"); - if (WiFi.status() != WL_CONNECTED) { - Serial.println("Wifi not connected"); - return; - } - int timeout = 0; - while (WiFi.status() != WL_CONNECTED && timeout <= 20) { - timeout++; - delay(500); - Serial.print("."); - } - Serial.println(""); - Serial.print("Connected to WiFi network with IP Address: "); - Serial.println(WiFi.localIP()); -} - -void setup() { - delay(200); - Serial.begin(115200); - scr_lvgl_init(); - - lv_init(); - - //lv_log_register_print_cb(my_print); // Register print function for LVGL logs - - // Get the active screen (root object for the display) - lv_obj_t* screen = lv_scr_act(); - - // Set the background color of the entire screen to black - lv_obj_set_style_bg_color(screen, lv_color_black(), 0); // 0 is the part ID for the main part - lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0); // Set opacity to fully opaque - - // Configure the SDMMC host - SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); - - if (!SD_MMC.begin()) { - Serial.println("Card Mount Failed"); - return; - } - - uint8_t cardType = SD_MMC.cardType(); - if (cardType == CARD_NONE) { - Serial.println("No SD card attached"); - return; - } - - Serial.println("SD Card initialized successfully."); - - display_animation(); - - //connectToWifi(); - - //display_text(); -} - -void loop() { - lv_timer_handler(); - vTaskDelay(5); - - lv_mem_monitor_t mem_mon; - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - Serial.print("Available Heap: "); - Serial.println(esp_get_free_heap_size()); - - - // if (WiFi.status() == WL_CONNECTED) { - // String speed = httpGETRequest("http://192.168.4.1/speed"); - - // Serial.print("Speed: "); - // Serial.println(speed); - - // lv_label_set_text(label1, speed.c_str()); - // } else { - // Serial.println("WiFi Disconnected"); - // connectToWifi(); - // } -} - - -String httpGETRequest(const char* serverName) { - WiFiClient client; - HTTPClient http; - - // Your Domain name with URL path or IP address with path - http.begin(client, serverName); - - // Send HTTP POST request - int httpResponseCode = http.GET(); - - String payload = "--"; - - if (httpResponseCode > 0) { - Serial.print("HTTP Response code: "); - Serial.println(httpResponseCode); - payload = http.getString(); - } else { - Serial.print("Error code: "); - Serial.println(httpResponseCode); - } - // Free resources - http.end(); - - return payload; +#include +#include "scr_st77916.h" +#include "SD_MMC.h" + + +// https://randomnerdtutorials.com/esp32-client-server-wi-fi/ +#include +#include + +const char* ssid = "ESP32-Access-Point"; +const char* password = "123456789"; + +String httpGETRequest(const char* serverName); + + +void my_print(const char* buf) { + Serial.println(buf); // Print logs to the serial monitor +} + +void display_animation() { + lv_obj_t* img; + + LV_IMG_DECLARE(loligod); + + img = lv_gif_create(lv_scr_act()); + + Serial.print("Available Heap before: "); + Serial.println(esp_get_free_heap_size()); + + lv_mem_monitor_t mem_mon; + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + // lv_fs_file_t file; + // if (lv_fs_open(&file, "A:wallpaper.gif", LV_FS_MODE_RD) == LV_FS_RES_OK) { + // lv_fs_close(&file); // File exists, proceed with loading + // lv_gif_set_src(img, "A:wallpaper.gif"); + // Serial.println("GIF Loaded Successfully"); + // } else { + // Serial.println("Failed to Load GIF: File not found or inaccessible"); + // } + lv_gif_set_src(img, &loligod); + + Serial.print("Available Heap after: "); + Serial.println(esp_get_free_heap_size()); + + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); +} + +lv_obj_t* label1; + +void display_text() { + // Create a style for the text + static lv_style_t style_text; + lv_style_init(&style_text); + + // Set the text color to white + lv_style_set_text_color(&style_text, lv_color_white()); + + // // Set the shadow color to black (this will simulate the outline) + // lv_style_set_shadow_color(&style_text, lv_color_black()); + + // // Set the shadow width to create the outline effect + // lv_style_set_shadow_width(&style_text, 2); // Adjust for desired outline thickness + + // // Set the shadow offset to 0 so it surrounds the text evenly + // lv_style_set_shadow_ofs_x(&style_text, 0); + // lv_style_set_shadow_ofs_y(&style_text, 0); + + label1 = lv_label_create(lv_scr_act()); + + // Apply the style to the label + lv_obj_add_style(label1, &style_text, LV_PART_MAIN); + + // lv_style_set_text_font(&label1, &Montserrat); /*Set a larger font*/ + lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/ + lv_label_set_text(label1, "0"); + lv_obj_set_width(label1, 150); /*Set smaller width to make the lines wrap*/ + lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0); + lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0); + // lv_obj_set_style_transform_zoom(label1, 256 * 2, 0); // Zoom: 256 = 1x scale (default) +} + +void connectToWifi() { + WiFi.begin(ssid, password); + Serial.println("Connecting"); + if (WiFi.status() != WL_CONNECTED) { + Serial.println("Wifi not connected"); + return; + } + int timeout = 0; + while (WiFi.status() != WL_CONNECTED && timeout <= 20) { + timeout++; + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to WiFi network with IP Address: "); + Serial.println(WiFi.localIP()); +} + +void setup() { + delay(200); + Serial.begin(115200); + scr_lvgl_init(); + + lv_init(); + + //lv_log_register_print_cb(my_print); // Register print function for LVGL logs + + // Get the active screen (root object for the display) + lv_obj_t* screen = lv_scr_act(); + + // Set the background color of the entire screen to black + lv_obj_set_style_bg_color(screen, lv_color_black(), 0); // 0 is the part ID for the main part + lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0); // Set opacity to fully opaque + + // Configure the SDMMC host + SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); + + if (!SD_MMC.begin()) { + Serial.println("Card Mount Failed"); + return; + } + + uint8_t cardType = SD_MMC.cardType(); + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return; + } + + Serial.println("SD Card initialized successfully."); + + display_animation(); + + //connectToWifi(); + + //display_text(); +} + +void loop() { + lv_timer_handler(); + vTaskDelay(5); + + lv_mem_monitor_t mem_mon; + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + Serial.print("Available Heap: "); + Serial.println(esp_get_free_heap_size()); + + + // if (WiFi.status() == WL_CONNECTED) { + // String speed = httpGETRequest("http://192.168.4.1/speed"); + + // Serial.print("Speed: "); + // Serial.println(speed); + + // lv_label_set_text(label1, speed.c_str()); + // } else { + // Serial.println("WiFi Disconnected"); + // connectToWifi(); + // } +} + + +String httpGETRequest(const char* serverName) { + WiFiClient client; + HTTPClient http; + + // Your Domain name with URL path or IP address with path + http.begin(client, serverName); + + // Send HTTP POST request + int httpResponseCode = http.GET(); + + String payload = "--"; + + if (httpResponseCode > 0) { + Serial.print("HTTP Response code: "); + Serial.println(httpResponseCode); + payload = http.getString(); + } else { + Serial.print("Error code: "); + Serial.println(httpResponseCode); + } + // Free resources + http.end(); + + return payload; } \ No newline at end of file diff --git a/10-OBD-Display-2024/display_gif_embedded/montserrat_100.c b/10-OBD-Display-2024/display_gif_embedded/src/montserrat_100.c similarity index 100% rename from 10-OBD-Display-2024/display_gif_embedded/montserrat_100.c rename to 10-OBD-Display-2024/display_gif_embedded/src/montserrat_100.c diff --git a/10-OBD-Display-2024/display_gif_sd/lv_conf.h b/10-OBD-Display-2024/display_gif_sd/include/lv_conf.h similarity index 100% rename from 10-OBD-Display-2024/display_gif_sd/lv_conf.h rename to 10-OBD-Display-2024/display_gif_sd/include/lv_conf.h diff --git a/10-OBD-Display-2024/display_gif_sd/pincfg.h b/10-OBD-Display-2024/display_gif_sd/include/pincfg.h similarity index 100% rename from 10-OBD-Display-2024/display_gif_sd/pincfg.h rename to 10-OBD-Display-2024/display_gif_sd/include/pincfg.h diff --git a/10-OBD-Display-2024/display_gif_sd/scr_st77916.h b/10-OBD-Display-2024/display_gif_sd/include/scr_st77916.h similarity index 100% rename from 10-OBD-Display-2024/display_gif_sd/scr_st77916.h rename to 10-OBD-Display-2024/display_gif_sd/include/scr_st77916.h diff --git a/10-OBD-Display-2024/display_gif_sd/platformio.ini b/10-OBD-Display-2024/display_gif_sd/platformio.ini new file mode 100644 index 0000000..fbb9c1c --- /dev/null +++ b/10-OBD-Display-2024/display_gif_sd/platformio.ini @@ -0,0 +1,28 @@ +; JC3636W518 — ESP32-S3R8, 16 MB QIO flash, 8 MB OPI PSRAM, 360x360 ST77916 QSPI + CST816S +; Settings mirror the vendor Arduino IDE setup (2-Program Example/Demo_Arduino/docs/Arduino set up.png) + +[env:jc3636w518] +; pioarduino = Arduino core 3.0.5 (ESP32_Display_Panel 0.1.4 needs core 3.x) +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip +board = esp32-s3-devkitc-1 +framework = arduino + +board_build.arduino.memory_type = qio_opi +board_build.flash_mode = qio +board_upload.flash_size = 16MB +board_build.partitions = huge_app.csv + +build_flags = + -DBOARD_HAS_PSRAM + -DARDUINO_USB_CDC_ON_BOOT=1 + ; LVGL (also when compiled as a library) picks up include/lv_conf.h of this project + -DLV_CONF_INCLUDE_SIMPLE + -Iinclude + +; vendor-bundled libraries: ESP32_Display_Panel 0.1.4, ESP32_IO_Expander 0.0.2, lvgl 8.3.11 +lib_extra_dirs = ../../2-Program Example/Demo_Arduino/library + +upload_port = COM21 +monitor_port = COM21 +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder diff --git a/10-OBD-Display-2024/display_gif_sd/display_gif_sd.ino b/10-OBD-Display-2024/display_gif_sd/src/main.cpp similarity index 96% rename from 10-OBD-Display-2024/display_gif_sd/display_gif_sd.ino rename to 10-OBD-Display-2024/display_gif_sd/src/main.cpp index 5d24d54..0ba9792 100644 --- a/10-OBD-Display-2024/display_gif_sd/display_gif_sd.ino +++ b/10-OBD-Display-2024/display_gif_sd/src/main.cpp @@ -1,116 +1,117 @@ -#include "scr_st77916.h" -#include "SD_MMC.h" - -void my_print(const char* buf) { - Serial.println(buf); // Print logs to the serial monitor -} - -void display_animation() { - lv_obj_t* img; - - img = lv_gif_create(lv_scr_act()); - - Serial.print("Available Heap before: "); - Serial.println(esp_get_free_heap_size()); - - lv_mem_monitor_t mem_mon; - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - lv_fs_file_t file; - if (lv_fs_open(&file, "A:wallpaper.gif", LV_FS_MODE_RD) == LV_FS_RES_OK) { - lv_fs_close(&file); // File exists, proceed with loading - lv_gif_set_src(img, "A:wallpaper.gif"); - Serial.println("GIF Loaded Successfully"); - } else { - Serial.println("Failed to Load GIF: File not found or inaccessible"); - } - - Serial.print("Available Heap after: "); - Serial.println(esp_get_free_heap_size()); - - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); -} - -void display_text() { - // Create a style for the text - static lv_style_t style_text; - lv_style_init(&style_text); - - // Set the text color to white - lv_style_set_text_color(&style_text, lv_color_white()); - - // // Set the shadow color to black (this will simulate the outline) - // lv_style_set_shadow_color(&style_text, lv_color_black()); - - // // Set the shadow width to create the outline effect - // lv_style_set_shadow_width(&style_text, 2); // Adjust for desired outline thickness - - // // Set the shadow offset to 0 so it surrounds the text evenly - // lv_style_set_shadow_ofs_x(&style_text, 0); - // lv_style_set_shadow_ofs_y(&style_text, 0); - - lv_obj_t* label1 = lv_label_create(lv_scr_act()); - - // Apply the style to the label - lv_obj_add_style(label1, &style_text, LV_PART_MAIN); - - // lv_style_set_text_font(&label1, &LV_FONT_MONTSERRAT_46); /*Set a larger font*/ - lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/ - lv_label_set_text(label1, "Test text"); - lv_obj_set_width(label1, 150); /*Set smaller width to make the lines wrap*/ - lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0); - lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0); -} - -void setup() { - delay(200); - Serial.begin(115200); - scr_lvgl_init(); - - lv_init(); - - //lv_log_register_print_cb(my_print); // Register print function for LVGL logs - - // Get the active screen (root object for the display) - lv_obj_t* screen = lv_scr_act(); - - // Set the background color of the entire screen to black - lv_obj_set_style_bg_color(screen, lv_color_black(), 0); // 0 is the part ID for the main part - lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0); // Set opacity to fully opaque - - // Configure the SDMMC host - SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); - - if (!SD_MMC.begin()) { - Serial.println("Card Mount Failed"); - return; - } - - uint8_t cardType = SD_MMC.cardType(); - if (cardType == CARD_NONE) { - Serial.println("No SD card attached"); - return; - } - - Serial.println("SD Card initialized successfully."); - - display_animation(); - - display_text(); -} - -void loop() { - lv_timer_handler(); - vTaskDelay(5); - - lv_mem_monitor_t mem_mon; - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - Serial.print("Available Heap: "); - Serial.println(esp_get_free_heap_size()); -} +#include +#include "scr_st77916.h" +#include "SD_MMC.h" + +void my_print(const char* buf) { + Serial.println(buf); // Print logs to the serial monitor +} + +void display_animation() { + lv_obj_t* img; + + img = lv_gif_create(lv_scr_act()); + + Serial.print("Available Heap before: "); + Serial.println(esp_get_free_heap_size()); + + lv_mem_monitor_t mem_mon; + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + lv_fs_file_t file; + if (lv_fs_open(&file, "A:wallpaper.gif", LV_FS_MODE_RD) == LV_FS_RES_OK) { + lv_fs_close(&file); // File exists, proceed with loading + lv_gif_set_src(img, "A:wallpaper.gif"); + Serial.println("GIF Loaded Successfully"); + } else { + Serial.println("Failed to Load GIF: File not found or inaccessible"); + } + + Serial.print("Available Heap after: "); + Serial.println(esp_get_free_heap_size()); + + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); +} + +void display_text() { + // Create a style for the text + static lv_style_t style_text; + lv_style_init(&style_text); + + // Set the text color to white + lv_style_set_text_color(&style_text, lv_color_white()); + + // // Set the shadow color to black (this will simulate the outline) + // lv_style_set_shadow_color(&style_text, lv_color_black()); + + // // Set the shadow width to create the outline effect + // lv_style_set_shadow_width(&style_text, 2); // Adjust for desired outline thickness + + // // Set the shadow offset to 0 so it surrounds the text evenly + // lv_style_set_shadow_ofs_x(&style_text, 0); + // lv_style_set_shadow_ofs_y(&style_text, 0); + + lv_obj_t* label1 = lv_label_create(lv_scr_act()); + + // Apply the style to the label + lv_obj_add_style(label1, &style_text, LV_PART_MAIN); + + // lv_style_set_text_font(&label1, &LV_FONT_MONTSERRAT_46); /*Set a larger font*/ + lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/ + lv_label_set_text(label1, "Test text"); + lv_obj_set_width(label1, 150); /*Set smaller width to make the lines wrap*/ + lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0); + lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0); +} + +void setup() { + delay(200); + Serial.begin(115200); + scr_lvgl_init(); + + lv_init(); + + //lv_log_register_print_cb(my_print); // Register print function for LVGL logs + + // Get the active screen (root object for the display) + lv_obj_t* screen = lv_scr_act(); + + // Set the background color of the entire screen to black + lv_obj_set_style_bg_color(screen, lv_color_black(), 0); // 0 is the part ID for the main part + lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0); // Set opacity to fully opaque + + // Configure the SDMMC host + SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); + + if (!SD_MMC.begin()) { + Serial.println("Card Mount Failed"); + return; + } + + uint8_t cardType = SD_MMC.cardType(); + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return; + } + + Serial.println("SD Card initialized successfully."); + + display_animation(); + + display_text(); +} + +void loop() { + lv_timer_handler(); + vTaskDelay(5); + + lv_mem_monitor_t mem_mon; + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + Serial.print("Available Heap: "); + Serial.println(esp_get_free_heap_size()); +} diff --git a/10-OBD-Display-2024/display_speed_wifi/lv_conf.h b/10-OBD-Display-2024/display_speed_wifi/include/lv_conf.h similarity index 100% rename from 10-OBD-Display-2024/display_speed_wifi/lv_conf.h rename to 10-OBD-Display-2024/display_speed_wifi/include/lv_conf.h diff --git a/10-OBD-Display-2024/display_speed_wifi/pincfg.h b/10-OBD-Display-2024/display_speed_wifi/include/pincfg.h similarity index 100% rename from 10-OBD-Display-2024/display_speed_wifi/pincfg.h rename to 10-OBD-Display-2024/display_speed_wifi/include/pincfg.h diff --git a/10-OBD-Display-2024/display_speed_wifi/scr_st77916.h b/10-OBD-Display-2024/display_speed_wifi/include/scr_st77916.h similarity index 100% rename from 10-OBD-Display-2024/display_speed_wifi/scr_st77916.h rename to 10-OBD-Display-2024/display_speed_wifi/include/scr_st77916.h diff --git a/10-OBD-Display-2024/display_speed_wifi/platformio.ini b/10-OBD-Display-2024/display_speed_wifi/platformio.ini new file mode 100644 index 0000000..fbb9c1c --- /dev/null +++ b/10-OBD-Display-2024/display_speed_wifi/platformio.ini @@ -0,0 +1,28 @@ +; JC3636W518 — ESP32-S3R8, 16 MB QIO flash, 8 MB OPI PSRAM, 360x360 ST77916 QSPI + CST816S +; Settings mirror the vendor Arduino IDE setup (2-Program Example/Demo_Arduino/docs/Arduino set up.png) + +[env:jc3636w518] +; pioarduino = Arduino core 3.0.5 (ESP32_Display_Panel 0.1.4 needs core 3.x) +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip +board = esp32-s3-devkitc-1 +framework = arduino + +board_build.arduino.memory_type = qio_opi +board_build.flash_mode = qio +board_upload.flash_size = 16MB +board_build.partitions = huge_app.csv + +build_flags = + -DBOARD_HAS_PSRAM + -DARDUINO_USB_CDC_ON_BOOT=1 + ; LVGL (also when compiled as a library) picks up include/lv_conf.h of this project + -DLV_CONF_INCLUDE_SIMPLE + -Iinclude + +; vendor-bundled libraries: ESP32_Display_Panel 0.1.4, ESP32_IO_Expander 0.0.2, lvgl 8.3.11 +lib_extra_dirs = ../../2-Program Example/Demo_Arduino/library + +upload_port = COM21 +monitor_port = COM21 +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder diff --git a/10-OBD-Display-2024/display_speed_wifi/display_speed_wifi.ino b/10-OBD-Display-2024/display_speed_wifi/src/main.cpp similarity index 96% rename from 10-OBD-Display-2024/display_speed_wifi/display_speed_wifi.ino rename to 10-OBD-Display-2024/display_speed_wifi/src/main.cpp index 4a69b73..bee0f06 100644 --- a/10-OBD-Display-2024/display_speed_wifi/display_speed_wifi.ino +++ b/10-OBD-Display-2024/display_speed_wifi/src/main.cpp @@ -1,181 +1,184 @@ -#include "scr_st77916.h" -#include "SD_MMC.h" - -// https://randomnerdtutorials.com/esp32-client-server-wi-fi/ -#include -#include - -const char* ssid = "ESP32-Access-Point"; -const char* password = "123456789"; - - -void my_print(const char* buf) { - Serial.println(buf); // Print logs to the serial monitor -} - -void display_animation() { - lv_obj_t* img; - - img = lv_gif_create(lv_scr_act()); - - Serial.print("Available Heap before: "); - Serial.println(esp_get_free_heap_size()); - - lv_mem_monitor_t mem_mon; - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - lv_fs_file_t file; - if (lv_fs_open(&file, "A:wallpaper.gif", LV_FS_MODE_RD) == LV_FS_RES_OK) { - lv_fs_close(&file); // File exists, proceed with loading - lv_gif_set_src(img, "A:wallpaper.gif"); - Serial.println("GIF Loaded Successfully"); - } else { - Serial.println("Failed to Load GIF: File not found or inaccessible"); - } - - Serial.print("Available Heap after: "); - Serial.println(esp_get_free_heap_size()); - - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); -} - -lv_obj_t* label1; - -void display_text() { - // Create a style for the text - static lv_style_t style_text; - lv_style_init(&style_text); - - // Set the text color to white - lv_style_set_text_color(&style_text, lv_color_white()); - - // // Set the shadow color to black (this will simulate the outline) - // lv_style_set_shadow_color(&style_text, lv_color_black()); - - // // Set the shadow width to create the outline effect - // lv_style_set_shadow_width(&style_text, 2); // Adjust for desired outline thickness - - // // Set the shadow offset to 0 so it surrounds the text evenly - // lv_style_set_shadow_ofs_x(&style_text, 0); - // lv_style_set_shadow_ofs_y(&style_text, 0); - - label1 = lv_label_create(lv_scr_act()); - - // Apply the style to the label - lv_obj_add_style(label1, &style_text, LV_PART_MAIN); - - // lv_style_set_text_font(&label1, &Montserrat); /*Set a larger font*/ - lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/ - lv_label_set_text(label1, "0"); - lv_obj_set_width(label1, 150); /*Set smaller width to make the lines wrap*/ - lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0); - lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0); - // lv_obj_set_style_transform_zoom(label1, 256 * 2, 0); // Zoom: 256 = 1x scale (default) -} - -void connectToWifi() { - WiFi.begin(ssid, password); - Serial.println("Connecting"); - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - Serial.println(""); - Serial.print("Connected to WiFi network with IP Address: "); - Serial.println(WiFi.localIP()); -} - -void setup() { - delay(200); - Serial.begin(115200); - scr_lvgl_init(); - - lv_init(); - - //lv_log_register_print_cb(my_print); // Register print function for LVGL logs - - // Get the active screen (root object for the display) - lv_obj_t* screen = lv_scr_act(); - - // Set the background color of the entire screen to black - lv_obj_set_style_bg_color(screen, lv_color_black(), 0); // 0 is the part ID for the main part - lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0); // Set opacity to fully opaque - - // Configure the SDMMC host - SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); - - if (!SD_MMC.begin()) { - Serial.println("Card Mount Failed"); - return; - } - - uint8_t cardType = SD_MMC.cardType(); - if (cardType == CARD_NONE) { - Serial.println("No SD card attached"); - return; - } - - Serial.println("SD Card initialized successfully."); - - connectToWifi(); - - display_animation(); - - display_text(); -} - -void loop() { - lv_timer_handler(); - vTaskDelay(5); - - lv_mem_monitor_t mem_mon; - lv_mem_monitor(&mem_mon); - printf("Free memory: %d bytes\n", mem_mon.free_size); - - Serial.print("Available Heap: "); - Serial.println(esp_get_free_heap_size()); - - - if (WiFi.status() == WL_CONNECTED) { - String speed = httpGETRequest("http://192.168.4.1/speed"); - - Serial.print("Speed: "); - Serial.println(speed); - - lv_label_set_text(label1, speed.c_str()); - } else { - Serial.println("WiFi Disconnected"); - connectToWifi(); - } -} - - -String httpGETRequest(const char* serverName) { - WiFiClient client; - HTTPClient http; - - // Your Domain name with URL path or IP address with path - http.begin(client, serverName); - - // Send HTTP POST request - int httpResponseCode = http.GET(); - - String payload = "--"; - - if (httpResponseCode > 0) { - Serial.print("HTTP Response code: "); - Serial.println(httpResponseCode); - payload = http.getString(); - } else { - Serial.print("Error code: "); - Serial.println(httpResponseCode); - } - // Free resources - http.end(); - - return payload; +#include +#include "scr_st77916.h" +#include "SD_MMC.h" + +// https://randomnerdtutorials.com/esp32-client-server-wi-fi/ +#include +#include + +const char* ssid = "ESP32-Access-Point"; +const char* password = "123456789"; + +String httpGETRequest(const char* serverName); + + +void my_print(const char* buf) { + Serial.println(buf); // Print logs to the serial monitor +} + +void display_animation() { + lv_obj_t* img; + + img = lv_gif_create(lv_scr_act()); + + Serial.print("Available Heap before: "); + Serial.println(esp_get_free_heap_size()); + + lv_mem_monitor_t mem_mon; + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + lv_fs_file_t file; + if (lv_fs_open(&file, "A:wallpaper.gif", LV_FS_MODE_RD) == LV_FS_RES_OK) { + lv_fs_close(&file); // File exists, proceed with loading + lv_gif_set_src(img, "A:wallpaper.gif"); + Serial.println("GIF Loaded Successfully"); + } else { + Serial.println("Failed to Load GIF: File not found or inaccessible"); + } + + Serial.print("Available Heap after: "); + Serial.println(esp_get_free_heap_size()); + + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); +} + +lv_obj_t* label1; + +void display_text() { + // Create a style for the text + static lv_style_t style_text; + lv_style_init(&style_text); + + // Set the text color to white + lv_style_set_text_color(&style_text, lv_color_white()); + + // // Set the shadow color to black (this will simulate the outline) + // lv_style_set_shadow_color(&style_text, lv_color_black()); + + // // Set the shadow width to create the outline effect + // lv_style_set_shadow_width(&style_text, 2); // Adjust for desired outline thickness + + // // Set the shadow offset to 0 so it surrounds the text evenly + // lv_style_set_shadow_ofs_x(&style_text, 0); + // lv_style_set_shadow_ofs_y(&style_text, 0); + + label1 = lv_label_create(lv_scr_act()); + + // Apply the style to the label + lv_obj_add_style(label1, &style_text, LV_PART_MAIN); + + // lv_style_set_text_font(&label1, &Montserrat); /*Set a larger font*/ + lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP); /*Break the long lines*/ + lv_label_set_text(label1, "0"); + lv_obj_set_width(label1, 150); /*Set smaller width to make the lines wrap*/ + lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0); + lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0); + // lv_obj_set_style_transform_zoom(label1, 256 * 2, 0); // Zoom: 256 = 1x scale (default) +} + +void connectToWifi() { + WiFi.begin(ssid, password); + Serial.println("Connecting"); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to WiFi network with IP Address: "); + Serial.println(WiFi.localIP()); +} + +void setup() { + delay(200); + Serial.begin(115200); + scr_lvgl_init(); + + lv_init(); + + //lv_log_register_print_cb(my_print); // Register print function for LVGL logs + + // Get the active screen (root object for the display) + lv_obj_t* screen = lv_scr_act(); + + // Set the background color of the entire screen to black + lv_obj_set_style_bg_color(screen, lv_color_black(), 0); // 0 is the part ID for the main part + lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0); // Set opacity to fully opaque + + // Configure the SDMMC host + SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); + + if (!SD_MMC.begin()) { + Serial.println("Card Mount Failed"); + return; + } + + uint8_t cardType = SD_MMC.cardType(); + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return; + } + + Serial.println("SD Card initialized successfully."); + + connectToWifi(); + + display_animation(); + + display_text(); +} + +void loop() { + lv_timer_handler(); + vTaskDelay(5); + + lv_mem_monitor_t mem_mon; + lv_mem_monitor(&mem_mon); + printf("Free memory: %d bytes\n", mem_mon.free_size); + + Serial.print("Available Heap: "); + Serial.println(esp_get_free_heap_size()); + + + if (WiFi.status() == WL_CONNECTED) { + String speed = httpGETRequest("http://192.168.4.1/speed"); + + Serial.print("Speed: "); + Serial.println(speed); + + lv_label_set_text(label1, speed.c_str()); + } else { + Serial.println("WiFi Disconnected"); + connectToWifi(); + } +} + + +String httpGETRequest(const char* serverName) { + WiFiClient client; + HTTPClient http; + + // Your Domain name with URL path or IP address with path + http.begin(client, serverName); + + // Send HTTP POST request + int httpResponseCode = http.GET(); + + String payload = "--"; + + if (httpResponseCode > 0) { + Serial.print("HTTP Response code: "); + Serial.println(httpResponseCode); + payload = http.getString(); + } else { + Serial.print("Error code: "); + Serial.println(httpResponseCode); + } + // Free resources + http.end(); + + return payload; } \ No newline at end of file diff --git a/10-OBD-Display-2024/display_speed_wifi/montserrat_100.c b/10-OBD-Display-2024/display_speed_wifi/src/montserrat_100.c similarity index 100% rename from 10-OBD-Display-2024/display_speed_wifi/montserrat_100.c rename to 10-OBD-Display-2024/display_speed_wifi/src/montserrat_100.c diff --git a/10-OBD-Display-2024/elm327_wifi_bridge/platformio.ini b/10-OBD-Display-2024/elm327_wifi_bridge/platformio.ini new file mode 100644 index 0000000..4a44550 --- /dev/null +++ b/10-OBD-Display-2024/elm327_wifi_bridge/platformio.ini @@ -0,0 +1,18 @@ +; ELM327 -> WiFi bridge — runs on a CLASSIC ESP32 (needs Bluetooth Classic, which the ESP32-S3 lacks) +; Original note: "needs esp32 2.0.* in boards manager" -> official platform 6.10.0 = Arduino core 2.0.17 + +[env:esp32dev] +platform = espressif32@6.10.0 +board = esp32dev +framework = arduino + +; BluetoothSerial + WiFi + web server do not fit the default 1.2 MB app partition +board_build.partitions = huge_app.csv + +lib_deps = + powerbroker2/ELMduino@3.4.1 + esphome/ESPAsyncWebServer-esphome@3.4.0 + +; upload_port = COMxx ; set to the classic ESP32's port (COM21 is the JC3636W518) +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder diff --git a/10-OBD-Display-2024/elm327_wifi_bridge/elm327_wifi_bridge.ino b/10-OBD-Display-2024/elm327_wifi_bridge/src/main.cpp similarity index 95% rename from 10-OBD-Display-2024/elm327_wifi_bridge/elm327_wifi_bridge.ino rename to 10-OBD-Display-2024/elm327_wifi_bridge/src/main.cpp index bd72144..21f40dc 100644 --- a/10-OBD-Display-2024/elm327_wifi_bridge/elm327_wifi_bridge.ino +++ b/10-OBD-Display-2024/elm327_wifi_bridge/src/main.cpp @@ -1,95 +1,96 @@ -// Import required libraries -#include "WiFi.h" -#include -// needs esp32 2.0.* in boards manaager // https://forum.arduino.cc/t/libary-problem-with-esp32-web-server/1282583/6 - -// Set your access point network credentials -const char* ssid = "ESP32-Access-Point"; -const char* password = "123456789"; - - -#include "BluetoothSerial.h" -#include "ELMduino.h" - -// Create AsyncWebServer object on port 80 -AsyncWebServer server(80); - -BluetoothSerial SerialBT; -#define ELM_PORT SerialBT -#define DEBUG_PORT Serial - - -ELM327 myELM327; - - -uint32_t kph = 0; - -String readSpeed() { - if (ELM_PORT.isClosed()) { - return "0"; - } - - float tempkph = myELM327.kph(); - - if (myELM327.nb_rx_state == ELM_SUCCESS) { - kph = (uint32_t)tempkph; - Serial.print("kph: "); - Serial.println(kph); - } else if (myELM327.nb_rx_state != ELM_GETTING_MSG) - myELM327.printError(); - - return String(kph); - // return "123"; -} - -void connectElm() { - if (!ELM_PORT.connect("OBDII")) { - DEBUG_PORT.println("Couldn't connect to OBD scanner - Phase 1"); - // while (1) - // ; - return; - } - - if (!myELM327.begin(ELM_PORT, true, 2000)) { - Serial.println("Couldn't connect to OBD scanner - Phase 2"); - // while (1) - // ; - return; - } - - Serial.println("Connected to ELM327"); -} - -void setup() { - DEBUG_PORT.begin(115200); - SerialBT.setPin("1234"); - ELM_PORT.begin("ArduHUD", true); - - Serial.println("Starting ELM327 to wifi bridge"); - - //connectElm(); - - // Setting the ESP as an access point - Serial.print("Setting AP (Access Point)…"); - // Remove the password parameter, if you want the AP (Access Point) to be open - WiFi.softAP(ssid, password); - - IPAddress IP = WiFi.softAPIP(); - Serial.print("AP IP address: "); - Serial.println(IP); - - server.on("/speed", HTTP_GET, [](AsyncWebServerRequest* request) { - request->send_P(200, "text/plain", readSpeed().c_str()); - }); - - // Start server - server.begin(); -} - - -void loop() { - if (ELM_PORT.isClosed()) { - Serial.println("Trying to reconnect to ELM327"); - connectElm(); - } -} +#include +// Import required libraries +#include "WiFi.h" +#include +// needs esp32 2.0.* in boards manaager // https://forum.arduino.cc/t/libary-problem-with-esp32-web-server/1282583/6 + +// Set your access point network credentials +const char* ssid = "ESP32-Access-Point"; +const char* password = "123456789"; + + +#include "BluetoothSerial.h" +#include "ELMduino.h" + +// Create AsyncWebServer object on port 80 +AsyncWebServer server(80); + +BluetoothSerial SerialBT; +#define ELM_PORT SerialBT +#define DEBUG_PORT Serial + + +ELM327 myELM327; + + +uint32_t kph = 0; + +String readSpeed() { + if (ELM_PORT.isClosed()) { + return "0"; + } + + float tempkph = myELM327.kph(); + + if (myELM327.nb_rx_state == ELM_SUCCESS) { + kph = (uint32_t)tempkph; + Serial.print("kph: "); + Serial.println(kph); + } else if (myELM327.nb_rx_state != ELM_GETTING_MSG) + myELM327.printError(); + + return String(kph); + // return "123"; +} + +void connectElm() { + if (!ELM_PORT.connect("OBDII")) { + DEBUG_PORT.println("Couldn't connect to OBD scanner - Phase 1"); + // while (1) + // ; + return; + } + + if (!myELM327.begin(ELM_PORT, true, 2000)) { + Serial.println("Couldn't connect to OBD scanner - Phase 2"); + // while (1) + // ; + return; + } + + Serial.println("Connected to ELM327"); +} + +void setup() { + DEBUG_PORT.begin(115200); + SerialBT.setPin("1234"); + ELM_PORT.begin("ArduHUD", true); + + Serial.println("Starting ELM327 to wifi bridge"); + + //connectElm(); + + // Setting the ESP as an access point + Serial.print("Setting AP (Access Point)…"); + // Remove the password parameter, if you want the AP (Access Point) to be open + WiFi.softAP(ssid, password); + + IPAddress IP = WiFi.softAPIP(); + Serial.print("AP IP address: "); + Serial.println(IP); + + server.on("/speed", HTTP_GET, [](AsyncWebServerRequest* request) { + request->send_P(200, "text/plain", readSpeed().c_str()); + }); + + // Start server + server.begin(); +} + + +void loop() { + if (ELM_PORT.isClosed()) { + Serial.println("Trying to reconnect to ELM327"); + connectElm(); + } +} diff --git a/10-OBD-Display-2024/elmulator/.gitignore b/10-OBD-Display-2024/elmulator/.gitignore index 9493d46..3367fce 100644 --- a/10-OBD-Display-2024/elmulator/.gitignore +++ b/10-OBD-Display-2024/elmulator/.gitignore @@ -4,5 +4,4 @@ .vscode/launch.json .vscode/ipch .vscode/extensions.json -platformio.ini diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ATCommands.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ATCommands.cpp deleted file mode 100644 index 8c8f304..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ATCommands.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "ATCommands.h" -#include "definitions.h" - -#if USE_WIFI -ATCommands::ATCommands(OBDWiFiComm *connection) { - this->connection = connection; -} -#else -ATCommands::ATCommands(OBDSerialComm *connection) { - this->connection = connection; -} -#endif - -ATCommands::~ATCommands() { - operator delete(this->connection); -} - - -bool ATCommands::process(const String& command) { - bool processed = false; - if (isATCommand(command)) { - processed = true; - processCommand(command); - DEBUG("RX AT: " + command); - } - return processed; -} - -void ATCommands::processCommand(const String& command) { - - // if space is enabled (ex: AT H[charPosition]) - uint8_t offset = 2; - if (command.charAt(2) == 0x20) { - offset = 3; - } - - // refer to ELM327 specs - String specificCommand = command.substring(offset, command.length()); - if (specificCommand.startsWith("D",offset)) { - ATCommands::ATD(); - } else if (specificCommand.startsWith("Z")) { - ATCommands::ATZ(); - } else if (specificCommand.startsWith("I")) { - ATCommands::ATI(); - } else if (specificCommand.startsWith("E")) { - ATCommands::ATEx(specificCommand); - } else if (specificCommand.startsWith("L")) { - ATCommands::ATLx(specificCommand); - } else if (specificCommand.startsWith("M")) { - ATCommands::ATMx(specificCommand); - } else if (specificCommand.startsWith("S")) { - if (specificCommand.startsWith("SP")) { - ATCommands::ATSPx(specificCommand); - } else { - ATCommands::ATSx(specificCommand); - } - } else if (specificCommand.startsWith("H")) { - ATCommands::ATHx(specificCommand); - } else if (specificCommand.startsWith("AT")) { - ATCommands::ATATx(specificCommand); - } else if (specificCommand.startsWith("DPN")) { - ATCommands::ATDPN(); - } else if (specificCommand.startsWith("DESC") || specificCommand.startsWith("@1")) { - ATCommands::ATDESC(); - } else if (specificCommand.startsWith("PC")) { - ATCommands::ATPC(); - } else if (specificCommand.startsWith("RV")){ - ATCommands::ATRV(); - } else { - - // lets assume we process any at command - connection->writeEndOK(); - } -} - -// set all to defaults -void ATCommands::ATD() { - connection->setToDefaults(); - connection->writeEndOK(); -} - -// reset all -void ATCommands::ATZ() { - connection->setToDefaults(); - connection->writeTo(ID); - connection->writeEndOK(); -} - -// Print the version ID -void ATCommands::ATI() { - connection->writeTo(ID); - connection->writeEndOK(); -} - -// send description -void ATCommands::ATDESC() { - connection->writeTo(DESC); - connection->writeEndOK(); -} - -// set echoEnable 0=off 1=on -void ATCommands::ATEx(String& cmd) { - connection->setEcho(cmd.equals("E0") ? false : true); - connection->writeEndOK(); -} - -// set memory off=0 on=1 -void ATCommands::ATMx(String& cmd) { - connection->setMemory(cmd.equals("M0") ? false : true); - connection->writeEndOK(); -} - -// line feeds off=0 on=1 -void ATCommands::ATLx(String& cmd) { - connection->setLineFeeds(cmd.equals("L0") ? false : true); - connection->writeEndOK(); -} - -// ATSx printing spaces off=0 on=1 -void ATCommands::ATSx(String& cmd) { - connection->setWhiteSpaces(cmd.equals("S0") ? false : true); - connection->writeEndOK(); -} - -// Headers off=0 on=1 -void ATCommands::ATHx(String& cmd) { - connection->setHeaders(cmd.equals("H0") ? false : true); - connection->writeEndOK(); -} - -// ATSPx Define protocol 0=auto -void ATCommands::ATSPx(String& cmd) { - connection->writeEndOK(); -} - -// set protocol -void ATCommands::ATDPN() { - connection->writeTo(PROTOCOL); - connection->writeEndOK(); -} - -// AT AT2 adaptative time control -void ATCommands::ATATx(String& cmd) { - connection->writeEndOK(); -} - -// Terminates current diagnostic session. Protocol close -void ATCommands::ATPC() { - connection->writeEndOK(); -} - -void ATCommands::ATRV() { - connection->writeTo("AT RV\r13.5V"); - connection->writeEnd(); -} - -// return true ir connectionand is AT -bool ATCommands::isATCommand(const String& command) { - toUpperCase(command.charAt(0)); - return command.startsWith("AT") ? true : false; -} - diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ATCommands.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ATCommands.h deleted file mode 100644 index 00e729b..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ATCommands.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef ELMulator_ATCommands_h -#define ELMulator_ATCommands_h - -#include -#include "definitions.h" -#if USE_WIFI -#include "OBDWiFiComm.h" -#else -#include "OBDSerialComm.h" -#endif - -class ATCommands -{ - -public: -#if USE_WIFI - ATCommands(OBDWiFiComm *connection); -#else - ATCommands(OBDSerialComm *connection); -#endif - ~ATCommands(); - - bool process(const String &string); - -private: - // Variables -#if USE_WIFI - OBDWiFiComm *connection; -#else - OBDSerialComm *connection; -#endif - void ATD(); - - void ATZ(); - - void ATI(); - - void ATEx(String &x); - - void ATMx(String &x); - - void ATLx(String &x); - - void ATSx(String &x); - - void ATHx(String &x); - - void ATSPx(String &x); - - void ATATx(String &cmd); - - void ATPC(); - - void ATDPN(); - - void ATDESC(); - - void ATRV(); - - void processCommand(const String &command); - - bool isATCommand(const String &command); -}; - -#endif diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ELMulator.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ELMulator.cpp deleted file mode 100644 index 58ec398..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ELMulator.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "ELMulator.h" - -#if USE_WIFI -ELMulator::ELMulator() -{ - _connection = new OBDWiFiComm(); - _atProcessor = new ATCommands(_connection); - _pidProcessor = new PidProcessor(_connection); - _lastCommand = ""; - elmRequest.reserve(MAX_REQUEST_SIZE); - elmRequest = ""; -} -#else -ELMulator::ELMulator() -{ - _connection = new OBDSerialComm(); - _atProcessor = new ATCommands(_connection); - _pidProcessor = new PidProcessor(_connection); - _lastCommand = ""; - elmRequest.reserve(MAX_REQUEST_SIZE); - elmRequest = ""; -} -#endif - - - -ELMulator::~ELMulator() {} - -void ELMulator::init(const String &deviceName, bool registerPids) -{ - _connection->init(deviceName); - if (registerPids) - { - registerAllMode01Pids(); - } -} - -void ELMulator::registerAllMode01Pids() -{ - // Set up PIDs 0x00 to 0x65 - // Will be provided a response with mock data value if no special handling is performed. - // Requests for PID > 0x65 are not currently supported - will return "NO DATA" - for (int i = 0; i < 0x66; i++) - { - _pidProcessor->registerMode01Pid(i); - } -} - -bool ELMulator::readELMRequest() -{ - do - { - elmRequest.clear(); // clear buffer from previous requests - _connection->readData(elmRequest); - elmRequest.toUpperCase(); - // TODO ignore spaces, and all control chars (tab, etc) - // TODO accept single carriage return as repeat last command at or pid - // ignore null i.e 00 - } while (processRequest(elmRequest)); // processRequest handles all non PID requests (AT commands, errors etc) - return true; // We have received a valid PID request we need to respond to -} - -void ELMulator::sendELMResponse() -{ - // Respond to any mode 01 request with a mock sensor value - if (isMode01(elmRequest)) - { - uint8_t pidCode = getPidCode(elmRequest); - writePidResponse(elmRequest, responseBytes[pidCode], getMockSensorValue()); - return; - } - // Not a mode 01 PID request. Report it as not supported (ie, "NO DATA"); - else - { - writePidNotSupported(); - } -} - -void ELMulator::begin() -{ - while (readELMRequest()) - { - sendELMResponse(); - } -} - -uint8_t ELMulator::getPidCode(const String &request) -{ - return _pidProcessor->getPidCodeFromRequest(request); -} - -bool ELMulator::registerMode01Pid(uint32_t pid) -{ - return _pidProcessor->registerMode01Pid(pid); -} - -bool ELMulator::registerMode01MILResponse(const String &response) -{ - return _pidProcessor->registerMode01MILResponse(response); -} - -bool ELMulator::registerMode03Response(const String &response) -{ - return _pidProcessor->registerMode03Response(response); -} - -void ELMulator::writePidNotSupported() -{ - _connection->writeEndNoData(); -} - -void ELMulator::writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value) -{ - _pidProcessor->writePidResponse(requestPid, numberOfBytes, value); -} - -void ELMulator::writeResponse(const String &response) -{ - _connection->writeTo(response.c_str()); - _connection->writeEnd(); -} - -bool ELMulator::processRequest(String &command) -{ - - // TODO: check for no 0X0D char in command, return ? and > - // TODO: receive only , repeat last command - - // carriage return, means repeat last command - if (command == "\n") - { - command = _lastCommand; - } - - // empty command, do not send to user - if (command.length() == 0) - { - return true; - } - - // Check for AT command - if (_atProcessor->process(command)) - { - _lastCommand = command; - return true; - } - - // Check for a valid hex string, return error if false - if (!isValidHex(command.c_str())) - { - _connection->writeEndUnknown(); - DEBUG("Invalid HEX command: " + command); - return true; - } - - // Check for a valid PID request - if (_pidProcessor->process(command)) - { - _lastCommand = command; - return true; - } - - return false; -} - -bool ELMulator::isValidHex(const char *pid) -{ - return (pid[strspn(pid, "0123456789abcdefABCDEF")] == 0); -} - -bool ELMulator::isMode01(const String &command) -{ - return _pidProcessor->isMode01(command); -} - -bool ELMulator::isMode22(const String &command) -{ - return _pidProcessor->isMode22(command); -} - -bool ELMulator::isMode03(const String &command) -{ - return _pidProcessor->isMode03(command); -} - -bool ELMulator::isMode01MIL(const String &command) -{ - return _pidProcessor->isMode01MIL(command); -} - -/** - * Fake some data - * start counter = 0 - * every call to getFakeSensorData, will increment the counter to a max of 255 (0xff) - * When 0xff is reached the cycle is reverted - * and the counter will decrement by one until 0 is reached - */ -uint32_t ELMulator::getMockSensorValue() -{ - if (isCycleUp) - { - cycle++; - if (cycle == 0xff) - { - isCycleUp = false; - } - } - else - { - cycle--; - if (cycle == 0) - { - isCycleUp = true; - } - } - - return cycle; -} \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ELMulator.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ELMulator.h deleted file mode 100644 index 86cc077..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ELMulator.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef ELMulator_ELMulator_h -#define ELMulator_ELMulator_h - -#include -#include "definitions.h" - -#if USE_WIFI -#include "OBDWiFiComm.h" -#else -#include "OBDSerialComm.h" -#endif - -#include "ATCommands.h" -#include "PidProcessor.h" -#include "definitions.h" - -class ELMulator -{ - -public: - /** - * When creating a new instance of ELMulator with an attached - * BT module, we need to set the Bluetooth serial parameters - * - * @param baudRate - rate for bluetooth serial port (normally 9600) - * @param rxPin - the Arduino RX pin for the Bluetooth module (serial port) - * @param txPin - the Arduino TX pin for the Bluetooth module (serial port) - * @return - */ - ELMulator(uint32_t baudRate, uint8_t rxPin, uint8_t txPin); - - ELMulator(); - - ~ELMulator(); - - void init(const String &deviceName, const bool registerPids = false); - - /** - * Waits and Reads a request from OBD client software (example: torque) - * - * It will only return if the OBD client software - * request's one of the previous registred PID (see: registerMode01Pid()) - * - * Any other request will be automaticly handle or it will be rejected. - * - * ELMulator lib will automaticly handle: - * - any AT command - * - PID's support request like 0100, 0120, 0140, 0160, ... - * - * @return the request PID (Vehicle speed ex: 010D ) - */ - bool readELMRequest(); - void sendELMResponse(); - void begin(); - - /** - * Registry the PID's (sensors) your arduino will support. - * Currently ELMulator lib only supports MODE 01 PID's - * - * In OBDII MODE 01 PID's, are request - * to Show current data for a given sensor identified by a PID - * - * List of MODE 01 PID's: https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_01 - * - * Example, for Vehicle speed, where OBDII PID code is 0D: - * - * registerMode01Pid(0x0D) - * - * @param pidHexId - * @return returns true if the entered ID is in the valide range [0x00, 0xFF] - */ - bool registerMode01Pid(uint32_t pidHexId); - - bool registerMode01MILResponse(const String &response); - - bool registerMode03Response(const String &response); - - uint8_t getPidCodeOnly(uint16_t hexCommand); - - /** - * Used to informe the OBD client that the PID, - * it has requested is not supported - * - * In normal conditions, you will only receive, - * request for the PID you have registred - * All other request is automaticly handle by GTTuboEcu lib - */ - void writePidNotSupported(); - - /** - * Respond to a given PID request from OBDII client (ex: torque) - * - * @param requestPid - the received pid - * @param numberOfBytes - number of bytes this PID response VALUE is supposed to have - * @param value - sensor value for this PID, - * lib will convert it to HEX - * with the appropriated number of HEX chars (numberOfChars) - */ - void writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value); - - // Write the response back to the requestor without PID formatting, etc - // Just pass the response string on. Useful for testing with a specific response - // that has been pre-configured. - void writeResponse(const String &response); - - bool isMode01(const String &command); - bool isMode03(const String &command); - bool isMode01MIL(const String &command); - bool isMode22(const String &command); - - uint8_t getPidCode(const String &request); - void registerAllMode01Pids(); - uint32_t getMockSensorValue(); - - String elmRequest; - -private: -#if USE_WIFI - OBDWiFiComm *_connection; -#else - OBDSerialComm *_connection; -#endif - ATCommands *_atProcessor; - - PidProcessor *_pidProcessor; - - String _lastCommand; - - bool isCycleUp = true; - - uint32_t cycle = 0; - - bool processRequest(String &command); - - bool isValidHex(const char *pid); -}; - -#endif diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDSerialComm.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDSerialComm.cpp deleted file mode 100644 index d0509af..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDSerialComm.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "OBDSerialComm.h" -#include "definitions.h" - - -OBDSerialComm::OBDSerialComm() { - -} - -OBDSerialComm::~OBDSerialComm() { - operator delete(serial); -} - -void OBDSerialComm::init(const String& deviceName) { - Serial.println("Starting BT . . ."); - serial = new BluetoothSerial(); - //delay(2000); - serial->begin(deviceName, false); - setToDefaults(); - -} - -void OBDSerialComm::writeEnd() { - - // 1 - write carriage return - writeTo("\r"); - - // 2- (optional ) write linefeed - if (lineFeedEnable) { - writeTo("\n"); - } - - // 3 - Write prompt - writeTo(">"); - - serial->flush(); -}; - - -void OBDSerialComm::writeEndOK() { - writeTo("OK"); - writeEnd(); -} - -void OBDSerialComm::writeEndERROR() { - writeTo("ERROR"); - writeEnd(); -} - -void OBDSerialComm::writeEndNoData() { - writeTo("NO DATA"); - writeEnd(); -} - -void OBDSerialComm::writeEndUnknown() { - writeTo("?"); - writeEnd(); -} - -void OBDSerialComm::setToDefaults() { - setEcho(true); - setStatus(READY); - setWhiteSpaces(true); - setHeaders(false); - setLineFeeds(true); - setMemory(false); -} - -void OBDSerialComm::writeTo(char const *response) { - serial->print(response); -} - - -void OBDSerialComm::writeTo(uint8_t cChar) { - serial->print(cChar); -} - -void OBDSerialComm::writeEndPidTo(char const *response) { - if (whiteSpacesEnabled) { - uint8_t len = strlen(response); - char spacedResponse[len + len / 2 + 1]; - addSpacesToResponse(response, spacedResponse); - writeTo(spacedResponse); - } else { - writeTo(response); - } - writeEnd(); -} - -void OBDSerialComm::readData(String& rxData) { - serial->flush(); // temp remove this - rxData = serial->readStringUntil(SERIAL_END_CHAR); - if (isEchoEnable()) { - writeTo(rxData.c_str()); - } - //return rxData; -} - -void OBDSerialComm::setBaudRate(uint32_t rate) { - this->baudRate = rate; -} - -long OBDSerialComm::getBaudRate() { - return this->baudRate; -} - -bool OBDSerialComm::isEchoEnable() { - return this->echoEnable; -} - -void OBDSerialComm::setEcho(bool echo) { - this->echoEnable = echo; -} - -void OBDSerialComm::setStatus(STATUS status) { - this->status = status; -} - -void OBDSerialComm::setLineFeeds(bool status) { - this->lineFeedEnable = status; -} - -void OBDSerialComm::setMemory(bool status) { - this->memoryEnabled = status; -} - -void OBDSerialComm::setWhiteSpaces(bool status) { - this->whiteSpacesEnabled = status; -} - -void OBDSerialComm::setHeaders(bool status) { - this->headersEnabled = status; -} - -void OBDSerialComm::addSpacesToResponse(const char *response, char spacedRes[]) { - uint8_t len = strlen(response); - int j = 0; - for (int i = 0; i < len;) { - *(spacedRes + j++) = *(response + i++); - *(spacedRes + j++) = *(response + i++); - if (i < len) { - *(spacedRes + j++) = 0x20; - } - } - *(spacedRes + j) = '\0'; -} diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDSerialComm.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDSerialComm.h deleted file mode 100644 index 2059b28..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDSerialComm.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef ELMulator_OBDSerialComm_h -#define ELMulator_OBDSerialComm_h - -#include -#include "definitions.h" - -#include - - -class OBDSerialComm -{ -public: - enum STATUS - { - IDLE = 0, - READY = 1 - }; - -// // Bluetooth is not built in, we are using a BT module via GPIO -// OBDSerialComm(uint32_t baudRate, uint8_t rxPin, uint8_t txPin); - - OBDSerialComm(); - - ~OBDSerialComm(); - - void init(const String &deviceName); - - void writeEndOK(); - - void writeEndERROR(); - - /** - * Response for unsupported PID command or missing sensor, respond "NO DATA". - */ - void writeEndNoData(); - - /** - * Response for invalid AT command, or invalid PID or other bad input, respond "?" - */ - void writeEndUnknown(); - - void setToDefaults(); - - void readData(String &rxData); - - void writeTo(uint8_t cChar); - - void writeTo(char const *string); - - void setEcho(bool echo); - - void writeEnd(); - - bool isEchoEnable(); - - void setLineFeeds(bool status); - - void setMemory(bool status); - - void setWhiteSpaces(bool status); - - void setHeaders(bool status); - - void setStatus(STATUS status); - - void writeEndPidTo(char const *string); - -private: - uint32_t baudRate; // Serial Baud Rate - STATUS status; // Operation status - bool echoEnable; // echoEnable command after received - bool lineFeedEnable; - bool memoryEnabled; - bool whiteSpacesEnabled; - bool headersEnabled; - - void setBaudRate(uint32_t rate); - - long getBaudRate(); - - void addSpacesToResponse(const char *response, char string[]); - -#ifndef BLUETOOTH_BUILTIN - HardwareSerial *serial; // lib to communicate with bluetooth -#else - BluetoothSerial *serial; -#endif -}; - -#endif \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDWiFiComm.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDWiFiComm.cpp deleted file mode 100644 index 484b4f0..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDWiFiComm.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include "OBDWiFiComm.h" -#include "definitions.h" - -WiFiServer server(35000); -IPAddress localIP = IPAddress(192, 168, 0, 10); -IPAddress gateway = IPAddress(192, 168, 0, 10); -IPAddress subnet = IPAddress(255,255,255,0); - -OBDWiFiComm::OBDWiFiComm() { - -} - -OBDWiFiComm::~OBDWiFiComm() { -} - -void OBDWiFiComm::init(const String& deviceName) { - Serial.println("Starting AP . . ."); - - WiFi.softAPConfig(localIP, gateway, subnet); - WiFi.softAP(deviceName); - - IPAddress myIP = WiFi.softAPIP(); - Serial.print("AP IP address: "); - Serial.println(myIP); - Serial.print("AP SSID: "); - Serial.println(deviceName); - server.begin(); - setToDefaults(); -} - -void OBDWiFiComm::writeEnd() { - - // 1 - write carriage return - writeTo("\r"); - - // 2- (optional ) write linefeed - if (lineFeedEnable) { - writeTo("\n"); - } - - // 3 - Write prompt - writeTo(">"); -}; - - -void OBDWiFiComm::writeEndOK() { - writeTo("OK"); - writeEnd(); -} - -void OBDWiFiComm::writeEndERROR() { - writeTo("ERROR"); - writeEnd(); -} - -void OBDWiFiComm::writeEndNoData() { - writeTo("NO DATA"); - writeEnd(); -} - -void OBDWiFiComm::writeEndUnknown() { - writeTo("?"); - writeEnd(); -} - -void OBDWiFiComm::setToDefaults() { - setEcho(true); - setStatus(READY); - setWhiteSpaces(true); - setHeaders(false); - setLineFeeds(true); - setMemory(false); -} - -void OBDWiFiComm::writeTo(char const *response) { - client.print(response); -} - - -void OBDWiFiComm::writeTo(uint8_t cChar) { - client.print(cChar); -} - -void OBDWiFiComm::writeEndPidTo(char const *response) { - if (this->whiteSpacesEnabled) { - uint8_t len = strlen(response); - char spacedResponse[len + len / 2 + 1]; - addSpacesToResponse(response, spacedResponse); - writeTo(spacedResponse); - } else { - writeTo(response); - } - writeEnd(); -} - -void OBDWiFiComm::readData(String& rxData) { - if (!client.connected()) { - client = server.available(); - } - - if(client) - { - rxData - = client.readStringUntil(SERIAL_END_CHAR); - if (isEchoEnable()) - { - writeTo(rxData.c_str()); - } - } -} - -bool OBDWiFiComm::isEchoEnable() { - return this->echoEnable; -} - -void OBDWiFiComm::setEcho(bool echo) { - this->echoEnable = echo; -} - -void OBDWiFiComm::setStatus(STATUS status) { - this->status = status; -} - -void OBDWiFiComm::setLineFeeds(bool status) { - this->lineFeedEnable = status; -} - -void OBDWiFiComm::setMemory(bool status) { - this->memoryEnabled = status; -} - -void OBDWiFiComm::setWhiteSpaces(bool status) { - this->whiteSpacesEnabled = status; -} - -void OBDWiFiComm::setHeaders(bool status) { - this->headersEnabled = status; -} - -void OBDWiFiComm::addSpacesToResponse(const char *response, char spacedRes[]) { - uint8_t len = strlen(response); - int j = 0; - for (int i = 0; i < len;) { - *(spacedRes + j++) = *(response + i++); - *(spacedRes + j++) = *(response + i++); - if (i < len) { - *(spacedRes + j++) = 0x20; - } - } - *(spacedRes + j) = '\0'; -} diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDWiFiComm.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDWiFiComm.h deleted file mode 100644 index eb49098..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/OBDWiFiComm.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef ELMulator_OBDWiFiComm_h -#define ELMulator_OBDWiFiComm_h - -#include -#include -#include -#include "definitions.h" - - -class OBDWiFiComm -{ -public: - enum STATUS - { - IDLE = 0, - READY = 1 - }; - - OBDWiFiComm(); - - ~OBDWiFiComm(); - - void init(const String &deviceName); - - void writeEndOK(); - - void writeEndERROR(); - - /** - * Response for unsupported PID command or missing sensor, respond "NO DATA". - */ - void writeEndNoData(); - - /** - * Response for invalid AT command, or invalid PID or other bad input, respond "?" - */ - void writeEndUnknown(); - - void setToDefaults(); - - void readData(String &rxData); - - void writeTo(uint8_t cChar); - - void writeTo(char const *string); - - void setEcho(bool echo); - - void writeEnd(); - - bool isEchoEnable(); - - void setLineFeeds(bool status); - - void setMemory(bool status); - - void setWhiteSpaces(bool status); - - void setHeaders(bool status); - - void setStatus(STATUS status); - - void writeEndPidTo(char const *string); - -private: - STATUS status; // Operation status - bool echoEnable; // echoEnable command after received - bool lineFeedEnable; - bool memoryEnabled; - bool whiteSpacesEnabled; - bool headersEnabled; - - void addSpacesToResponse(const char *response, char string[]); - - WiFiClient client; -}; - -#endif \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/PidProcessor.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/PidProcessor.cpp deleted file mode 100644 index 9184f80..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/PidProcessor.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "PidProcessor.h" - -#if USE_WIFI -PidProcessor::PidProcessor(OBDWiFiComm *connection) { - _connection = connection; - resetPidMode01Array(); -}; -#else -PidProcessor::PidProcessor(OBDSerialComm *connection) { - _connection = connection; - resetPidMode01Array(); -}; -#endif - - -bool PidProcessor::process(String& command) { - bool processed = false; - - if (command.length() > 4) - { - command = command.substring(0, 4); // remove num_responses value if present; lib only handles single responses - } - - if (!isMode01(command) & !isMode22(command)) - { - _connection->writeEndNoData(); - return false; - } - - uint16_t hexCommand = strtoul(command.c_str(), NULL, HEX); - uint8_t pid = getPidCodeFromHex(hexCommand); - if (isSupportedPidRequest(pid)) { //reqeust to return a list of valid PIDs we can respond to - processed = true; - uint32_t supportedPids = getSupportedPids(pid); - writePidResponse(command, 4, supportedPids); - } - return processed; -} - -void PidProcessor::writePidResponse(const String& requestPid, uint8_t numberOfBytes, uint32_t value) { - uint8_t nHexChars = PID_N_BYTES * N_CHARS_IN_BYTE + numberOfBytes * N_CHARS_IN_BYTE ; - char responseArray[nHexChars + 1]; // one more for termination char - getFormattedResponse(responseArray, nHexChars, requestPid, value); - _connection->writeEndPidTo(responseArray); -} - -/** - * adds a supported pid, so it can answer to pid support request, ex 0100, 0120, ... - */ -bool PidProcessor::registerMode01Pid(uint32_t pid) { - // pid must be off type 01 - if (pid > 0x00 && pid < 0x0200) { - // remove PidMode, only use pid code - pid = getPidCodeFromHex(pid); - setPidBit(pid); - - char buffer[4]; - sprintf(buffer, "%02X", pid); - DEBUG("Registered PID: " + String(buffer )); - return true; - } - return false; -} - -bool PidProcessor::isMode01(const String& command) -{ - return command.startsWith("01") ? true : false; -} - -bool PidProcessor::isMode01MIL(const String& command) -{ - return command.startsWith("0101") ? true : false; -} - -bool PidProcessor::isMode03(const String& command) -{ - return command.startsWith("03") ? true : false; -} - -bool PidProcessor::isMode22(const String& command) -{ - return command.startsWith("22") ? true : false; -} - - -/** - * return true if: - * - 1000 - * - 1020 - * - 1040 - * - 1060 - * .... - */ -bool PidProcessor::isSupportedPidRequest(uint8_t pid) { - return pid == getPidIntervalId(pid); -} - -/** - * returns the interval RANGEID for the given pid (ex: 00, 20, 40, ...) - */ -uint8_t PidProcessor::getPidIntervalId(uint8_t pidcode) { - return getPidIntervalIndex(pidcode) * PID_INTERVAL_OFFSET; -} - -/** - * returns the interval INDEX for the given pid (0,1,2,3,4,...) - */ -uint8_t PidProcessor::getPidIntervalIndex(uint8_t pidcode) { - return pidcode / PID_INTERVAL_OFFSET; -} - -/** - * Receives a mode pid ex 010C , - * returns only the pid ex 0C - */ -uint8_t PidProcessor::getPidCodeFromHex(uint16_t hexCommand) { - - if (hexCommand >= 0x0100) { - hexCommand -= 0x100; - } - return (uint8_t) hexCommand; // return only the lower 8 bits (trim off num_messages or other extra bytes if present) -} - -/** - * Receives a complete PID request, - * returns only the pid ex 0C - */ -uint8_t PidProcessor::getPidCodeFromRequest(const String& request) { - uint16_t hexCommand = strtoul(request.c_str(), NULL, HEX); - return getPidCodeFromHex(hexCommand); -} - - -void PidProcessor::setPidBit(uint8_t pid) { - uint8_t arrayIndex = getPidIntervalIndex(pid); - if(isSupportedPidRequest(pid)) { - arrayIndex -= 1; - } - - uint8_t bitPosition = getPidBitPosition(pid); - bitWrite(pidMode01Supported[arrayIndex], bitPosition, 1); - - // mark available intervals - for (int i = 0; i < arrayIndex; i++) { - bitWrite(pidMode01Supported[i], 0, 1); - } -} - -uint8_t PidProcessor::getPidBitPosition(uint8_t pid) { - uint8_t intervalId = getPidIntervalId(pid) ; - if(isSupportedPidRequest(pid)) { - intervalId -= PID_INTERVAL_OFFSET; - } - - uint16_t pos = pid - intervalId; - pos = PID_INTERVAL_OFFSET - pos; - return pos; -} - - -uint32_t PidProcessor:: getSupportedPids(uint8_t pid) { - uint8_t index = getPidIntervalIndex(pid); - return pidMode01Supported[index]; -} - -void PidProcessor::getFormattedResponse(char *response, uint8_t totalNumberOfChars, const String& pid, uint32_t value) { - uint8_t nValueChars = totalNumberOfChars - PID_N_BYTES * N_CHARS_IN_BYTE; - char cValue[3] = {0}; - itoa(nValueChars, cValue, DEC); - String mask = "%s%0"; - mask.concat(cValue); - mask.concat("lX\0"); - String pidResponse = convertToPidResponse(pid); - sprintf(response, mask.c_str(), pidResponse.c_str(), value); - - DEBUG("RX PID: " + pid + " - TX: " + String(response)); -} - -String PidProcessor::convertToPidResponse(String pid) { - String x = "4"; - x.concat(pid.substring(1, pid.length())); - return x; -} - -void PidProcessor::resetPidMode01Array() { - for(uint8_t i = 0; i < N_MODE01_INTERVALS; i++ ) { - pidMode01Supported[i] = 0x0; - } -} - - - - - - diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/PidProcessor.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/PidProcessor.h deleted file mode 100644 index 378850b..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/PidProcessor.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef ELMulator_PIDPROCESSOR_H -#define ELMulator_PIDPROCESSOR_H - -#include "definitions.h" -#include -#include -#include -#include "OBDWiFiComm.h" -#include "OBDSerialComm.h" - -class PidProcessor -{ - -public: - PidProcessor(OBDWiFiComm *connection); - PidProcessor(OBDSerialComm *connection); - bool process(String &string); - - bool registerMode01Pid(uint32_t pid); - - bool registerMode01MILResponse(const String &response); - - bool registerMode03Response(const String &response); - - void writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value); - - uint8_t getPidCodeFromHex(uint16_t hexCommand); - uint8_t getPidCodeFromRequest(const String &command); - - bool isMode01(const String &command); - bool isMode01MIL(const String &command); - bool isMode03(const String &command); - bool isMode22(const String &command); - -private: -#if USE_WIFI - OBDWiFiComm *_connection; -#else - OBDSerialComm *_connection; -#endif - uint32_t pidMode01Supported[N_MODE01_INTERVALS]; - - bool isSupportedPidRequest(uint8_t pid); - - uint32_t getSupportedPids(uint8_t pidcode); - - uint8_t getPidIntervalId(uint8_t pidcode); - - uint8_t getPidIntervalIndex(uint8_t pidcode); - - void setPidBit(uint8_t pid); - - uint8_t getPidBitPosition(uint8_t pidcode); - - String convertToPidResponse(String pid); - - void getFormattedResponse(char *response, uint8_t totalNumberOfChars, const String &pid, uint32_t value); - - void resetPidMode01Array(); -}; - -#endif // ELMulator_PIDPROCESSOR_H diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/definitions.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/definitions.h deleted file mode 100644 index c1b030b..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/definitions.h +++ /dev/null @@ -1,294 +0,0 @@ -#ifndef ELMulator_DEFINITIONS_H -#define ELMulator_DEFINITIONS_H - -#include - -// true == We are running on hardware that has builtin Bluetooth -// false == We are using hardware that has BT module attached via GPIO pins -#define BLUETOOTH_BUILTIN true - -#define USE_WIFI false - -#define DO_DEBUG true -#define DEBUG(x) do {if (DO_DEBUG) { Serial.println(x); } } while (0) - -#define xtoc(x) ((x < 10) ? ('0' + x) : ('A' - 10 + x)) -#define getNumOfHexChars(nBytes) (nBytes * 2) - -#define PID_N_BYTES 2 -#define N_CHARS_IN_BYTE 2 - -// Device ID -#define ID "ELM327 / ELMulator V1.3.0" -#define DESC "ELMulator OBD2 Arduino library, based on ELM327 protocol" -#define PROTOCOL "6" // canbus 500k 11 bit protocol id for elm. - -// Char representing end of serial string -#define SERIAL_END_CHAR 0x0D -#define SERIAL_READ_TIMEOUT 20000L - -#define WIFI_END_CHAR 0x0A - -const uint8_t maxPid = 0xFF; -const uint8_t N_MODE01_INTERVALS = 7; -const uint8_t PID_INTERVAL_OFFSET = 0x20; -const uint8_t MAX_REQUEST_SIZE = 40; - - -//-------------------------------------------------------------------------------------// -// Protocol IDs -//-------------------------------------------------------------------------------------// -const char AUTOMATIC = '0'; -const char SAE_J1850_PWM_41_KBAUD = '1'; -const char SAE_J1850_PWM_10_KBAUD = '2'; -const char ISO_9141_5_BAUD_INIT = '3'; -const char ISO_14230_5_BAUD_INIT = '4'; -const char ISO_14230_FAST_INIT = '5'; -const char ISO_15765_11_BIT_500_KBAUD = '6'; -const char ISO_15765_29_BIT_500_KBAUD = '7'; -const char ISO_15765_11_BIT_250_KBAUD = '8'; -const char ISO_15765_29_BIT_250_KBAUD = '9'; -const char SAE_J1939_29_BIT_250_KBAUD = 'A'; -const char USER_1_CAN = 'B'; -const char USER_2_CAN = 'C'; - - - - -//-------------------------------------------------------------------------------------// -// PIDs (https://en.wikipedia.org/wiki/OBD-II_PIDs) -//-------------------------------------------------------------------------------------// -const uint8_t SUPPORTED_PIDS_1_20 = 0; // 0x00 - bit encoded -const uint8_t MONITOR_STATUS_SINCE_DTC_CLEARED = 1; // 0x01 - bit encoded -const uint8_t FREEZE_DTC = 2; // 0x02 - -const uint8_t FUEL_SYSTEM_STATUS = 3; // 0x03 - bit encoded -const uint8_t ENGINE_LOAD = 4; // 0x04 - % -const uint8_t ENGINE_COOLANT_TEMP = 5; // 0x05 - °C -const uint8_t SHORT_TERM_FUEL_TRIM_BANK_1 = 6; // 0x06 - % -const uint8_t LONG_TERM_FUEL_TRIM_BANK_1 = 7; // 0x07 - % -const uint8_t SHORT_TERM_FUEL_TRIM_BANK_2 = 8; // 0x08 - % -const uint8_t LONG_TERM_FUEL_TRIM_BANK_2 = 9; // 0x09 - % -const uint8_t FUEL_PRESSURE = 10; // 0x0A - kPa -const uint8_t INTAKE_MANIFOLD_ABS_PRESSURE = 11; // 0x0B - kPa -const uint8_t ENGINE_RPM = 12; // 0x0C - rpm -const uint8_t VEHICLE_SPEED = 13; // 0x0D - km/h -const uint8_t TIMING_ADVANCE = 14; // 0x0E - ° before TDC -const uint8_t INTAKE_AIR_TEMP = 15; // 0x0F - °C -const uint8_t MAF_FLOW_RATE = 16; // 0x10 - g/s -const uint8_t THROTTLE_POSITION = 17; // 0x11 - % -const uint8_t COMMANDED_SECONDARY_AIR_STATUS = 18; // 0x12 - bit encoded -const uint8_t OXYGEN_SENSORS_PRESENT_2_BANKS = 19; // 0x13 - bit encoded -const uint8_t OXYGEN_SENSOR_1_A = 20; // 0x14 - V % -const uint8_t OXYGEN_SENSOR_2_A = 21; // 0x15 - V % -const uint8_t OXYGEN_SENSOR_3_A = 22; // 0x16 - V % -const uint8_t OXYGEN_SENSOR_4_A = 23; // 0x17 - V % -const uint8_t OXYGEN_SENSOR_5_A = 24; // 0x18 - V % -const uint8_t OXYGEN_SENSOR_6_A = 25; // 0x19 - V % -const uint8_t OXYGEN_SENSOR_7_A = 26; // 0x1A - V % -const uint8_t OXYGEN_SENSOR_8_A = 27; // 0x1B - V % -const uint8_t OBD_STANDARDS = 28; // 0x1C - bit encoded -const uint8_t OXYGEN_SENSORS_PRESENT_4_BANKS = 29; // 0x1D - bit encoded -const uint8_t AUX_INPUT_STATUS = 30; // 0x1E - bit encoded -const uint8_t RUN_TIME_SINCE_ENGINE_START = 31; // 0x1F - sec - -const uint8_t SUPPORTED_PIDS_21_40 = 32; // 0x20 - bit encoded -const uint8_t DISTANCE_TRAVELED_WITH_MIL_ON = 33; // 0x21 - km -const uint8_t FUEL_RAIL_PRESSURE = 34; // 0x22 - kPa -const uint8_t FUEL_RAIL_GUAGE_PRESSURE = 35; // 0x23 - kPa -const uint8_t OXYGEN_SENSOR_1_B = 36; // 0x24 - ratio V -const uint8_t OXYGEN_SENSOR_2_B = 37; // 0x25 - ratio V -const uint8_t OXYGEN_SENSOR_3_B = 38; // 0x26 - ratio V -const uint8_t OXYGEN_SENSOR_4_B = 39; // 0x27 - ratio V -const uint8_t OXYGEN_SENSOR_5_B = 40; // 0x28 - ratio V -const uint8_t OXYGEN_SENSOR_6_B = 41; // 0x29 - ratio V -const uint8_t OXYGEN_SENSOR_7_B = 42; // 0x2A - ratio V -const uint8_t OXYGEN_SENSOR_8_B = 43; // 0x2B - ratio V -const uint8_t COMMANDED_EGR = 44; // 0x2C - % -const uint8_t EGR_ERROR = 45; // 0x2D - % -const uint8_t COMMANDED_EVAPORATIVE_PURGE = 46; // 0x2E - % -const uint8_t FUEL_TANK_LEVEL_INPUT = 47; // 0x2F - % -const uint8_t WARM_UPS_SINCE_CODES_CLEARED = 48; // 0x30 - count -const uint8_t DIST_TRAV_SINCE_CODES_CLEARED = 49; // 0x31 - km -const uint8_t EVAP_SYSTEM_VAPOR_PRESSURE = 50; // 0x32 - Pa -const uint8_t ABS_BAROMETRIC_PRESSURE = 51; // 0x33 - kPa -const uint8_t OXYGEN_SENSOR_1_C = 52; // 0x34 - ratio mA -const uint8_t OXYGEN_SENSOR_2_C = 53; // 0x35 - ratio mA -const uint8_t OXYGEN_SENSOR_3_C = 54; // 0x36 - ratio mA -const uint8_t OXYGEN_SENSOR_4_C = 55; // 0x37 - ratio mA -const uint8_t OXYGEN_SENSOR_5_C = 56; // 0x38 - ratio mA -const uint8_t OXYGEN_SENSOR_6_C = 57; // 0x39 - ratio mA -const uint8_t OXYGEN_SENSOR_7_C = 58; // 0x3A - ratio mA -const uint8_t OXYGEN_SENSOR_8_C = 59; // 0x3B - ratio mA -const uint8_t CATALYST_TEMP_BANK_1_SENSOR_1 = 60; // 0x3C - °C -const uint8_t CATALYST_TEMP_BANK_2_SENSOR_1 = 61; // 0x3D - °C -const uint8_t CATALYST_TEMP_BANK_1_SENSOR_2 = 62; // 0x3E - °C -const uint8_t CATALYST_TEMP_BANK_2_SENSOR_2 = 63; // 0x3F - °C - -const uint8_t SUPPORTED_PIDS_41_60 = 64; // 0x40 - bit encoded -const uint8_t MONITOR_STATUS_THIS_DRIVE_CYCLE = 65; // 0x41 - bit encoded -const uint8_t CONTROL_MODULE_VOLTAGE = 66; // 0x42 - V -const uint8_t ABS_LOAD_VALUE = 67; // 0x43 - % -const uint8_t FUEL_AIR_COMMANDED_EQUIV_RATIO = 68; // 0x44 - ratio -const uint8_t RELATIVE_THROTTLE_POSITION = 69; // 0x45 - % -const uint8_t AMBIENT_AIR_TEMP = 70; // 0x46 - °C -const uint8_t ABS_THROTTLE_POSITION_B = 71; // 0x47 - % -const uint8_t ABS_THROTTLE_POSITION_C = 72; // 0x48 - % -const uint8_t ABS_THROTTLE_POSITION_D = 73; // 0x49 - % -const uint8_t ABS_THROTTLE_POSITION_E = 74; // 0x4A - % -const uint8_t ABS_THROTTLE_POSITION_F = 75; // 0x4B - % -const uint8_t COMMANDED_THROTTLE_ACTUATOR = 76; // 0x4C - % -const uint8_t TIME_RUN_WITH_MIL_ON = 77; // 0x4D - min -const uint8_t TIME_SINCE_CODES_CLEARED = 78; // 0x4E - min -const uint8_t MAX_VALUES_EQUIV_V_I_PRESSURE = 79; // 0x4F - ratio V mA kPa -const uint8_t MAX_MAF_RATE = 80; // 0x50 - g/s -const uint8_t FUEL_TYPE = 81; // 0x51 - ref table -const uint8_t ETHANOL_FUEL_PERCENT = 82; // 0x52 - % -const uint8_t ABS_EVAP_SYS_VAPOR_PRESSURE = 83; // 0x53 - kPa -const uint8_t EVAP_SYS_VAPOR_PRESSURE = 84; // 0x54 - Pa -const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_1_3 = 85; // 0x55 - % -const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_1_3 = 86; // 0x56 - % -const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_2_4 = 87; // 0x57 - % -const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_2_4 = 88; // 0x58 - % -const uint8_t FUEL_RAIL_ABS_PRESSURE = 89; // 0x59 - kPa -const uint8_t RELATIVE_ACCELERATOR_PEDAL_POS = 90; // 0x5A - % -const uint8_t HYBRID_BATTERY_REMAINING_LIFE = 91; // 0x5B - % -const uint8_t ENGINE_OIL_TEMP = 92; // 0x5C - °C -const uint8_t FUEL_INJECTION_TIMING = 93; // 0x5D - ° -const uint8_t ENGINE_FUEL_RATE = 94; // 0x5E - L/h -const uint8_t EMISSION_REQUIREMENTS = 95; // 0x5F - bit encoded - -const uint8_t SUPPORTED_PIDS_61_80 = 96; // 0x60 - bit encoded -const uint8_t DEMANDED_ENGINE_PERCENT_TORQUE = 97; // 0x61 - % -const uint8_t ACTUAL_ENGINE_TORQUE = 98; // 0x62 - % -const uint8_t ENGINE_REFERENCE_TORQUE = 99; // 0x63 - Nm -const uint8_t ENGINE_PERCENT_TORQUE_DATA = 100; // 0x64 - % -const uint8_t AUX_INPUT_OUTPUT_SUPPORTED = 101; // 0x65 - bit encoded - -const uint8_t ODOMETER = 166; // 0xA6 - km * 10 - -const uint8_t SERVICE_01 = 1; -const uint8_t SERVICE_02 = 2; -const uint8_t SERVICE_03 = 3; - - -//-------------------------------------------------------------------------------------// -// AT commands (https://www.sparkfun.com/datasheets/Widgets/ELM327_AT_Commands.pdf) -//-------------------------------------------------------------------------------------// -const char * const DISP_DEVICE_DESCRIPT = "AT @1"; // General -const char * const DISP_DEVICE_ID = "AT @2"; // General -const char * const STORE_DEVICE_ID = "AT @3 %s"; // General -const char * const REPEAT_LAST_COMMAND = "AT \r"; // General -const char * const ALLOW_LONG_MESSAGES = "AT AL"; // General -const char * const AUTOMATIC_RECEIVE = "AT AR"; // OBD -const char * const ADAPTIVE_TIMING_OFF = "AT AT0"; // OBD -const char * const ADAPTIVE_TIMING_AUTO_1 = "AT AT1"; // OBD -const char * const ADAPTIVE_TIMING_AUTO_2 = "AT AT2"; // OBD -const char * const DUMP_BUFFER = "AT BD"; // OBD -const char * const BYPASS_INIT_SEQUENCE = "AT BI"; // OBD -const char * const TRY_BAUD_DIVISOR = "AT BRD %02d"; // General -const char * const SET_HANDSHAKE_TIMEOUT = "AT BRT %02d"; // General -const char * const CAN_AUTO_FORMAT_OFF = "AT CAF0"; // CAN -const char * const CAN_AUTO_FORMAT_ON = "AT CAF1"; // CAN -const char * const CAN_EXTENDED_ADDRESS_OFF = "AT CEA"; // CAN -const char * const USE_CAN_EXTENDED_ADDRESS = "AT CEA %02d"; // CAN -const char * const SET_ID_FILTER = "AT CF %s"; // CAN -const char * const CAN_FLOW_CONTROL_OFF = "AT CFC0"; // CAN -const char * const CAN_FLOW_CONTROL_ON = "AT CFC1"; // CAN -const char * const SET_ID_MASK = "AT CM %s"; // CAN -const char * const SET_CAN_PRIORITY = "AT CP %02d"; // CAN -const char * const SHOW_CAN_STATUS = "AT CS"; // CAN -const char * const CAN_SILENT_MODE_OFF = "AT CSM0"; // CAN -const char * const CAN_SILENT_MODE_ON = "AT CSM1"; // CAN -const char * const CALIBRATE_VOLTAGE_CUSTOM = "AT CV %04d"; // Volts -const char * const RESTORE_CV_TO_FACTORY = "AT CV 0000"; // Volts -const char * const SET_ALL_TO_DEFAULTS = "AT D"; // General -const char * const DISP_DLC_OFF = "AT D0"; // CAN -const char * const DISP_DLC_ON = "AT D1"; // CAN -const char * const MONITOR_FOR_DM1_MESSAGES = "AT DM1"; // J1939 -const char * const DISP_CURRENT_PROTOCOL = "AT DP"; // OBD -const char * const DISP_CURRENT_PROTOCOL_NUM = "AT DPN"; // OBD -const char * const ECHO_OFF = "AT E0"; // General -const char * const ECHO_ON = "AT E1"; // General -const char * const FLOW_CONTROL_SET_DATA_TO = "AT FC SD %s"; // CAN -const char * const FLOW_CONTROL_SET_HEAD_TO = "AT FC SH %s"; // CAN -const char * const FLOW_CONTROL_SET_MODE_TO = "AT FC SM %c"; // CAN -const char * const FORGE_EVENTS = "AT FE"; // General -const char * const PERFORM_FAST_INIT = "AT FI"; // ISO -const char * const HEADERS_OFF = "AT H0"; // OBD -const char * const HEADERS_ON = "AT H1"; // OBD -const char * const DISP_ID = "AT I"; // General -const char * const SET_ISO_BAUD_10400 = "AT IB 10"; // ISO -const char * const SET_ISO_BAUD_4800 = "AT IB 48"; // ISO -const char * const SET_ISO_BAUD_9600 = "AT IB 96"; // ISO -const char * const IFR_VAL_FROM_HEADER = "AT IFR H"; // J1850 -const char * const IFR_VAL_FROM_SOURCE = "AT IFR S"; // J1850 -const char * const IFRS_OFF = "AT IFR0"; // J1850 -const char * const IFRS_AUTO = "AT IFR1"; // J1850 -const char * const IFRS_ON = "AT IFR2"; // J1850 -const char * const IREAD_IGNMON_INPUT_LEVEL = "AT IGN"; // Other -const char * const SET_ISO_SLOW_INIT_ADDRESS = "AT IIA %02d"; // ISO -const char * const USE_J1939_ELM_DATA_FORMAT = "AT JE"; // J1850 -const char * const J1939_HEAD_FORMAT_OFF = "AT JHF0"; // J1850 -const char * const J1939_HEAD_FORMAT_ON = "AT JHF1"; // J1850 -const char * const USE_J1939_SAE_DATA_FORMAT = "AT JS"; // J1850 -const char * const SET_J1939_TIMER_X_TO_1X = "AT JTM1"; // J1850 -const char * const SET_J1939_TIMER_X_TO_5X = "AT JTM5"; // J1850 -const char * const DISP_KEY_WORDS = "AT KW"; // ISO -const char * const KEY_WORD_CHECKING_OFF = "AT KW0"; // ISO -const char * const KEY_WORD_CHECKING_ON = "AT KW1"; // ISO -const char * const LINEFEEDS_OFF = "AT L0"; // General -const char * const LINEFEEDS_ON = "AT L1"; // General -const char * const LOW_POWER_MODE = "AT LP"; // General -const char * const MEMORY_OFF = "AT M0"; // General -const char * const MEMORY_ON = "AT M1"; // General -const char * const MONITOR_ALL = "AT MA"; // OBD -const char * const MONITOR_FOR_PGN = "AT MP %s"; // J1939 -const char * const MONITOR_FOR_RECEIVER = "AT MR %02d"; // OBD -const char * const MONITOR_FOR_TRANSMITTER = "AT MT %02d"; // OBD -const char * const NORMAL_LENGTH_MESSAGES = "AT NL"; // OBD -const char * const SET_PROTO_OPTIONS_AND_BAUD = "AT PB %s"; // OBD -const char * const PROTOCOL_CLOSE = "AT PC"; // OBD -const char * const ALL_PROG_PARAMS_OFF = "AT PP FF OFF";// PPs -const char * const ALL_PROG_PARAMS_ON = "AT PP FF ON"; // PPs -const char * const SET_PROG_PARAM_OFF = "AT PP %s OFF";// PPs -const char * const SET_PROG_PARAM_ON = "AT PP %s ON"; // PPs -const char * const SET_PROG_PARAM_VAL = "AT PP %s SV %s"; // PPs -const char * const DISP_PP_SUMMARY = "AT PPS"; // PPs -const char * const RESPONSES_OFF = "AT R0"; // OBD -const char * const RESPONSES_ON = "AT R1"; // OBD -const char * const SET_RECEIVE_ADDRESS_TO = "AT RA %02d"; // OBD -const char * const READ_STORED_DATA = "AT RD"; // General -const char * const SEND_RTR_MESSAGE = "AT RTR"; // CAN -const char * const READ_VOLTAGE = "AT RV"; // Volts -const char * const PRINTING_SPACES_OFF = "AT S0"; // OBD -const char * const PRINTING_SPACES_ON = "AT S1"; // OBD -const char * const STORE_DATA_BYTE = "AT SD "; // General -const char * const SET_HEADER = "AT SH %s"; // OBD -const char * const PERFORM_SLOW_INIT = "AT SI"; // ISO -const char * const SET_PROTOCOL_TO_AUTO_H_SAVE = "AT SP A%c"; // OBD -const char * const SET_PROTOCOL_TO_H_SAVE = "AT SP %c"; // OBD -const char * const SET_PROTOCOL_TO_AUTO_SAVE = "AT SP 00"; // OBD -const char * const SET_REC_ADDRESS = "AT SR %02d"; // OBD -const char * const SET_STANDARD_SEARCH_ORDER = "AT SS"; // OBD -const char * const SET_TIMEOUT_TO_H_X_4MS = "AT ST %02d"; // OBD -const char * const SET_WAKEUP_TO_H_X_20MS = "AT SW %02d"; // ISO -const char * const SET_TESTER_ADDRESS_TO = "AT TA %02d"; // OBD -const char * const TRY_PROT_H_AUTO_SEARCH = "AT TP A%c"; // OBD -const char * const TRY_PROT_H = "AT TP %c"; // OBD -const char * const VARIABLE_DLC_OFF = "AT V0"; // CAN -const char * const VARIABLE_DLC_ON = "AT V1"; // CAN -const char * const SET_WAKEUP_MESSAGE = "AT WM"; // ISO -const char * const WARM_START = "AT WS"; // General -const char * const RESET_ALL = "AT Z"; // General - - -const uint8_t responseBytes[0xA9] = -{ - 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, - 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 4, 4, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, - 4, 1, 1, 2, 5, 2, 5, 3, 3, 7, 5, 5, 5, 11, 9, 3, 10, 6, 5, 5, 5, 7, 7, 5, 9, 9, 7, 7, 9, 1, 1, 13, - 4, 41, 41, 9, 1, 10, 5, 5, 13, 41, 41, 7, 17, 1, 1, 7, 3, 5, 2, 3, 12, 9, 9, 6, 4, 17, 4, 2, 9 -}; - -#endif //ELMulator_DEFINITIONS_H diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ATCommands.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ATCommands.cpp deleted file mode 100644 index 8c8f304..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ATCommands.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "ATCommands.h" -#include "definitions.h" - -#if USE_WIFI -ATCommands::ATCommands(OBDWiFiComm *connection) { - this->connection = connection; -} -#else -ATCommands::ATCommands(OBDSerialComm *connection) { - this->connection = connection; -} -#endif - -ATCommands::~ATCommands() { - operator delete(this->connection); -} - - -bool ATCommands::process(const String& command) { - bool processed = false; - if (isATCommand(command)) { - processed = true; - processCommand(command); - DEBUG("RX AT: " + command); - } - return processed; -} - -void ATCommands::processCommand(const String& command) { - - // if space is enabled (ex: AT H[charPosition]) - uint8_t offset = 2; - if (command.charAt(2) == 0x20) { - offset = 3; - } - - // refer to ELM327 specs - String specificCommand = command.substring(offset, command.length()); - if (specificCommand.startsWith("D",offset)) { - ATCommands::ATD(); - } else if (specificCommand.startsWith("Z")) { - ATCommands::ATZ(); - } else if (specificCommand.startsWith("I")) { - ATCommands::ATI(); - } else if (specificCommand.startsWith("E")) { - ATCommands::ATEx(specificCommand); - } else if (specificCommand.startsWith("L")) { - ATCommands::ATLx(specificCommand); - } else if (specificCommand.startsWith("M")) { - ATCommands::ATMx(specificCommand); - } else if (specificCommand.startsWith("S")) { - if (specificCommand.startsWith("SP")) { - ATCommands::ATSPx(specificCommand); - } else { - ATCommands::ATSx(specificCommand); - } - } else if (specificCommand.startsWith("H")) { - ATCommands::ATHx(specificCommand); - } else if (specificCommand.startsWith("AT")) { - ATCommands::ATATx(specificCommand); - } else if (specificCommand.startsWith("DPN")) { - ATCommands::ATDPN(); - } else if (specificCommand.startsWith("DESC") || specificCommand.startsWith("@1")) { - ATCommands::ATDESC(); - } else if (specificCommand.startsWith("PC")) { - ATCommands::ATPC(); - } else if (specificCommand.startsWith("RV")){ - ATCommands::ATRV(); - } else { - - // lets assume we process any at command - connection->writeEndOK(); - } -} - -// set all to defaults -void ATCommands::ATD() { - connection->setToDefaults(); - connection->writeEndOK(); -} - -// reset all -void ATCommands::ATZ() { - connection->setToDefaults(); - connection->writeTo(ID); - connection->writeEndOK(); -} - -// Print the version ID -void ATCommands::ATI() { - connection->writeTo(ID); - connection->writeEndOK(); -} - -// send description -void ATCommands::ATDESC() { - connection->writeTo(DESC); - connection->writeEndOK(); -} - -// set echoEnable 0=off 1=on -void ATCommands::ATEx(String& cmd) { - connection->setEcho(cmd.equals("E0") ? false : true); - connection->writeEndOK(); -} - -// set memory off=0 on=1 -void ATCommands::ATMx(String& cmd) { - connection->setMemory(cmd.equals("M0") ? false : true); - connection->writeEndOK(); -} - -// line feeds off=0 on=1 -void ATCommands::ATLx(String& cmd) { - connection->setLineFeeds(cmd.equals("L0") ? false : true); - connection->writeEndOK(); -} - -// ATSx printing spaces off=0 on=1 -void ATCommands::ATSx(String& cmd) { - connection->setWhiteSpaces(cmd.equals("S0") ? false : true); - connection->writeEndOK(); -} - -// Headers off=0 on=1 -void ATCommands::ATHx(String& cmd) { - connection->setHeaders(cmd.equals("H0") ? false : true); - connection->writeEndOK(); -} - -// ATSPx Define protocol 0=auto -void ATCommands::ATSPx(String& cmd) { - connection->writeEndOK(); -} - -// set protocol -void ATCommands::ATDPN() { - connection->writeTo(PROTOCOL); - connection->writeEndOK(); -} - -// AT AT2 adaptative time control -void ATCommands::ATATx(String& cmd) { - connection->writeEndOK(); -} - -// Terminates current diagnostic session. Protocol close -void ATCommands::ATPC() { - connection->writeEndOK(); -} - -void ATCommands::ATRV() { - connection->writeTo("AT RV\r13.5V"); - connection->writeEnd(); -} - -// return true ir connectionand is AT -bool ATCommands::isATCommand(const String& command) { - toUpperCase(command.charAt(0)); - return command.startsWith("AT") ? true : false; -} - diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ATCommands.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ATCommands.h deleted file mode 100644 index 00e729b..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ATCommands.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef ELMulator_ATCommands_h -#define ELMulator_ATCommands_h - -#include -#include "definitions.h" -#if USE_WIFI -#include "OBDWiFiComm.h" -#else -#include "OBDSerialComm.h" -#endif - -class ATCommands -{ - -public: -#if USE_WIFI - ATCommands(OBDWiFiComm *connection); -#else - ATCommands(OBDSerialComm *connection); -#endif - ~ATCommands(); - - bool process(const String &string); - -private: - // Variables -#if USE_WIFI - OBDWiFiComm *connection; -#else - OBDSerialComm *connection; -#endif - void ATD(); - - void ATZ(); - - void ATI(); - - void ATEx(String &x); - - void ATMx(String &x); - - void ATLx(String &x); - - void ATSx(String &x); - - void ATHx(String &x); - - void ATSPx(String &x); - - void ATATx(String &cmd); - - void ATPC(); - - void ATDPN(); - - void ATDESC(); - - void ATRV(); - - void processCommand(const String &command); - - bool isATCommand(const String &command); -}; - -#endif diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ELMulator.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ELMulator.cpp deleted file mode 100644 index 58ec398..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ELMulator.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "ELMulator.h" - -#if USE_WIFI -ELMulator::ELMulator() -{ - _connection = new OBDWiFiComm(); - _atProcessor = new ATCommands(_connection); - _pidProcessor = new PidProcessor(_connection); - _lastCommand = ""; - elmRequest.reserve(MAX_REQUEST_SIZE); - elmRequest = ""; -} -#else -ELMulator::ELMulator() -{ - _connection = new OBDSerialComm(); - _atProcessor = new ATCommands(_connection); - _pidProcessor = new PidProcessor(_connection); - _lastCommand = ""; - elmRequest.reserve(MAX_REQUEST_SIZE); - elmRequest = ""; -} -#endif - - - -ELMulator::~ELMulator() {} - -void ELMulator::init(const String &deviceName, bool registerPids) -{ - _connection->init(deviceName); - if (registerPids) - { - registerAllMode01Pids(); - } -} - -void ELMulator::registerAllMode01Pids() -{ - // Set up PIDs 0x00 to 0x65 - // Will be provided a response with mock data value if no special handling is performed. - // Requests for PID > 0x65 are not currently supported - will return "NO DATA" - for (int i = 0; i < 0x66; i++) - { - _pidProcessor->registerMode01Pid(i); - } -} - -bool ELMulator::readELMRequest() -{ - do - { - elmRequest.clear(); // clear buffer from previous requests - _connection->readData(elmRequest); - elmRequest.toUpperCase(); - // TODO ignore spaces, and all control chars (tab, etc) - // TODO accept single carriage return as repeat last command at or pid - // ignore null i.e 00 - } while (processRequest(elmRequest)); // processRequest handles all non PID requests (AT commands, errors etc) - return true; // We have received a valid PID request we need to respond to -} - -void ELMulator::sendELMResponse() -{ - // Respond to any mode 01 request with a mock sensor value - if (isMode01(elmRequest)) - { - uint8_t pidCode = getPidCode(elmRequest); - writePidResponse(elmRequest, responseBytes[pidCode], getMockSensorValue()); - return; - } - // Not a mode 01 PID request. Report it as not supported (ie, "NO DATA"); - else - { - writePidNotSupported(); - } -} - -void ELMulator::begin() -{ - while (readELMRequest()) - { - sendELMResponse(); - } -} - -uint8_t ELMulator::getPidCode(const String &request) -{ - return _pidProcessor->getPidCodeFromRequest(request); -} - -bool ELMulator::registerMode01Pid(uint32_t pid) -{ - return _pidProcessor->registerMode01Pid(pid); -} - -bool ELMulator::registerMode01MILResponse(const String &response) -{ - return _pidProcessor->registerMode01MILResponse(response); -} - -bool ELMulator::registerMode03Response(const String &response) -{ - return _pidProcessor->registerMode03Response(response); -} - -void ELMulator::writePidNotSupported() -{ - _connection->writeEndNoData(); -} - -void ELMulator::writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value) -{ - _pidProcessor->writePidResponse(requestPid, numberOfBytes, value); -} - -void ELMulator::writeResponse(const String &response) -{ - _connection->writeTo(response.c_str()); - _connection->writeEnd(); -} - -bool ELMulator::processRequest(String &command) -{ - - // TODO: check for no 0X0D char in command, return ? and > - // TODO: receive only , repeat last command - - // carriage return, means repeat last command - if (command == "\n") - { - command = _lastCommand; - } - - // empty command, do not send to user - if (command.length() == 0) - { - return true; - } - - // Check for AT command - if (_atProcessor->process(command)) - { - _lastCommand = command; - return true; - } - - // Check for a valid hex string, return error if false - if (!isValidHex(command.c_str())) - { - _connection->writeEndUnknown(); - DEBUG("Invalid HEX command: " + command); - return true; - } - - // Check for a valid PID request - if (_pidProcessor->process(command)) - { - _lastCommand = command; - return true; - } - - return false; -} - -bool ELMulator::isValidHex(const char *pid) -{ - return (pid[strspn(pid, "0123456789abcdefABCDEF")] == 0); -} - -bool ELMulator::isMode01(const String &command) -{ - return _pidProcessor->isMode01(command); -} - -bool ELMulator::isMode22(const String &command) -{ - return _pidProcessor->isMode22(command); -} - -bool ELMulator::isMode03(const String &command) -{ - return _pidProcessor->isMode03(command); -} - -bool ELMulator::isMode01MIL(const String &command) -{ - return _pidProcessor->isMode01MIL(command); -} - -/** - * Fake some data - * start counter = 0 - * every call to getFakeSensorData, will increment the counter to a max of 255 (0xff) - * When 0xff is reached the cycle is reverted - * and the counter will decrement by one until 0 is reached - */ -uint32_t ELMulator::getMockSensorValue() -{ - if (isCycleUp) - { - cycle++; - if (cycle == 0xff) - { - isCycleUp = false; - } - } - else - { - cycle--; - if (cycle == 0) - { - isCycleUp = true; - } - } - - return cycle; -} \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ELMulator.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ELMulator.h deleted file mode 100644 index 86cc077..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ELMulator.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef ELMulator_ELMulator_h -#define ELMulator_ELMulator_h - -#include -#include "definitions.h" - -#if USE_WIFI -#include "OBDWiFiComm.h" -#else -#include "OBDSerialComm.h" -#endif - -#include "ATCommands.h" -#include "PidProcessor.h" -#include "definitions.h" - -class ELMulator -{ - -public: - /** - * When creating a new instance of ELMulator with an attached - * BT module, we need to set the Bluetooth serial parameters - * - * @param baudRate - rate for bluetooth serial port (normally 9600) - * @param rxPin - the Arduino RX pin for the Bluetooth module (serial port) - * @param txPin - the Arduino TX pin for the Bluetooth module (serial port) - * @return - */ - ELMulator(uint32_t baudRate, uint8_t rxPin, uint8_t txPin); - - ELMulator(); - - ~ELMulator(); - - void init(const String &deviceName, const bool registerPids = false); - - /** - * Waits and Reads a request from OBD client software (example: torque) - * - * It will only return if the OBD client software - * request's one of the previous registred PID (see: registerMode01Pid()) - * - * Any other request will be automaticly handle or it will be rejected. - * - * ELMulator lib will automaticly handle: - * - any AT command - * - PID's support request like 0100, 0120, 0140, 0160, ... - * - * @return the request PID (Vehicle speed ex: 010D ) - */ - bool readELMRequest(); - void sendELMResponse(); - void begin(); - - /** - * Registry the PID's (sensors) your arduino will support. - * Currently ELMulator lib only supports MODE 01 PID's - * - * In OBDII MODE 01 PID's, are request - * to Show current data for a given sensor identified by a PID - * - * List of MODE 01 PID's: https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_01 - * - * Example, for Vehicle speed, where OBDII PID code is 0D: - * - * registerMode01Pid(0x0D) - * - * @param pidHexId - * @return returns true if the entered ID is in the valide range [0x00, 0xFF] - */ - bool registerMode01Pid(uint32_t pidHexId); - - bool registerMode01MILResponse(const String &response); - - bool registerMode03Response(const String &response); - - uint8_t getPidCodeOnly(uint16_t hexCommand); - - /** - * Used to informe the OBD client that the PID, - * it has requested is not supported - * - * In normal conditions, you will only receive, - * request for the PID you have registred - * All other request is automaticly handle by GTTuboEcu lib - */ - void writePidNotSupported(); - - /** - * Respond to a given PID request from OBDII client (ex: torque) - * - * @param requestPid - the received pid - * @param numberOfBytes - number of bytes this PID response VALUE is supposed to have - * @param value - sensor value for this PID, - * lib will convert it to HEX - * with the appropriated number of HEX chars (numberOfChars) - */ - void writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value); - - // Write the response back to the requestor without PID formatting, etc - // Just pass the response string on. Useful for testing with a specific response - // that has been pre-configured. - void writeResponse(const String &response); - - bool isMode01(const String &command); - bool isMode03(const String &command); - bool isMode01MIL(const String &command); - bool isMode22(const String &command); - - uint8_t getPidCode(const String &request); - void registerAllMode01Pids(); - uint32_t getMockSensorValue(); - - String elmRequest; - -private: -#if USE_WIFI - OBDWiFiComm *_connection; -#else - OBDSerialComm *_connection; -#endif - ATCommands *_atProcessor; - - PidProcessor *_pidProcessor; - - String _lastCommand; - - bool isCycleUp = true; - - uint32_t cycle = 0; - - bool processRequest(String &command); - - bool isValidHex(const char *pid); -}; - -#endif diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDSerialComm.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDSerialComm.cpp deleted file mode 100644 index d0509af..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDSerialComm.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "OBDSerialComm.h" -#include "definitions.h" - - -OBDSerialComm::OBDSerialComm() { - -} - -OBDSerialComm::~OBDSerialComm() { - operator delete(serial); -} - -void OBDSerialComm::init(const String& deviceName) { - Serial.println("Starting BT . . ."); - serial = new BluetoothSerial(); - //delay(2000); - serial->begin(deviceName, false); - setToDefaults(); - -} - -void OBDSerialComm::writeEnd() { - - // 1 - write carriage return - writeTo("\r"); - - // 2- (optional ) write linefeed - if (lineFeedEnable) { - writeTo("\n"); - } - - // 3 - Write prompt - writeTo(">"); - - serial->flush(); -}; - - -void OBDSerialComm::writeEndOK() { - writeTo("OK"); - writeEnd(); -} - -void OBDSerialComm::writeEndERROR() { - writeTo("ERROR"); - writeEnd(); -} - -void OBDSerialComm::writeEndNoData() { - writeTo("NO DATA"); - writeEnd(); -} - -void OBDSerialComm::writeEndUnknown() { - writeTo("?"); - writeEnd(); -} - -void OBDSerialComm::setToDefaults() { - setEcho(true); - setStatus(READY); - setWhiteSpaces(true); - setHeaders(false); - setLineFeeds(true); - setMemory(false); -} - -void OBDSerialComm::writeTo(char const *response) { - serial->print(response); -} - - -void OBDSerialComm::writeTo(uint8_t cChar) { - serial->print(cChar); -} - -void OBDSerialComm::writeEndPidTo(char const *response) { - if (whiteSpacesEnabled) { - uint8_t len = strlen(response); - char spacedResponse[len + len / 2 + 1]; - addSpacesToResponse(response, spacedResponse); - writeTo(spacedResponse); - } else { - writeTo(response); - } - writeEnd(); -} - -void OBDSerialComm::readData(String& rxData) { - serial->flush(); // temp remove this - rxData = serial->readStringUntil(SERIAL_END_CHAR); - if (isEchoEnable()) { - writeTo(rxData.c_str()); - } - //return rxData; -} - -void OBDSerialComm::setBaudRate(uint32_t rate) { - this->baudRate = rate; -} - -long OBDSerialComm::getBaudRate() { - return this->baudRate; -} - -bool OBDSerialComm::isEchoEnable() { - return this->echoEnable; -} - -void OBDSerialComm::setEcho(bool echo) { - this->echoEnable = echo; -} - -void OBDSerialComm::setStatus(STATUS status) { - this->status = status; -} - -void OBDSerialComm::setLineFeeds(bool status) { - this->lineFeedEnable = status; -} - -void OBDSerialComm::setMemory(bool status) { - this->memoryEnabled = status; -} - -void OBDSerialComm::setWhiteSpaces(bool status) { - this->whiteSpacesEnabled = status; -} - -void OBDSerialComm::setHeaders(bool status) { - this->headersEnabled = status; -} - -void OBDSerialComm::addSpacesToResponse(const char *response, char spacedRes[]) { - uint8_t len = strlen(response); - int j = 0; - for (int i = 0; i < len;) { - *(spacedRes + j++) = *(response + i++); - *(spacedRes + j++) = *(response + i++); - if (i < len) { - *(spacedRes + j++) = 0x20; - } - } - *(spacedRes + j) = '\0'; -} diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDSerialComm.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDSerialComm.h deleted file mode 100644 index 2059b28..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDSerialComm.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef ELMulator_OBDSerialComm_h -#define ELMulator_OBDSerialComm_h - -#include -#include "definitions.h" - -#include - - -class OBDSerialComm -{ -public: - enum STATUS - { - IDLE = 0, - READY = 1 - }; - -// // Bluetooth is not built in, we are using a BT module via GPIO -// OBDSerialComm(uint32_t baudRate, uint8_t rxPin, uint8_t txPin); - - OBDSerialComm(); - - ~OBDSerialComm(); - - void init(const String &deviceName); - - void writeEndOK(); - - void writeEndERROR(); - - /** - * Response for unsupported PID command or missing sensor, respond "NO DATA". - */ - void writeEndNoData(); - - /** - * Response for invalid AT command, or invalid PID or other bad input, respond "?" - */ - void writeEndUnknown(); - - void setToDefaults(); - - void readData(String &rxData); - - void writeTo(uint8_t cChar); - - void writeTo(char const *string); - - void setEcho(bool echo); - - void writeEnd(); - - bool isEchoEnable(); - - void setLineFeeds(bool status); - - void setMemory(bool status); - - void setWhiteSpaces(bool status); - - void setHeaders(bool status); - - void setStatus(STATUS status); - - void writeEndPidTo(char const *string); - -private: - uint32_t baudRate; // Serial Baud Rate - STATUS status; // Operation status - bool echoEnable; // echoEnable command after received - bool lineFeedEnable; - bool memoryEnabled; - bool whiteSpacesEnabled; - bool headersEnabled; - - void setBaudRate(uint32_t rate); - - long getBaudRate(); - - void addSpacesToResponse(const char *response, char string[]); - -#ifndef BLUETOOTH_BUILTIN - HardwareSerial *serial; // lib to communicate with bluetooth -#else - BluetoothSerial *serial; -#endif -}; - -#endif \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDWiFiComm.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDWiFiComm.cpp deleted file mode 100644 index 484b4f0..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDWiFiComm.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include "OBDWiFiComm.h" -#include "definitions.h" - -WiFiServer server(35000); -IPAddress localIP = IPAddress(192, 168, 0, 10); -IPAddress gateway = IPAddress(192, 168, 0, 10); -IPAddress subnet = IPAddress(255,255,255,0); - -OBDWiFiComm::OBDWiFiComm() { - -} - -OBDWiFiComm::~OBDWiFiComm() { -} - -void OBDWiFiComm::init(const String& deviceName) { - Serial.println("Starting AP . . ."); - - WiFi.softAPConfig(localIP, gateway, subnet); - WiFi.softAP(deviceName); - - IPAddress myIP = WiFi.softAPIP(); - Serial.print("AP IP address: "); - Serial.println(myIP); - Serial.print("AP SSID: "); - Serial.println(deviceName); - server.begin(); - setToDefaults(); -} - -void OBDWiFiComm::writeEnd() { - - // 1 - write carriage return - writeTo("\r"); - - // 2- (optional ) write linefeed - if (lineFeedEnable) { - writeTo("\n"); - } - - // 3 - Write prompt - writeTo(">"); -}; - - -void OBDWiFiComm::writeEndOK() { - writeTo("OK"); - writeEnd(); -} - -void OBDWiFiComm::writeEndERROR() { - writeTo("ERROR"); - writeEnd(); -} - -void OBDWiFiComm::writeEndNoData() { - writeTo("NO DATA"); - writeEnd(); -} - -void OBDWiFiComm::writeEndUnknown() { - writeTo("?"); - writeEnd(); -} - -void OBDWiFiComm::setToDefaults() { - setEcho(true); - setStatus(READY); - setWhiteSpaces(true); - setHeaders(false); - setLineFeeds(true); - setMemory(false); -} - -void OBDWiFiComm::writeTo(char const *response) { - client.print(response); -} - - -void OBDWiFiComm::writeTo(uint8_t cChar) { - client.print(cChar); -} - -void OBDWiFiComm::writeEndPidTo(char const *response) { - if (this->whiteSpacesEnabled) { - uint8_t len = strlen(response); - char spacedResponse[len + len / 2 + 1]; - addSpacesToResponse(response, spacedResponse); - writeTo(spacedResponse); - } else { - writeTo(response); - } - writeEnd(); -} - -void OBDWiFiComm::readData(String& rxData) { - if (!client.connected()) { - client = server.available(); - } - - if(client) - { - rxData - = client.readStringUntil(SERIAL_END_CHAR); - if (isEchoEnable()) - { - writeTo(rxData.c_str()); - } - } -} - -bool OBDWiFiComm::isEchoEnable() { - return this->echoEnable; -} - -void OBDWiFiComm::setEcho(bool echo) { - this->echoEnable = echo; -} - -void OBDWiFiComm::setStatus(STATUS status) { - this->status = status; -} - -void OBDWiFiComm::setLineFeeds(bool status) { - this->lineFeedEnable = status; -} - -void OBDWiFiComm::setMemory(bool status) { - this->memoryEnabled = status; -} - -void OBDWiFiComm::setWhiteSpaces(bool status) { - this->whiteSpacesEnabled = status; -} - -void OBDWiFiComm::setHeaders(bool status) { - this->headersEnabled = status; -} - -void OBDWiFiComm::addSpacesToResponse(const char *response, char spacedRes[]) { - uint8_t len = strlen(response); - int j = 0; - for (int i = 0; i < len;) { - *(spacedRes + j++) = *(response + i++); - *(spacedRes + j++) = *(response + i++); - if (i < len) { - *(spacedRes + j++) = 0x20; - } - } - *(spacedRes + j) = '\0'; -} diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDWiFiComm.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDWiFiComm.h deleted file mode 100644 index eb49098..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/OBDWiFiComm.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef ELMulator_OBDWiFiComm_h -#define ELMulator_OBDWiFiComm_h - -#include -#include -#include -#include "definitions.h" - - -class OBDWiFiComm -{ -public: - enum STATUS - { - IDLE = 0, - READY = 1 - }; - - OBDWiFiComm(); - - ~OBDWiFiComm(); - - void init(const String &deviceName); - - void writeEndOK(); - - void writeEndERROR(); - - /** - * Response for unsupported PID command or missing sensor, respond "NO DATA". - */ - void writeEndNoData(); - - /** - * Response for invalid AT command, or invalid PID or other bad input, respond "?" - */ - void writeEndUnknown(); - - void setToDefaults(); - - void readData(String &rxData); - - void writeTo(uint8_t cChar); - - void writeTo(char const *string); - - void setEcho(bool echo); - - void writeEnd(); - - bool isEchoEnable(); - - void setLineFeeds(bool status); - - void setMemory(bool status); - - void setWhiteSpaces(bool status); - - void setHeaders(bool status); - - void setStatus(STATUS status); - - void writeEndPidTo(char const *string); - -private: - STATUS status; // Operation status - bool echoEnable; // echoEnable command after received - bool lineFeedEnable; - bool memoryEnabled; - bool whiteSpacesEnabled; - bool headersEnabled; - - void addSpacesToResponse(const char *response, char string[]); - - WiFiClient client; -}; - -#endif \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/PidProcessor.cpp b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/PidProcessor.cpp deleted file mode 100644 index 9184f80..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/PidProcessor.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "PidProcessor.h" - -#if USE_WIFI -PidProcessor::PidProcessor(OBDWiFiComm *connection) { - _connection = connection; - resetPidMode01Array(); -}; -#else -PidProcessor::PidProcessor(OBDSerialComm *connection) { - _connection = connection; - resetPidMode01Array(); -}; -#endif - - -bool PidProcessor::process(String& command) { - bool processed = false; - - if (command.length() > 4) - { - command = command.substring(0, 4); // remove num_responses value if present; lib only handles single responses - } - - if (!isMode01(command) & !isMode22(command)) - { - _connection->writeEndNoData(); - return false; - } - - uint16_t hexCommand = strtoul(command.c_str(), NULL, HEX); - uint8_t pid = getPidCodeFromHex(hexCommand); - if (isSupportedPidRequest(pid)) { //reqeust to return a list of valid PIDs we can respond to - processed = true; - uint32_t supportedPids = getSupportedPids(pid); - writePidResponse(command, 4, supportedPids); - } - return processed; -} - -void PidProcessor::writePidResponse(const String& requestPid, uint8_t numberOfBytes, uint32_t value) { - uint8_t nHexChars = PID_N_BYTES * N_CHARS_IN_BYTE + numberOfBytes * N_CHARS_IN_BYTE ; - char responseArray[nHexChars + 1]; // one more for termination char - getFormattedResponse(responseArray, nHexChars, requestPid, value); - _connection->writeEndPidTo(responseArray); -} - -/** - * adds a supported pid, so it can answer to pid support request, ex 0100, 0120, ... - */ -bool PidProcessor::registerMode01Pid(uint32_t pid) { - // pid must be off type 01 - if (pid > 0x00 && pid < 0x0200) { - // remove PidMode, only use pid code - pid = getPidCodeFromHex(pid); - setPidBit(pid); - - char buffer[4]; - sprintf(buffer, "%02X", pid); - DEBUG("Registered PID: " + String(buffer )); - return true; - } - return false; -} - -bool PidProcessor::isMode01(const String& command) -{ - return command.startsWith("01") ? true : false; -} - -bool PidProcessor::isMode01MIL(const String& command) -{ - return command.startsWith("0101") ? true : false; -} - -bool PidProcessor::isMode03(const String& command) -{ - return command.startsWith("03") ? true : false; -} - -bool PidProcessor::isMode22(const String& command) -{ - return command.startsWith("22") ? true : false; -} - - -/** - * return true if: - * - 1000 - * - 1020 - * - 1040 - * - 1060 - * .... - */ -bool PidProcessor::isSupportedPidRequest(uint8_t pid) { - return pid == getPidIntervalId(pid); -} - -/** - * returns the interval RANGEID for the given pid (ex: 00, 20, 40, ...) - */ -uint8_t PidProcessor::getPidIntervalId(uint8_t pidcode) { - return getPidIntervalIndex(pidcode) * PID_INTERVAL_OFFSET; -} - -/** - * returns the interval INDEX for the given pid (0,1,2,3,4,...) - */ -uint8_t PidProcessor::getPidIntervalIndex(uint8_t pidcode) { - return pidcode / PID_INTERVAL_OFFSET; -} - -/** - * Receives a mode pid ex 010C , - * returns only the pid ex 0C - */ -uint8_t PidProcessor::getPidCodeFromHex(uint16_t hexCommand) { - - if (hexCommand >= 0x0100) { - hexCommand -= 0x100; - } - return (uint8_t) hexCommand; // return only the lower 8 bits (trim off num_messages or other extra bytes if present) -} - -/** - * Receives a complete PID request, - * returns only the pid ex 0C - */ -uint8_t PidProcessor::getPidCodeFromRequest(const String& request) { - uint16_t hexCommand = strtoul(request.c_str(), NULL, HEX); - return getPidCodeFromHex(hexCommand); -} - - -void PidProcessor::setPidBit(uint8_t pid) { - uint8_t arrayIndex = getPidIntervalIndex(pid); - if(isSupportedPidRequest(pid)) { - arrayIndex -= 1; - } - - uint8_t bitPosition = getPidBitPosition(pid); - bitWrite(pidMode01Supported[arrayIndex], bitPosition, 1); - - // mark available intervals - for (int i = 0; i < arrayIndex; i++) { - bitWrite(pidMode01Supported[i], 0, 1); - } -} - -uint8_t PidProcessor::getPidBitPosition(uint8_t pid) { - uint8_t intervalId = getPidIntervalId(pid) ; - if(isSupportedPidRequest(pid)) { - intervalId -= PID_INTERVAL_OFFSET; - } - - uint16_t pos = pid - intervalId; - pos = PID_INTERVAL_OFFSET - pos; - return pos; -} - - -uint32_t PidProcessor:: getSupportedPids(uint8_t pid) { - uint8_t index = getPidIntervalIndex(pid); - return pidMode01Supported[index]; -} - -void PidProcessor::getFormattedResponse(char *response, uint8_t totalNumberOfChars, const String& pid, uint32_t value) { - uint8_t nValueChars = totalNumberOfChars - PID_N_BYTES * N_CHARS_IN_BYTE; - char cValue[3] = {0}; - itoa(nValueChars, cValue, DEC); - String mask = "%s%0"; - mask.concat(cValue); - mask.concat("lX\0"); - String pidResponse = convertToPidResponse(pid); - sprintf(response, mask.c_str(), pidResponse.c_str(), value); - - DEBUG("RX PID: " + pid + " - TX: " + String(response)); -} - -String PidProcessor::convertToPidResponse(String pid) { - String x = "4"; - x.concat(pid.substring(1, pid.length())); - return x; -} - -void PidProcessor::resetPidMode01Array() { - for(uint8_t i = 0; i < N_MODE01_INTERVALS; i++ ) { - pidMode01Supported[i] = 0x0; - } -} - - - - - - diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/PidProcessor.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/PidProcessor.h deleted file mode 100644 index 378850b..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/PidProcessor.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef ELMulator_PIDPROCESSOR_H -#define ELMulator_PIDPROCESSOR_H - -#include "definitions.h" -#include -#include -#include -#include "OBDWiFiComm.h" -#include "OBDSerialComm.h" - -class PidProcessor -{ - -public: - PidProcessor(OBDWiFiComm *connection); - PidProcessor(OBDSerialComm *connection); - bool process(String &string); - - bool registerMode01Pid(uint32_t pid); - - bool registerMode01MILResponse(const String &response); - - bool registerMode03Response(const String &response); - - void writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value); - - uint8_t getPidCodeFromHex(uint16_t hexCommand); - uint8_t getPidCodeFromRequest(const String &command); - - bool isMode01(const String &command); - bool isMode01MIL(const String &command); - bool isMode03(const String &command); - bool isMode22(const String &command); - -private: -#if USE_WIFI - OBDWiFiComm *_connection; -#else - OBDSerialComm *_connection; -#endif - uint32_t pidMode01Supported[N_MODE01_INTERVALS]; - - bool isSupportedPidRequest(uint8_t pid); - - uint32_t getSupportedPids(uint8_t pidcode); - - uint8_t getPidIntervalId(uint8_t pidcode); - - uint8_t getPidIntervalIndex(uint8_t pidcode); - - void setPidBit(uint8_t pid); - - uint8_t getPidBitPosition(uint8_t pidcode); - - String convertToPidResponse(String pid); - - void getFormattedResponse(char *response, uint8_t totalNumberOfChars, const String &pid, uint32_t value); - - void resetPidMode01Array(); -}; - -#endif // ELMulator_PIDPROCESSOR_H diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/definitions.h b/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/definitions.h deleted file mode 100644 index c1b030b..0000000 --- a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/definitions.h +++ /dev/null @@ -1,294 +0,0 @@ -#ifndef ELMulator_DEFINITIONS_H -#define ELMulator_DEFINITIONS_H - -#include - -// true == We are running on hardware that has builtin Bluetooth -// false == We are using hardware that has BT module attached via GPIO pins -#define BLUETOOTH_BUILTIN true - -#define USE_WIFI false - -#define DO_DEBUG true -#define DEBUG(x) do {if (DO_DEBUG) { Serial.println(x); } } while (0) - -#define xtoc(x) ((x < 10) ? ('0' + x) : ('A' - 10 + x)) -#define getNumOfHexChars(nBytes) (nBytes * 2) - -#define PID_N_BYTES 2 -#define N_CHARS_IN_BYTE 2 - -// Device ID -#define ID "ELM327 / ELMulator V1.3.0" -#define DESC "ELMulator OBD2 Arduino library, based on ELM327 protocol" -#define PROTOCOL "6" // canbus 500k 11 bit protocol id for elm. - -// Char representing end of serial string -#define SERIAL_END_CHAR 0x0D -#define SERIAL_READ_TIMEOUT 20000L - -#define WIFI_END_CHAR 0x0A - -const uint8_t maxPid = 0xFF; -const uint8_t N_MODE01_INTERVALS = 7; -const uint8_t PID_INTERVAL_OFFSET = 0x20; -const uint8_t MAX_REQUEST_SIZE = 40; - - -//-------------------------------------------------------------------------------------// -// Protocol IDs -//-------------------------------------------------------------------------------------// -const char AUTOMATIC = '0'; -const char SAE_J1850_PWM_41_KBAUD = '1'; -const char SAE_J1850_PWM_10_KBAUD = '2'; -const char ISO_9141_5_BAUD_INIT = '3'; -const char ISO_14230_5_BAUD_INIT = '4'; -const char ISO_14230_FAST_INIT = '5'; -const char ISO_15765_11_BIT_500_KBAUD = '6'; -const char ISO_15765_29_BIT_500_KBAUD = '7'; -const char ISO_15765_11_BIT_250_KBAUD = '8'; -const char ISO_15765_29_BIT_250_KBAUD = '9'; -const char SAE_J1939_29_BIT_250_KBAUD = 'A'; -const char USER_1_CAN = 'B'; -const char USER_2_CAN = 'C'; - - - - -//-------------------------------------------------------------------------------------// -// PIDs (https://en.wikipedia.org/wiki/OBD-II_PIDs) -//-------------------------------------------------------------------------------------// -const uint8_t SUPPORTED_PIDS_1_20 = 0; // 0x00 - bit encoded -const uint8_t MONITOR_STATUS_SINCE_DTC_CLEARED = 1; // 0x01 - bit encoded -const uint8_t FREEZE_DTC = 2; // 0x02 - -const uint8_t FUEL_SYSTEM_STATUS = 3; // 0x03 - bit encoded -const uint8_t ENGINE_LOAD = 4; // 0x04 - % -const uint8_t ENGINE_COOLANT_TEMP = 5; // 0x05 - °C -const uint8_t SHORT_TERM_FUEL_TRIM_BANK_1 = 6; // 0x06 - % -const uint8_t LONG_TERM_FUEL_TRIM_BANK_1 = 7; // 0x07 - % -const uint8_t SHORT_TERM_FUEL_TRIM_BANK_2 = 8; // 0x08 - % -const uint8_t LONG_TERM_FUEL_TRIM_BANK_2 = 9; // 0x09 - % -const uint8_t FUEL_PRESSURE = 10; // 0x0A - kPa -const uint8_t INTAKE_MANIFOLD_ABS_PRESSURE = 11; // 0x0B - kPa -const uint8_t ENGINE_RPM = 12; // 0x0C - rpm -const uint8_t VEHICLE_SPEED = 13; // 0x0D - km/h -const uint8_t TIMING_ADVANCE = 14; // 0x0E - ° before TDC -const uint8_t INTAKE_AIR_TEMP = 15; // 0x0F - °C -const uint8_t MAF_FLOW_RATE = 16; // 0x10 - g/s -const uint8_t THROTTLE_POSITION = 17; // 0x11 - % -const uint8_t COMMANDED_SECONDARY_AIR_STATUS = 18; // 0x12 - bit encoded -const uint8_t OXYGEN_SENSORS_PRESENT_2_BANKS = 19; // 0x13 - bit encoded -const uint8_t OXYGEN_SENSOR_1_A = 20; // 0x14 - V % -const uint8_t OXYGEN_SENSOR_2_A = 21; // 0x15 - V % -const uint8_t OXYGEN_SENSOR_3_A = 22; // 0x16 - V % -const uint8_t OXYGEN_SENSOR_4_A = 23; // 0x17 - V % -const uint8_t OXYGEN_SENSOR_5_A = 24; // 0x18 - V % -const uint8_t OXYGEN_SENSOR_6_A = 25; // 0x19 - V % -const uint8_t OXYGEN_SENSOR_7_A = 26; // 0x1A - V % -const uint8_t OXYGEN_SENSOR_8_A = 27; // 0x1B - V % -const uint8_t OBD_STANDARDS = 28; // 0x1C - bit encoded -const uint8_t OXYGEN_SENSORS_PRESENT_4_BANKS = 29; // 0x1D - bit encoded -const uint8_t AUX_INPUT_STATUS = 30; // 0x1E - bit encoded -const uint8_t RUN_TIME_SINCE_ENGINE_START = 31; // 0x1F - sec - -const uint8_t SUPPORTED_PIDS_21_40 = 32; // 0x20 - bit encoded -const uint8_t DISTANCE_TRAVELED_WITH_MIL_ON = 33; // 0x21 - km -const uint8_t FUEL_RAIL_PRESSURE = 34; // 0x22 - kPa -const uint8_t FUEL_RAIL_GUAGE_PRESSURE = 35; // 0x23 - kPa -const uint8_t OXYGEN_SENSOR_1_B = 36; // 0x24 - ratio V -const uint8_t OXYGEN_SENSOR_2_B = 37; // 0x25 - ratio V -const uint8_t OXYGEN_SENSOR_3_B = 38; // 0x26 - ratio V -const uint8_t OXYGEN_SENSOR_4_B = 39; // 0x27 - ratio V -const uint8_t OXYGEN_SENSOR_5_B = 40; // 0x28 - ratio V -const uint8_t OXYGEN_SENSOR_6_B = 41; // 0x29 - ratio V -const uint8_t OXYGEN_SENSOR_7_B = 42; // 0x2A - ratio V -const uint8_t OXYGEN_SENSOR_8_B = 43; // 0x2B - ratio V -const uint8_t COMMANDED_EGR = 44; // 0x2C - % -const uint8_t EGR_ERROR = 45; // 0x2D - % -const uint8_t COMMANDED_EVAPORATIVE_PURGE = 46; // 0x2E - % -const uint8_t FUEL_TANK_LEVEL_INPUT = 47; // 0x2F - % -const uint8_t WARM_UPS_SINCE_CODES_CLEARED = 48; // 0x30 - count -const uint8_t DIST_TRAV_SINCE_CODES_CLEARED = 49; // 0x31 - km -const uint8_t EVAP_SYSTEM_VAPOR_PRESSURE = 50; // 0x32 - Pa -const uint8_t ABS_BAROMETRIC_PRESSURE = 51; // 0x33 - kPa -const uint8_t OXYGEN_SENSOR_1_C = 52; // 0x34 - ratio mA -const uint8_t OXYGEN_SENSOR_2_C = 53; // 0x35 - ratio mA -const uint8_t OXYGEN_SENSOR_3_C = 54; // 0x36 - ratio mA -const uint8_t OXYGEN_SENSOR_4_C = 55; // 0x37 - ratio mA -const uint8_t OXYGEN_SENSOR_5_C = 56; // 0x38 - ratio mA -const uint8_t OXYGEN_SENSOR_6_C = 57; // 0x39 - ratio mA -const uint8_t OXYGEN_SENSOR_7_C = 58; // 0x3A - ratio mA -const uint8_t OXYGEN_SENSOR_8_C = 59; // 0x3B - ratio mA -const uint8_t CATALYST_TEMP_BANK_1_SENSOR_1 = 60; // 0x3C - °C -const uint8_t CATALYST_TEMP_BANK_2_SENSOR_1 = 61; // 0x3D - °C -const uint8_t CATALYST_TEMP_BANK_1_SENSOR_2 = 62; // 0x3E - °C -const uint8_t CATALYST_TEMP_BANK_2_SENSOR_2 = 63; // 0x3F - °C - -const uint8_t SUPPORTED_PIDS_41_60 = 64; // 0x40 - bit encoded -const uint8_t MONITOR_STATUS_THIS_DRIVE_CYCLE = 65; // 0x41 - bit encoded -const uint8_t CONTROL_MODULE_VOLTAGE = 66; // 0x42 - V -const uint8_t ABS_LOAD_VALUE = 67; // 0x43 - % -const uint8_t FUEL_AIR_COMMANDED_EQUIV_RATIO = 68; // 0x44 - ratio -const uint8_t RELATIVE_THROTTLE_POSITION = 69; // 0x45 - % -const uint8_t AMBIENT_AIR_TEMP = 70; // 0x46 - °C -const uint8_t ABS_THROTTLE_POSITION_B = 71; // 0x47 - % -const uint8_t ABS_THROTTLE_POSITION_C = 72; // 0x48 - % -const uint8_t ABS_THROTTLE_POSITION_D = 73; // 0x49 - % -const uint8_t ABS_THROTTLE_POSITION_E = 74; // 0x4A - % -const uint8_t ABS_THROTTLE_POSITION_F = 75; // 0x4B - % -const uint8_t COMMANDED_THROTTLE_ACTUATOR = 76; // 0x4C - % -const uint8_t TIME_RUN_WITH_MIL_ON = 77; // 0x4D - min -const uint8_t TIME_SINCE_CODES_CLEARED = 78; // 0x4E - min -const uint8_t MAX_VALUES_EQUIV_V_I_PRESSURE = 79; // 0x4F - ratio V mA kPa -const uint8_t MAX_MAF_RATE = 80; // 0x50 - g/s -const uint8_t FUEL_TYPE = 81; // 0x51 - ref table -const uint8_t ETHANOL_FUEL_PERCENT = 82; // 0x52 - % -const uint8_t ABS_EVAP_SYS_VAPOR_PRESSURE = 83; // 0x53 - kPa -const uint8_t EVAP_SYS_VAPOR_PRESSURE = 84; // 0x54 - Pa -const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_1_3 = 85; // 0x55 - % -const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_1_3 = 86; // 0x56 - % -const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_2_4 = 87; // 0x57 - % -const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_2_4 = 88; // 0x58 - % -const uint8_t FUEL_RAIL_ABS_PRESSURE = 89; // 0x59 - kPa -const uint8_t RELATIVE_ACCELERATOR_PEDAL_POS = 90; // 0x5A - % -const uint8_t HYBRID_BATTERY_REMAINING_LIFE = 91; // 0x5B - % -const uint8_t ENGINE_OIL_TEMP = 92; // 0x5C - °C -const uint8_t FUEL_INJECTION_TIMING = 93; // 0x5D - ° -const uint8_t ENGINE_FUEL_RATE = 94; // 0x5E - L/h -const uint8_t EMISSION_REQUIREMENTS = 95; // 0x5F - bit encoded - -const uint8_t SUPPORTED_PIDS_61_80 = 96; // 0x60 - bit encoded -const uint8_t DEMANDED_ENGINE_PERCENT_TORQUE = 97; // 0x61 - % -const uint8_t ACTUAL_ENGINE_TORQUE = 98; // 0x62 - % -const uint8_t ENGINE_REFERENCE_TORQUE = 99; // 0x63 - Nm -const uint8_t ENGINE_PERCENT_TORQUE_DATA = 100; // 0x64 - % -const uint8_t AUX_INPUT_OUTPUT_SUPPORTED = 101; // 0x65 - bit encoded - -const uint8_t ODOMETER = 166; // 0xA6 - km * 10 - -const uint8_t SERVICE_01 = 1; -const uint8_t SERVICE_02 = 2; -const uint8_t SERVICE_03 = 3; - - -//-------------------------------------------------------------------------------------// -// AT commands (https://www.sparkfun.com/datasheets/Widgets/ELM327_AT_Commands.pdf) -//-------------------------------------------------------------------------------------// -const char * const DISP_DEVICE_DESCRIPT = "AT @1"; // General -const char * const DISP_DEVICE_ID = "AT @2"; // General -const char * const STORE_DEVICE_ID = "AT @3 %s"; // General -const char * const REPEAT_LAST_COMMAND = "AT \r"; // General -const char * const ALLOW_LONG_MESSAGES = "AT AL"; // General -const char * const AUTOMATIC_RECEIVE = "AT AR"; // OBD -const char * const ADAPTIVE_TIMING_OFF = "AT AT0"; // OBD -const char * const ADAPTIVE_TIMING_AUTO_1 = "AT AT1"; // OBD -const char * const ADAPTIVE_TIMING_AUTO_2 = "AT AT2"; // OBD -const char * const DUMP_BUFFER = "AT BD"; // OBD -const char * const BYPASS_INIT_SEQUENCE = "AT BI"; // OBD -const char * const TRY_BAUD_DIVISOR = "AT BRD %02d"; // General -const char * const SET_HANDSHAKE_TIMEOUT = "AT BRT %02d"; // General -const char * const CAN_AUTO_FORMAT_OFF = "AT CAF0"; // CAN -const char * const CAN_AUTO_FORMAT_ON = "AT CAF1"; // CAN -const char * const CAN_EXTENDED_ADDRESS_OFF = "AT CEA"; // CAN -const char * const USE_CAN_EXTENDED_ADDRESS = "AT CEA %02d"; // CAN -const char * const SET_ID_FILTER = "AT CF %s"; // CAN -const char * const CAN_FLOW_CONTROL_OFF = "AT CFC0"; // CAN -const char * const CAN_FLOW_CONTROL_ON = "AT CFC1"; // CAN -const char * const SET_ID_MASK = "AT CM %s"; // CAN -const char * const SET_CAN_PRIORITY = "AT CP %02d"; // CAN -const char * const SHOW_CAN_STATUS = "AT CS"; // CAN -const char * const CAN_SILENT_MODE_OFF = "AT CSM0"; // CAN -const char * const CAN_SILENT_MODE_ON = "AT CSM1"; // CAN -const char * const CALIBRATE_VOLTAGE_CUSTOM = "AT CV %04d"; // Volts -const char * const RESTORE_CV_TO_FACTORY = "AT CV 0000"; // Volts -const char * const SET_ALL_TO_DEFAULTS = "AT D"; // General -const char * const DISP_DLC_OFF = "AT D0"; // CAN -const char * const DISP_DLC_ON = "AT D1"; // CAN -const char * const MONITOR_FOR_DM1_MESSAGES = "AT DM1"; // J1939 -const char * const DISP_CURRENT_PROTOCOL = "AT DP"; // OBD -const char * const DISP_CURRENT_PROTOCOL_NUM = "AT DPN"; // OBD -const char * const ECHO_OFF = "AT E0"; // General -const char * const ECHO_ON = "AT E1"; // General -const char * const FLOW_CONTROL_SET_DATA_TO = "AT FC SD %s"; // CAN -const char * const FLOW_CONTROL_SET_HEAD_TO = "AT FC SH %s"; // CAN -const char * const FLOW_CONTROL_SET_MODE_TO = "AT FC SM %c"; // CAN -const char * const FORGE_EVENTS = "AT FE"; // General -const char * const PERFORM_FAST_INIT = "AT FI"; // ISO -const char * const HEADERS_OFF = "AT H0"; // OBD -const char * const HEADERS_ON = "AT H1"; // OBD -const char * const DISP_ID = "AT I"; // General -const char * const SET_ISO_BAUD_10400 = "AT IB 10"; // ISO -const char * const SET_ISO_BAUD_4800 = "AT IB 48"; // ISO -const char * const SET_ISO_BAUD_9600 = "AT IB 96"; // ISO -const char * const IFR_VAL_FROM_HEADER = "AT IFR H"; // J1850 -const char * const IFR_VAL_FROM_SOURCE = "AT IFR S"; // J1850 -const char * const IFRS_OFF = "AT IFR0"; // J1850 -const char * const IFRS_AUTO = "AT IFR1"; // J1850 -const char * const IFRS_ON = "AT IFR2"; // J1850 -const char * const IREAD_IGNMON_INPUT_LEVEL = "AT IGN"; // Other -const char * const SET_ISO_SLOW_INIT_ADDRESS = "AT IIA %02d"; // ISO -const char * const USE_J1939_ELM_DATA_FORMAT = "AT JE"; // J1850 -const char * const J1939_HEAD_FORMAT_OFF = "AT JHF0"; // J1850 -const char * const J1939_HEAD_FORMAT_ON = "AT JHF1"; // J1850 -const char * const USE_J1939_SAE_DATA_FORMAT = "AT JS"; // J1850 -const char * const SET_J1939_TIMER_X_TO_1X = "AT JTM1"; // J1850 -const char * const SET_J1939_TIMER_X_TO_5X = "AT JTM5"; // J1850 -const char * const DISP_KEY_WORDS = "AT KW"; // ISO -const char * const KEY_WORD_CHECKING_OFF = "AT KW0"; // ISO -const char * const KEY_WORD_CHECKING_ON = "AT KW1"; // ISO -const char * const LINEFEEDS_OFF = "AT L0"; // General -const char * const LINEFEEDS_ON = "AT L1"; // General -const char * const LOW_POWER_MODE = "AT LP"; // General -const char * const MEMORY_OFF = "AT M0"; // General -const char * const MEMORY_ON = "AT M1"; // General -const char * const MONITOR_ALL = "AT MA"; // OBD -const char * const MONITOR_FOR_PGN = "AT MP %s"; // J1939 -const char * const MONITOR_FOR_RECEIVER = "AT MR %02d"; // OBD -const char * const MONITOR_FOR_TRANSMITTER = "AT MT %02d"; // OBD -const char * const NORMAL_LENGTH_MESSAGES = "AT NL"; // OBD -const char * const SET_PROTO_OPTIONS_AND_BAUD = "AT PB %s"; // OBD -const char * const PROTOCOL_CLOSE = "AT PC"; // OBD -const char * const ALL_PROG_PARAMS_OFF = "AT PP FF OFF";// PPs -const char * const ALL_PROG_PARAMS_ON = "AT PP FF ON"; // PPs -const char * const SET_PROG_PARAM_OFF = "AT PP %s OFF";// PPs -const char * const SET_PROG_PARAM_ON = "AT PP %s ON"; // PPs -const char * const SET_PROG_PARAM_VAL = "AT PP %s SV %s"; // PPs -const char * const DISP_PP_SUMMARY = "AT PPS"; // PPs -const char * const RESPONSES_OFF = "AT R0"; // OBD -const char * const RESPONSES_ON = "AT R1"; // OBD -const char * const SET_RECEIVE_ADDRESS_TO = "AT RA %02d"; // OBD -const char * const READ_STORED_DATA = "AT RD"; // General -const char * const SEND_RTR_MESSAGE = "AT RTR"; // CAN -const char * const READ_VOLTAGE = "AT RV"; // Volts -const char * const PRINTING_SPACES_OFF = "AT S0"; // OBD -const char * const PRINTING_SPACES_ON = "AT S1"; // OBD -const char * const STORE_DATA_BYTE = "AT SD "; // General -const char * const SET_HEADER = "AT SH %s"; // OBD -const char * const PERFORM_SLOW_INIT = "AT SI"; // ISO -const char * const SET_PROTOCOL_TO_AUTO_H_SAVE = "AT SP A%c"; // OBD -const char * const SET_PROTOCOL_TO_H_SAVE = "AT SP %c"; // OBD -const char * const SET_PROTOCOL_TO_AUTO_SAVE = "AT SP 00"; // OBD -const char * const SET_REC_ADDRESS = "AT SR %02d"; // OBD -const char * const SET_STANDARD_SEARCH_ORDER = "AT SS"; // OBD -const char * const SET_TIMEOUT_TO_H_X_4MS = "AT ST %02d"; // OBD -const char * const SET_WAKEUP_TO_H_X_20MS = "AT SW %02d"; // ISO -const char * const SET_TESTER_ADDRESS_TO = "AT TA %02d"; // OBD -const char * const TRY_PROT_H_AUTO_SEARCH = "AT TP A%c"; // OBD -const char * const TRY_PROT_H = "AT TP %c"; // OBD -const char * const VARIABLE_DLC_OFF = "AT V0"; // CAN -const char * const VARIABLE_DLC_ON = "AT V1"; // CAN -const char * const SET_WAKEUP_MESSAGE = "AT WM"; // ISO -const char * const WARM_START = "AT WS"; // General -const char * const RESET_ALL = "AT Z"; // General - - -const uint8_t responseBytes[0xA9] = -{ - 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, - 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 4, 4, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, - 4, 1, 1, 2, 5, 2, 5, 3, 3, 7, 5, 5, 5, 11, 9, 3, 10, 6, 5, 5, 5, 7, 7, 5, 9, 9, 7, 7, 9, 1, 1, 13, - 4, 41, 41, 9, 1, 10, 5, 5, 13, 41, 41, 7, 17, 1, 1, 7, 3, 5, 2, 3, 12, 9, 9, 6, 4, 17, 4, 2, 9 -}; - -#endif //ELMulator_DEFINITIONS_H diff --git a/10-OBD-Display-2024/elmulator/keywords.txt b/10-OBD-Display-2024/elmulator/lib/ELMulator/keywords.txt similarity index 100% rename from 10-OBD-Display-2024/elmulator/keywords.txt rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/keywords.txt diff --git a/10-OBD-Display-2024/elmulator/library.properties b/10-OBD-Display-2024/elmulator/lib/ELMulator/library.properties similarity index 100% rename from 10-OBD-Display-2024/elmulator/library.properties rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/library.properties diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ATCommands.cpp b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/ATCommands.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ATCommands.cpp rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/ATCommands.cpp diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ATCommands.h b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/ATCommands.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ATCommands.h rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/ATCommands.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ELMulator.cpp b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/ELMulator.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ELMulator.cpp rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/ELMulator.cpp diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ELMulator.h b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/ELMulator.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ELMulator.h rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/ELMulator.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDSerialComm.cpp b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDSerialComm.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDSerialComm.cpp rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDSerialComm.cpp diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDSerialComm.h b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDSerialComm.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDSerialComm.h rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDSerialComm.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDWiFiComm.cpp b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDWiFiComm.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDWiFiComm.cpp rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDWiFiComm.cpp diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDWiFiComm.h b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDWiFiComm.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/OBDWiFiComm.h rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/OBDWiFiComm.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/PidProcessor.cpp b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/PidProcessor.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/PidProcessor.cpp rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/PidProcessor.cpp diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/PidProcessor.h b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/PidProcessor.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/PidProcessor.h rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/PidProcessor.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/definitions.h b/10-OBD-Display-2024/elmulator/lib/ELMulator/src/definitions.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/definitions.h rename to 10-OBD-Display-2024/elmulator/lib/ELMulator/src/definitions.h diff --git a/10-OBD-Display-2024/elmulator/platformio.ini b/10-OBD-Display-2024/elmulator/platformio.ini new file mode 100644 index 0000000..7bbdee9 --- /dev/null +++ b/10-OBD-Display-2024/elmulator/platformio.ini @@ -0,0 +1,27 @@ +; ELMulator — fake ELM327 OBD-II adapter for testing without a car. +; Runs on a CLASSIC ESP32 (Bluetooth Classic SPP). Library lives in lib/ELMulator. +; One env per example: pio run -e simple | custom | wifi + +[platformio] +default_envs = simple + +[env] +platform = espressif32@6.10.0 +board = esp32dev +framework = arduino +board_build.partitions = huge_app.csv +; upload_port = COMxx ; the classic ESP32's port (COM21 is the JC3636W518) +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder + +; all Mode 01 PIDs answered with mock data, BT name "ELMULATOR" +[env:simple] +build_src_filter = + + +; custom PID handler + DTC response, BT name "ELMULATOR" +[env:custom] +build_src_filter = + + +; custom handler, BT name "OBDII" (matches what elm327_wifi_bridge connects to) +[env:wifi] +build_src_filter = + diff --git a/10-OBD-Display-2024/elmulator/src/ATCommands.cpp b/10-OBD-Display-2024/elmulator/src/ATCommands.cpp deleted file mode 100644 index 8c8f304..0000000 --- a/10-OBD-Display-2024/elmulator/src/ATCommands.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "ATCommands.h" -#include "definitions.h" - -#if USE_WIFI -ATCommands::ATCommands(OBDWiFiComm *connection) { - this->connection = connection; -} -#else -ATCommands::ATCommands(OBDSerialComm *connection) { - this->connection = connection; -} -#endif - -ATCommands::~ATCommands() { - operator delete(this->connection); -} - - -bool ATCommands::process(const String& command) { - bool processed = false; - if (isATCommand(command)) { - processed = true; - processCommand(command); - DEBUG("RX AT: " + command); - } - return processed; -} - -void ATCommands::processCommand(const String& command) { - - // if space is enabled (ex: AT H[charPosition]) - uint8_t offset = 2; - if (command.charAt(2) == 0x20) { - offset = 3; - } - - // refer to ELM327 specs - String specificCommand = command.substring(offset, command.length()); - if (specificCommand.startsWith("D",offset)) { - ATCommands::ATD(); - } else if (specificCommand.startsWith("Z")) { - ATCommands::ATZ(); - } else if (specificCommand.startsWith("I")) { - ATCommands::ATI(); - } else if (specificCommand.startsWith("E")) { - ATCommands::ATEx(specificCommand); - } else if (specificCommand.startsWith("L")) { - ATCommands::ATLx(specificCommand); - } else if (specificCommand.startsWith("M")) { - ATCommands::ATMx(specificCommand); - } else if (specificCommand.startsWith("S")) { - if (specificCommand.startsWith("SP")) { - ATCommands::ATSPx(specificCommand); - } else { - ATCommands::ATSx(specificCommand); - } - } else if (specificCommand.startsWith("H")) { - ATCommands::ATHx(specificCommand); - } else if (specificCommand.startsWith("AT")) { - ATCommands::ATATx(specificCommand); - } else if (specificCommand.startsWith("DPN")) { - ATCommands::ATDPN(); - } else if (specificCommand.startsWith("DESC") || specificCommand.startsWith("@1")) { - ATCommands::ATDESC(); - } else if (specificCommand.startsWith("PC")) { - ATCommands::ATPC(); - } else if (specificCommand.startsWith("RV")){ - ATCommands::ATRV(); - } else { - - // lets assume we process any at command - connection->writeEndOK(); - } -} - -// set all to defaults -void ATCommands::ATD() { - connection->setToDefaults(); - connection->writeEndOK(); -} - -// reset all -void ATCommands::ATZ() { - connection->setToDefaults(); - connection->writeTo(ID); - connection->writeEndOK(); -} - -// Print the version ID -void ATCommands::ATI() { - connection->writeTo(ID); - connection->writeEndOK(); -} - -// send description -void ATCommands::ATDESC() { - connection->writeTo(DESC); - connection->writeEndOK(); -} - -// set echoEnable 0=off 1=on -void ATCommands::ATEx(String& cmd) { - connection->setEcho(cmd.equals("E0") ? false : true); - connection->writeEndOK(); -} - -// set memory off=0 on=1 -void ATCommands::ATMx(String& cmd) { - connection->setMemory(cmd.equals("M0") ? false : true); - connection->writeEndOK(); -} - -// line feeds off=0 on=1 -void ATCommands::ATLx(String& cmd) { - connection->setLineFeeds(cmd.equals("L0") ? false : true); - connection->writeEndOK(); -} - -// ATSx printing spaces off=0 on=1 -void ATCommands::ATSx(String& cmd) { - connection->setWhiteSpaces(cmd.equals("S0") ? false : true); - connection->writeEndOK(); -} - -// Headers off=0 on=1 -void ATCommands::ATHx(String& cmd) { - connection->setHeaders(cmd.equals("H0") ? false : true); - connection->writeEndOK(); -} - -// ATSPx Define protocol 0=auto -void ATCommands::ATSPx(String& cmd) { - connection->writeEndOK(); -} - -// set protocol -void ATCommands::ATDPN() { - connection->writeTo(PROTOCOL); - connection->writeEndOK(); -} - -// AT AT2 adaptative time control -void ATCommands::ATATx(String& cmd) { - connection->writeEndOK(); -} - -// Terminates current diagnostic session. Protocol close -void ATCommands::ATPC() { - connection->writeEndOK(); -} - -void ATCommands::ATRV() { - connection->writeTo("AT RV\r13.5V"); - connection->writeEnd(); -} - -// return true ir connectionand is AT -bool ATCommands::isATCommand(const String& command) { - toUpperCase(command.charAt(0)); - return command.startsWith("AT") ? true : false; -} - diff --git a/10-OBD-Display-2024/elmulator/src/ATCommands.h b/10-OBD-Display-2024/elmulator/src/ATCommands.h deleted file mode 100644 index 00e729b..0000000 --- a/10-OBD-Display-2024/elmulator/src/ATCommands.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef ELMulator_ATCommands_h -#define ELMulator_ATCommands_h - -#include -#include "definitions.h" -#if USE_WIFI -#include "OBDWiFiComm.h" -#else -#include "OBDSerialComm.h" -#endif - -class ATCommands -{ - -public: -#if USE_WIFI - ATCommands(OBDWiFiComm *connection); -#else - ATCommands(OBDSerialComm *connection); -#endif - ~ATCommands(); - - bool process(const String &string); - -private: - // Variables -#if USE_WIFI - OBDWiFiComm *connection; -#else - OBDSerialComm *connection; -#endif - void ATD(); - - void ATZ(); - - void ATI(); - - void ATEx(String &x); - - void ATMx(String &x); - - void ATLx(String &x); - - void ATSx(String &x); - - void ATHx(String &x); - - void ATSPx(String &x); - - void ATATx(String &cmd); - - void ATPC(); - - void ATDPN(); - - void ATDESC(); - - void ATRV(); - - void processCommand(const String &command); - - bool isATCommand(const String &command); -}; - -#endif diff --git a/10-OBD-Display-2024/elmulator/src/ELMulator.cpp b/10-OBD-Display-2024/elmulator/src/ELMulator.cpp deleted file mode 100644 index 58ec398..0000000 --- a/10-OBD-Display-2024/elmulator/src/ELMulator.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "ELMulator.h" - -#if USE_WIFI -ELMulator::ELMulator() -{ - _connection = new OBDWiFiComm(); - _atProcessor = new ATCommands(_connection); - _pidProcessor = new PidProcessor(_connection); - _lastCommand = ""; - elmRequest.reserve(MAX_REQUEST_SIZE); - elmRequest = ""; -} -#else -ELMulator::ELMulator() -{ - _connection = new OBDSerialComm(); - _atProcessor = new ATCommands(_connection); - _pidProcessor = new PidProcessor(_connection); - _lastCommand = ""; - elmRequest.reserve(MAX_REQUEST_SIZE); - elmRequest = ""; -} -#endif - - - -ELMulator::~ELMulator() {} - -void ELMulator::init(const String &deviceName, bool registerPids) -{ - _connection->init(deviceName); - if (registerPids) - { - registerAllMode01Pids(); - } -} - -void ELMulator::registerAllMode01Pids() -{ - // Set up PIDs 0x00 to 0x65 - // Will be provided a response with mock data value if no special handling is performed. - // Requests for PID > 0x65 are not currently supported - will return "NO DATA" - for (int i = 0; i < 0x66; i++) - { - _pidProcessor->registerMode01Pid(i); - } -} - -bool ELMulator::readELMRequest() -{ - do - { - elmRequest.clear(); // clear buffer from previous requests - _connection->readData(elmRequest); - elmRequest.toUpperCase(); - // TODO ignore spaces, and all control chars (tab, etc) - // TODO accept single carriage return as repeat last command at or pid - // ignore null i.e 00 - } while (processRequest(elmRequest)); // processRequest handles all non PID requests (AT commands, errors etc) - return true; // We have received a valid PID request we need to respond to -} - -void ELMulator::sendELMResponse() -{ - // Respond to any mode 01 request with a mock sensor value - if (isMode01(elmRequest)) - { - uint8_t pidCode = getPidCode(elmRequest); - writePidResponse(elmRequest, responseBytes[pidCode], getMockSensorValue()); - return; - } - // Not a mode 01 PID request. Report it as not supported (ie, "NO DATA"); - else - { - writePidNotSupported(); - } -} - -void ELMulator::begin() -{ - while (readELMRequest()) - { - sendELMResponse(); - } -} - -uint8_t ELMulator::getPidCode(const String &request) -{ - return _pidProcessor->getPidCodeFromRequest(request); -} - -bool ELMulator::registerMode01Pid(uint32_t pid) -{ - return _pidProcessor->registerMode01Pid(pid); -} - -bool ELMulator::registerMode01MILResponse(const String &response) -{ - return _pidProcessor->registerMode01MILResponse(response); -} - -bool ELMulator::registerMode03Response(const String &response) -{ - return _pidProcessor->registerMode03Response(response); -} - -void ELMulator::writePidNotSupported() -{ - _connection->writeEndNoData(); -} - -void ELMulator::writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value) -{ - _pidProcessor->writePidResponse(requestPid, numberOfBytes, value); -} - -void ELMulator::writeResponse(const String &response) -{ - _connection->writeTo(response.c_str()); - _connection->writeEnd(); -} - -bool ELMulator::processRequest(String &command) -{ - - // TODO: check for no 0X0D char in command, return ? and > - // TODO: receive only , repeat last command - - // carriage return, means repeat last command - if (command == "\n") - { - command = _lastCommand; - } - - // empty command, do not send to user - if (command.length() == 0) - { - return true; - } - - // Check for AT command - if (_atProcessor->process(command)) - { - _lastCommand = command; - return true; - } - - // Check for a valid hex string, return error if false - if (!isValidHex(command.c_str())) - { - _connection->writeEndUnknown(); - DEBUG("Invalid HEX command: " + command); - return true; - } - - // Check for a valid PID request - if (_pidProcessor->process(command)) - { - _lastCommand = command; - return true; - } - - return false; -} - -bool ELMulator::isValidHex(const char *pid) -{ - return (pid[strspn(pid, "0123456789abcdefABCDEF")] == 0); -} - -bool ELMulator::isMode01(const String &command) -{ - return _pidProcessor->isMode01(command); -} - -bool ELMulator::isMode22(const String &command) -{ - return _pidProcessor->isMode22(command); -} - -bool ELMulator::isMode03(const String &command) -{ - return _pidProcessor->isMode03(command); -} - -bool ELMulator::isMode01MIL(const String &command) -{ - return _pidProcessor->isMode01MIL(command); -} - -/** - * Fake some data - * start counter = 0 - * every call to getFakeSensorData, will increment the counter to a max of 255 (0xff) - * When 0xff is reached the cycle is reverted - * and the counter will decrement by one until 0 is reached - */ -uint32_t ELMulator::getMockSensorValue() -{ - if (isCycleUp) - { - cycle++; - if (cycle == 0xff) - { - isCycleUp = false; - } - } - else - { - cycle--; - if (cycle == 0) - { - isCycleUp = true; - } - } - - return cycle; -} \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/src/ELMulator.h b/10-OBD-Display-2024/elmulator/src/ELMulator.h deleted file mode 100644 index 86cc077..0000000 --- a/10-OBD-Display-2024/elmulator/src/ELMulator.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef ELMulator_ELMulator_h -#define ELMulator_ELMulator_h - -#include -#include "definitions.h" - -#if USE_WIFI -#include "OBDWiFiComm.h" -#else -#include "OBDSerialComm.h" -#endif - -#include "ATCommands.h" -#include "PidProcessor.h" -#include "definitions.h" - -class ELMulator -{ - -public: - /** - * When creating a new instance of ELMulator with an attached - * BT module, we need to set the Bluetooth serial parameters - * - * @param baudRate - rate for bluetooth serial port (normally 9600) - * @param rxPin - the Arduino RX pin for the Bluetooth module (serial port) - * @param txPin - the Arduino TX pin for the Bluetooth module (serial port) - * @return - */ - ELMulator(uint32_t baudRate, uint8_t rxPin, uint8_t txPin); - - ELMulator(); - - ~ELMulator(); - - void init(const String &deviceName, const bool registerPids = false); - - /** - * Waits and Reads a request from OBD client software (example: torque) - * - * It will only return if the OBD client software - * request's one of the previous registred PID (see: registerMode01Pid()) - * - * Any other request will be automaticly handle or it will be rejected. - * - * ELMulator lib will automaticly handle: - * - any AT command - * - PID's support request like 0100, 0120, 0140, 0160, ... - * - * @return the request PID (Vehicle speed ex: 010D ) - */ - bool readELMRequest(); - void sendELMResponse(); - void begin(); - - /** - * Registry the PID's (sensors) your arduino will support. - * Currently ELMulator lib only supports MODE 01 PID's - * - * In OBDII MODE 01 PID's, are request - * to Show current data for a given sensor identified by a PID - * - * List of MODE 01 PID's: https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_01 - * - * Example, for Vehicle speed, where OBDII PID code is 0D: - * - * registerMode01Pid(0x0D) - * - * @param pidHexId - * @return returns true if the entered ID is in the valide range [0x00, 0xFF] - */ - bool registerMode01Pid(uint32_t pidHexId); - - bool registerMode01MILResponse(const String &response); - - bool registerMode03Response(const String &response); - - uint8_t getPidCodeOnly(uint16_t hexCommand); - - /** - * Used to informe the OBD client that the PID, - * it has requested is not supported - * - * In normal conditions, you will only receive, - * request for the PID you have registred - * All other request is automaticly handle by GTTuboEcu lib - */ - void writePidNotSupported(); - - /** - * Respond to a given PID request from OBDII client (ex: torque) - * - * @param requestPid - the received pid - * @param numberOfBytes - number of bytes this PID response VALUE is supposed to have - * @param value - sensor value for this PID, - * lib will convert it to HEX - * with the appropriated number of HEX chars (numberOfChars) - */ - void writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value); - - // Write the response back to the requestor without PID formatting, etc - // Just pass the response string on. Useful for testing with a specific response - // that has been pre-configured. - void writeResponse(const String &response); - - bool isMode01(const String &command); - bool isMode03(const String &command); - bool isMode01MIL(const String &command); - bool isMode22(const String &command); - - uint8_t getPidCode(const String &request); - void registerAllMode01Pids(); - uint32_t getMockSensorValue(); - - String elmRequest; - -private: -#if USE_WIFI - OBDWiFiComm *_connection; -#else - OBDSerialComm *_connection; -#endif - ATCommands *_atProcessor; - - PidProcessor *_pidProcessor; - - String _lastCommand; - - bool isCycleUp = true; - - uint32_t cycle = 0; - - bool processRequest(String &command); - - bool isValidHex(const char *pid); -}; - -#endif diff --git a/10-OBD-Display-2024/elmulator/src/OBDSerialComm.cpp b/10-OBD-Display-2024/elmulator/src/OBDSerialComm.cpp deleted file mode 100644 index d0509af..0000000 --- a/10-OBD-Display-2024/elmulator/src/OBDSerialComm.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "OBDSerialComm.h" -#include "definitions.h" - - -OBDSerialComm::OBDSerialComm() { - -} - -OBDSerialComm::~OBDSerialComm() { - operator delete(serial); -} - -void OBDSerialComm::init(const String& deviceName) { - Serial.println("Starting BT . . ."); - serial = new BluetoothSerial(); - //delay(2000); - serial->begin(deviceName, false); - setToDefaults(); - -} - -void OBDSerialComm::writeEnd() { - - // 1 - write carriage return - writeTo("\r"); - - // 2- (optional ) write linefeed - if (lineFeedEnable) { - writeTo("\n"); - } - - // 3 - Write prompt - writeTo(">"); - - serial->flush(); -}; - - -void OBDSerialComm::writeEndOK() { - writeTo("OK"); - writeEnd(); -} - -void OBDSerialComm::writeEndERROR() { - writeTo("ERROR"); - writeEnd(); -} - -void OBDSerialComm::writeEndNoData() { - writeTo("NO DATA"); - writeEnd(); -} - -void OBDSerialComm::writeEndUnknown() { - writeTo("?"); - writeEnd(); -} - -void OBDSerialComm::setToDefaults() { - setEcho(true); - setStatus(READY); - setWhiteSpaces(true); - setHeaders(false); - setLineFeeds(true); - setMemory(false); -} - -void OBDSerialComm::writeTo(char const *response) { - serial->print(response); -} - - -void OBDSerialComm::writeTo(uint8_t cChar) { - serial->print(cChar); -} - -void OBDSerialComm::writeEndPidTo(char const *response) { - if (whiteSpacesEnabled) { - uint8_t len = strlen(response); - char spacedResponse[len + len / 2 + 1]; - addSpacesToResponse(response, spacedResponse); - writeTo(spacedResponse); - } else { - writeTo(response); - } - writeEnd(); -} - -void OBDSerialComm::readData(String& rxData) { - serial->flush(); // temp remove this - rxData = serial->readStringUntil(SERIAL_END_CHAR); - if (isEchoEnable()) { - writeTo(rxData.c_str()); - } - //return rxData; -} - -void OBDSerialComm::setBaudRate(uint32_t rate) { - this->baudRate = rate; -} - -long OBDSerialComm::getBaudRate() { - return this->baudRate; -} - -bool OBDSerialComm::isEchoEnable() { - return this->echoEnable; -} - -void OBDSerialComm::setEcho(bool echo) { - this->echoEnable = echo; -} - -void OBDSerialComm::setStatus(STATUS status) { - this->status = status; -} - -void OBDSerialComm::setLineFeeds(bool status) { - this->lineFeedEnable = status; -} - -void OBDSerialComm::setMemory(bool status) { - this->memoryEnabled = status; -} - -void OBDSerialComm::setWhiteSpaces(bool status) { - this->whiteSpacesEnabled = status; -} - -void OBDSerialComm::setHeaders(bool status) { - this->headersEnabled = status; -} - -void OBDSerialComm::addSpacesToResponse(const char *response, char spacedRes[]) { - uint8_t len = strlen(response); - int j = 0; - for (int i = 0; i < len;) { - *(spacedRes + j++) = *(response + i++); - *(spacedRes + j++) = *(response + i++); - if (i < len) { - *(spacedRes + j++) = 0x20; - } - } - *(spacedRes + j) = '\0'; -} diff --git a/10-OBD-Display-2024/elmulator/src/OBDSerialComm.h b/10-OBD-Display-2024/elmulator/src/OBDSerialComm.h deleted file mode 100644 index 2059b28..0000000 --- a/10-OBD-Display-2024/elmulator/src/OBDSerialComm.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef ELMulator_OBDSerialComm_h -#define ELMulator_OBDSerialComm_h - -#include -#include "definitions.h" - -#include - - -class OBDSerialComm -{ -public: - enum STATUS - { - IDLE = 0, - READY = 1 - }; - -// // Bluetooth is not built in, we are using a BT module via GPIO -// OBDSerialComm(uint32_t baudRate, uint8_t rxPin, uint8_t txPin); - - OBDSerialComm(); - - ~OBDSerialComm(); - - void init(const String &deviceName); - - void writeEndOK(); - - void writeEndERROR(); - - /** - * Response for unsupported PID command or missing sensor, respond "NO DATA". - */ - void writeEndNoData(); - - /** - * Response for invalid AT command, or invalid PID or other bad input, respond "?" - */ - void writeEndUnknown(); - - void setToDefaults(); - - void readData(String &rxData); - - void writeTo(uint8_t cChar); - - void writeTo(char const *string); - - void setEcho(bool echo); - - void writeEnd(); - - bool isEchoEnable(); - - void setLineFeeds(bool status); - - void setMemory(bool status); - - void setWhiteSpaces(bool status); - - void setHeaders(bool status); - - void setStatus(STATUS status); - - void writeEndPidTo(char const *string); - -private: - uint32_t baudRate; // Serial Baud Rate - STATUS status; // Operation status - bool echoEnable; // echoEnable command after received - bool lineFeedEnable; - bool memoryEnabled; - bool whiteSpacesEnabled; - bool headersEnabled; - - void setBaudRate(uint32_t rate); - - long getBaudRate(); - - void addSpacesToResponse(const char *response, char string[]); - -#ifndef BLUETOOTH_BUILTIN - HardwareSerial *serial; // lib to communicate with bluetooth -#else - BluetoothSerial *serial; -#endif -}; - -#endif \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/src/OBDWiFiComm.cpp b/10-OBD-Display-2024/elmulator/src/OBDWiFiComm.cpp deleted file mode 100644 index 484b4f0..0000000 --- a/10-OBD-Display-2024/elmulator/src/OBDWiFiComm.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include "OBDWiFiComm.h" -#include "definitions.h" - -WiFiServer server(35000); -IPAddress localIP = IPAddress(192, 168, 0, 10); -IPAddress gateway = IPAddress(192, 168, 0, 10); -IPAddress subnet = IPAddress(255,255,255,0); - -OBDWiFiComm::OBDWiFiComm() { - -} - -OBDWiFiComm::~OBDWiFiComm() { -} - -void OBDWiFiComm::init(const String& deviceName) { - Serial.println("Starting AP . . ."); - - WiFi.softAPConfig(localIP, gateway, subnet); - WiFi.softAP(deviceName); - - IPAddress myIP = WiFi.softAPIP(); - Serial.print("AP IP address: "); - Serial.println(myIP); - Serial.print("AP SSID: "); - Serial.println(deviceName); - server.begin(); - setToDefaults(); -} - -void OBDWiFiComm::writeEnd() { - - // 1 - write carriage return - writeTo("\r"); - - // 2- (optional ) write linefeed - if (lineFeedEnable) { - writeTo("\n"); - } - - // 3 - Write prompt - writeTo(">"); -}; - - -void OBDWiFiComm::writeEndOK() { - writeTo("OK"); - writeEnd(); -} - -void OBDWiFiComm::writeEndERROR() { - writeTo("ERROR"); - writeEnd(); -} - -void OBDWiFiComm::writeEndNoData() { - writeTo("NO DATA"); - writeEnd(); -} - -void OBDWiFiComm::writeEndUnknown() { - writeTo("?"); - writeEnd(); -} - -void OBDWiFiComm::setToDefaults() { - setEcho(true); - setStatus(READY); - setWhiteSpaces(true); - setHeaders(false); - setLineFeeds(true); - setMemory(false); -} - -void OBDWiFiComm::writeTo(char const *response) { - client.print(response); -} - - -void OBDWiFiComm::writeTo(uint8_t cChar) { - client.print(cChar); -} - -void OBDWiFiComm::writeEndPidTo(char const *response) { - if (this->whiteSpacesEnabled) { - uint8_t len = strlen(response); - char spacedResponse[len + len / 2 + 1]; - addSpacesToResponse(response, spacedResponse); - writeTo(spacedResponse); - } else { - writeTo(response); - } - writeEnd(); -} - -void OBDWiFiComm::readData(String& rxData) { - if (!client.connected()) { - client = server.available(); - } - - if(client) - { - rxData - = client.readStringUntil(SERIAL_END_CHAR); - if (isEchoEnable()) - { - writeTo(rxData.c_str()); - } - } -} - -bool OBDWiFiComm::isEchoEnable() { - return this->echoEnable; -} - -void OBDWiFiComm::setEcho(bool echo) { - this->echoEnable = echo; -} - -void OBDWiFiComm::setStatus(STATUS status) { - this->status = status; -} - -void OBDWiFiComm::setLineFeeds(bool status) { - this->lineFeedEnable = status; -} - -void OBDWiFiComm::setMemory(bool status) { - this->memoryEnabled = status; -} - -void OBDWiFiComm::setWhiteSpaces(bool status) { - this->whiteSpacesEnabled = status; -} - -void OBDWiFiComm::setHeaders(bool status) { - this->headersEnabled = status; -} - -void OBDWiFiComm::addSpacesToResponse(const char *response, char spacedRes[]) { - uint8_t len = strlen(response); - int j = 0; - for (int i = 0; i < len;) { - *(spacedRes + j++) = *(response + i++); - *(spacedRes + j++) = *(response + i++); - if (i < len) { - *(spacedRes + j++) = 0x20; - } - } - *(spacedRes + j) = '\0'; -} diff --git a/10-OBD-Display-2024/elmulator/src/OBDWiFiComm.h b/10-OBD-Display-2024/elmulator/src/OBDWiFiComm.h deleted file mode 100644 index eb49098..0000000 --- a/10-OBD-Display-2024/elmulator/src/OBDWiFiComm.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef ELMulator_OBDWiFiComm_h -#define ELMulator_OBDWiFiComm_h - -#include -#include -#include -#include "definitions.h" - - -class OBDWiFiComm -{ -public: - enum STATUS - { - IDLE = 0, - READY = 1 - }; - - OBDWiFiComm(); - - ~OBDWiFiComm(); - - void init(const String &deviceName); - - void writeEndOK(); - - void writeEndERROR(); - - /** - * Response for unsupported PID command or missing sensor, respond "NO DATA". - */ - void writeEndNoData(); - - /** - * Response for invalid AT command, or invalid PID or other bad input, respond "?" - */ - void writeEndUnknown(); - - void setToDefaults(); - - void readData(String &rxData); - - void writeTo(uint8_t cChar); - - void writeTo(char const *string); - - void setEcho(bool echo); - - void writeEnd(); - - bool isEchoEnable(); - - void setLineFeeds(bool status); - - void setMemory(bool status); - - void setWhiteSpaces(bool status); - - void setHeaders(bool status); - - void setStatus(STATUS status); - - void writeEndPidTo(char const *string); - -private: - STATUS status; // Operation status - bool echoEnable; // echoEnable command after received - bool lineFeedEnable; - bool memoryEnabled; - bool whiteSpacesEnabled; - bool headersEnabled; - - void addSpacesToResponse(const char *response, char string[]); - - WiFiClient client; -}; - -#endif \ No newline at end of file diff --git a/10-OBD-Display-2024/elmulator/src/PidProcessor.cpp b/10-OBD-Display-2024/elmulator/src/PidProcessor.cpp deleted file mode 100644 index 9184f80..0000000 --- a/10-OBD-Display-2024/elmulator/src/PidProcessor.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "PidProcessor.h" - -#if USE_WIFI -PidProcessor::PidProcessor(OBDWiFiComm *connection) { - _connection = connection; - resetPidMode01Array(); -}; -#else -PidProcessor::PidProcessor(OBDSerialComm *connection) { - _connection = connection; - resetPidMode01Array(); -}; -#endif - - -bool PidProcessor::process(String& command) { - bool processed = false; - - if (command.length() > 4) - { - command = command.substring(0, 4); // remove num_responses value if present; lib only handles single responses - } - - if (!isMode01(command) & !isMode22(command)) - { - _connection->writeEndNoData(); - return false; - } - - uint16_t hexCommand = strtoul(command.c_str(), NULL, HEX); - uint8_t pid = getPidCodeFromHex(hexCommand); - if (isSupportedPidRequest(pid)) { //reqeust to return a list of valid PIDs we can respond to - processed = true; - uint32_t supportedPids = getSupportedPids(pid); - writePidResponse(command, 4, supportedPids); - } - return processed; -} - -void PidProcessor::writePidResponse(const String& requestPid, uint8_t numberOfBytes, uint32_t value) { - uint8_t nHexChars = PID_N_BYTES * N_CHARS_IN_BYTE + numberOfBytes * N_CHARS_IN_BYTE ; - char responseArray[nHexChars + 1]; // one more for termination char - getFormattedResponse(responseArray, nHexChars, requestPid, value); - _connection->writeEndPidTo(responseArray); -} - -/** - * adds a supported pid, so it can answer to pid support request, ex 0100, 0120, ... - */ -bool PidProcessor::registerMode01Pid(uint32_t pid) { - // pid must be off type 01 - if (pid > 0x00 && pid < 0x0200) { - // remove PidMode, only use pid code - pid = getPidCodeFromHex(pid); - setPidBit(pid); - - char buffer[4]; - sprintf(buffer, "%02X", pid); - DEBUG("Registered PID: " + String(buffer )); - return true; - } - return false; -} - -bool PidProcessor::isMode01(const String& command) -{ - return command.startsWith("01") ? true : false; -} - -bool PidProcessor::isMode01MIL(const String& command) -{ - return command.startsWith("0101") ? true : false; -} - -bool PidProcessor::isMode03(const String& command) -{ - return command.startsWith("03") ? true : false; -} - -bool PidProcessor::isMode22(const String& command) -{ - return command.startsWith("22") ? true : false; -} - - -/** - * return true if: - * - 1000 - * - 1020 - * - 1040 - * - 1060 - * .... - */ -bool PidProcessor::isSupportedPidRequest(uint8_t pid) { - return pid == getPidIntervalId(pid); -} - -/** - * returns the interval RANGEID for the given pid (ex: 00, 20, 40, ...) - */ -uint8_t PidProcessor::getPidIntervalId(uint8_t pidcode) { - return getPidIntervalIndex(pidcode) * PID_INTERVAL_OFFSET; -} - -/** - * returns the interval INDEX for the given pid (0,1,2,3,4,...) - */ -uint8_t PidProcessor::getPidIntervalIndex(uint8_t pidcode) { - return pidcode / PID_INTERVAL_OFFSET; -} - -/** - * Receives a mode pid ex 010C , - * returns only the pid ex 0C - */ -uint8_t PidProcessor::getPidCodeFromHex(uint16_t hexCommand) { - - if (hexCommand >= 0x0100) { - hexCommand -= 0x100; - } - return (uint8_t) hexCommand; // return only the lower 8 bits (trim off num_messages or other extra bytes if present) -} - -/** - * Receives a complete PID request, - * returns only the pid ex 0C - */ -uint8_t PidProcessor::getPidCodeFromRequest(const String& request) { - uint16_t hexCommand = strtoul(request.c_str(), NULL, HEX); - return getPidCodeFromHex(hexCommand); -} - - -void PidProcessor::setPidBit(uint8_t pid) { - uint8_t arrayIndex = getPidIntervalIndex(pid); - if(isSupportedPidRequest(pid)) { - arrayIndex -= 1; - } - - uint8_t bitPosition = getPidBitPosition(pid); - bitWrite(pidMode01Supported[arrayIndex], bitPosition, 1); - - // mark available intervals - for (int i = 0; i < arrayIndex; i++) { - bitWrite(pidMode01Supported[i], 0, 1); - } -} - -uint8_t PidProcessor::getPidBitPosition(uint8_t pid) { - uint8_t intervalId = getPidIntervalId(pid) ; - if(isSupportedPidRequest(pid)) { - intervalId -= PID_INTERVAL_OFFSET; - } - - uint16_t pos = pid - intervalId; - pos = PID_INTERVAL_OFFSET - pos; - return pos; -} - - -uint32_t PidProcessor:: getSupportedPids(uint8_t pid) { - uint8_t index = getPidIntervalIndex(pid); - return pidMode01Supported[index]; -} - -void PidProcessor::getFormattedResponse(char *response, uint8_t totalNumberOfChars, const String& pid, uint32_t value) { - uint8_t nValueChars = totalNumberOfChars - PID_N_BYTES * N_CHARS_IN_BYTE; - char cValue[3] = {0}; - itoa(nValueChars, cValue, DEC); - String mask = "%s%0"; - mask.concat(cValue); - mask.concat("lX\0"); - String pidResponse = convertToPidResponse(pid); - sprintf(response, mask.c_str(), pidResponse.c_str(), value); - - DEBUG("RX PID: " + pid + " - TX: " + String(response)); -} - -String PidProcessor::convertToPidResponse(String pid) { - String x = "4"; - x.concat(pid.substring(1, pid.length())); - return x; -} - -void PidProcessor::resetPidMode01Array() { - for(uint8_t i = 0; i < N_MODE01_INTERVALS; i++ ) { - pidMode01Supported[i] = 0x0; - } -} - - - - - - diff --git a/10-OBD-Display-2024/elmulator/src/PidProcessor.h b/10-OBD-Display-2024/elmulator/src/PidProcessor.h deleted file mode 100644 index 378850b..0000000 --- a/10-OBD-Display-2024/elmulator/src/PidProcessor.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef ELMulator_PIDPROCESSOR_H -#define ELMulator_PIDPROCESSOR_H - -#include "definitions.h" -#include -#include -#include -#include "OBDWiFiComm.h" -#include "OBDSerialComm.h" - -class PidProcessor -{ - -public: - PidProcessor(OBDWiFiComm *connection); - PidProcessor(OBDSerialComm *connection); - bool process(String &string); - - bool registerMode01Pid(uint32_t pid); - - bool registerMode01MILResponse(const String &response); - - bool registerMode03Response(const String &response); - - void writePidResponse(const String &requestPid, uint8_t numberOfBytes, uint32_t value); - - uint8_t getPidCodeFromHex(uint16_t hexCommand); - uint8_t getPidCodeFromRequest(const String &command); - - bool isMode01(const String &command); - bool isMode01MIL(const String &command); - bool isMode03(const String &command); - bool isMode22(const String &command); - -private: -#if USE_WIFI - OBDWiFiComm *_connection; -#else - OBDSerialComm *_connection; -#endif - uint32_t pidMode01Supported[N_MODE01_INTERVALS]; - - bool isSupportedPidRequest(uint8_t pid); - - uint32_t getSupportedPids(uint8_t pidcode); - - uint8_t getPidIntervalId(uint8_t pidcode); - - uint8_t getPidIntervalIndex(uint8_t pidcode); - - void setPidBit(uint8_t pid); - - uint8_t getPidBitPosition(uint8_t pidcode); - - String convertToPidResponse(String pid); - - void getFormattedResponse(char *response, uint8_t totalNumberOfChars, const String &pid, uint32_t value); - - void resetPidMode01Array(); -}; - -#endif // ELMulator_PIDPROCESSOR_H diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ESP32_Custom_ELMulator.h b/10-OBD-Display-2024/elmulator/src/custom/ESP32_Custom_ELMulator.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ESP32_Custom_ELMulator.h rename to 10-OBD-Display-2024/elmulator/src/custom/ESP32_Custom_ELMulator.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ESP32_Custom_ELMulator.ino b/10-OBD-Display-2024/elmulator/src/custom/main.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Custom_ELMulator/ESP32_Custom_ELMulator.ino rename to 10-OBD-Display-2024/elmulator/src/custom/main.cpp diff --git a/10-OBD-Display-2024/elmulator/src/definitions.h b/10-OBD-Display-2024/elmulator/src/definitions.h deleted file mode 100644 index c1b030b..0000000 --- a/10-OBD-Display-2024/elmulator/src/definitions.h +++ /dev/null @@ -1,294 +0,0 @@ -#ifndef ELMulator_DEFINITIONS_H -#define ELMulator_DEFINITIONS_H - -#include - -// true == We are running on hardware that has builtin Bluetooth -// false == We are using hardware that has BT module attached via GPIO pins -#define BLUETOOTH_BUILTIN true - -#define USE_WIFI false - -#define DO_DEBUG true -#define DEBUG(x) do {if (DO_DEBUG) { Serial.println(x); } } while (0) - -#define xtoc(x) ((x < 10) ? ('0' + x) : ('A' - 10 + x)) -#define getNumOfHexChars(nBytes) (nBytes * 2) - -#define PID_N_BYTES 2 -#define N_CHARS_IN_BYTE 2 - -// Device ID -#define ID "ELM327 / ELMulator V1.3.0" -#define DESC "ELMulator OBD2 Arduino library, based on ELM327 protocol" -#define PROTOCOL "6" // canbus 500k 11 bit protocol id for elm. - -// Char representing end of serial string -#define SERIAL_END_CHAR 0x0D -#define SERIAL_READ_TIMEOUT 20000L - -#define WIFI_END_CHAR 0x0A - -const uint8_t maxPid = 0xFF; -const uint8_t N_MODE01_INTERVALS = 7; -const uint8_t PID_INTERVAL_OFFSET = 0x20; -const uint8_t MAX_REQUEST_SIZE = 40; - - -//-------------------------------------------------------------------------------------// -// Protocol IDs -//-------------------------------------------------------------------------------------// -const char AUTOMATIC = '0'; -const char SAE_J1850_PWM_41_KBAUD = '1'; -const char SAE_J1850_PWM_10_KBAUD = '2'; -const char ISO_9141_5_BAUD_INIT = '3'; -const char ISO_14230_5_BAUD_INIT = '4'; -const char ISO_14230_FAST_INIT = '5'; -const char ISO_15765_11_BIT_500_KBAUD = '6'; -const char ISO_15765_29_BIT_500_KBAUD = '7'; -const char ISO_15765_11_BIT_250_KBAUD = '8'; -const char ISO_15765_29_BIT_250_KBAUD = '9'; -const char SAE_J1939_29_BIT_250_KBAUD = 'A'; -const char USER_1_CAN = 'B'; -const char USER_2_CAN = 'C'; - - - - -//-------------------------------------------------------------------------------------// -// PIDs (https://en.wikipedia.org/wiki/OBD-II_PIDs) -//-------------------------------------------------------------------------------------// -const uint8_t SUPPORTED_PIDS_1_20 = 0; // 0x00 - bit encoded -const uint8_t MONITOR_STATUS_SINCE_DTC_CLEARED = 1; // 0x01 - bit encoded -const uint8_t FREEZE_DTC = 2; // 0x02 - -const uint8_t FUEL_SYSTEM_STATUS = 3; // 0x03 - bit encoded -const uint8_t ENGINE_LOAD = 4; // 0x04 - % -const uint8_t ENGINE_COOLANT_TEMP = 5; // 0x05 - °C -const uint8_t SHORT_TERM_FUEL_TRIM_BANK_1 = 6; // 0x06 - % -const uint8_t LONG_TERM_FUEL_TRIM_BANK_1 = 7; // 0x07 - % -const uint8_t SHORT_TERM_FUEL_TRIM_BANK_2 = 8; // 0x08 - % -const uint8_t LONG_TERM_FUEL_TRIM_BANK_2 = 9; // 0x09 - % -const uint8_t FUEL_PRESSURE = 10; // 0x0A - kPa -const uint8_t INTAKE_MANIFOLD_ABS_PRESSURE = 11; // 0x0B - kPa -const uint8_t ENGINE_RPM = 12; // 0x0C - rpm -const uint8_t VEHICLE_SPEED = 13; // 0x0D - km/h -const uint8_t TIMING_ADVANCE = 14; // 0x0E - ° before TDC -const uint8_t INTAKE_AIR_TEMP = 15; // 0x0F - °C -const uint8_t MAF_FLOW_RATE = 16; // 0x10 - g/s -const uint8_t THROTTLE_POSITION = 17; // 0x11 - % -const uint8_t COMMANDED_SECONDARY_AIR_STATUS = 18; // 0x12 - bit encoded -const uint8_t OXYGEN_SENSORS_PRESENT_2_BANKS = 19; // 0x13 - bit encoded -const uint8_t OXYGEN_SENSOR_1_A = 20; // 0x14 - V % -const uint8_t OXYGEN_SENSOR_2_A = 21; // 0x15 - V % -const uint8_t OXYGEN_SENSOR_3_A = 22; // 0x16 - V % -const uint8_t OXYGEN_SENSOR_4_A = 23; // 0x17 - V % -const uint8_t OXYGEN_SENSOR_5_A = 24; // 0x18 - V % -const uint8_t OXYGEN_SENSOR_6_A = 25; // 0x19 - V % -const uint8_t OXYGEN_SENSOR_7_A = 26; // 0x1A - V % -const uint8_t OXYGEN_SENSOR_8_A = 27; // 0x1B - V % -const uint8_t OBD_STANDARDS = 28; // 0x1C - bit encoded -const uint8_t OXYGEN_SENSORS_PRESENT_4_BANKS = 29; // 0x1D - bit encoded -const uint8_t AUX_INPUT_STATUS = 30; // 0x1E - bit encoded -const uint8_t RUN_TIME_SINCE_ENGINE_START = 31; // 0x1F - sec - -const uint8_t SUPPORTED_PIDS_21_40 = 32; // 0x20 - bit encoded -const uint8_t DISTANCE_TRAVELED_WITH_MIL_ON = 33; // 0x21 - km -const uint8_t FUEL_RAIL_PRESSURE = 34; // 0x22 - kPa -const uint8_t FUEL_RAIL_GUAGE_PRESSURE = 35; // 0x23 - kPa -const uint8_t OXYGEN_SENSOR_1_B = 36; // 0x24 - ratio V -const uint8_t OXYGEN_SENSOR_2_B = 37; // 0x25 - ratio V -const uint8_t OXYGEN_SENSOR_3_B = 38; // 0x26 - ratio V -const uint8_t OXYGEN_SENSOR_4_B = 39; // 0x27 - ratio V -const uint8_t OXYGEN_SENSOR_5_B = 40; // 0x28 - ratio V -const uint8_t OXYGEN_SENSOR_6_B = 41; // 0x29 - ratio V -const uint8_t OXYGEN_SENSOR_7_B = 42; // 0x2A - ratio V -const uint8_t OXYGEN_SENSOR_8_B = 43; // 0x2B - ratio V -const uint8_t COMMANDED_EGR = 44; // 0x2C - % -const uint8_t EGR_ERROR = 45; // 0x2D - % -const uint8_t COMMANDED_EVAPORATIVE_PURGE = 46; // 0x2E - % -const uint8_t FUEL_TANK_LEVEL_INPUT = 47; // 0x2F - % -const uint8_t WARM_UPS_SINCE_CODES_CLEARED = 48; // 0x30 - count -const uint8_t DIST_TRAV_SINCE_CODES_CLEARED = 49; // 0x31 - km -const uint8_t EVAP_SYSTEM_VAPOR_PRESSURE = 50; // 0x32 - Pa -const uint8_t ABS_BAROMETRIC_PRESSURE = 51; // 0x33 - kPa -const uint8_t OXYGEN_SENSOR_1_C = 52; // 0x34 - ratio mA -const uint8_t OXYGEN_SENSOR_2_C = 53; // 0x35 - ratio mA -const uint8_t OXYGEN_SENSOR_3_C = 54; // 0x36 - ratio mA -const uint8_t OXYGEN_SENSOR_4_C = 55; // 0x37 - ratio mA -const uint8_t OXYGEN_SENSOR_5_C = 56; // 0x38 - ratio mA -const uint8_t OXYGEN_SENSOR_6_C = 57; // 0x39 - ratio mA -const uint8_t OXYGEN_SENSOR_7_C = 58; // 0x3A - ratio mA -const uint8_t OXYGEN_SENSOR_8_C = 59; // 0x3B - ratio mA -const uint8_t CATALYST_TEMP_BANK_1_SENSOR_1 = 60; // 0x3C - °C -const uint8_t CATALYST_TEMP_BANK_2_SENSOR_1 = 61; // 0x3D - °C -const uint8_t CATALYST_TEMP_BANK_1_SENSOR_2 = 62; // 0x3E - °C -const uint8_t CATALYST_TEMP_BANK_2_SENSOR_2 = 63; // 0x3F - °C - -const uint8_t SUPPORTED_PIDS_41_60 = 64; // 0x40 - bit encoded -const uint8_t MONITOR_STATUS_THIS_DRIVE_CYCLE = 65; // 0x41 - bit encoded -const uint8_t CONTROL_MODULE_VOLTAGE = 66; // 0x42 - V -const uint8_t ABS_LOAD_VALUE = 67; // 0x43 - % -const uint8_t FUEL_AIR_COMMANDED_EQUIV_RATIO = 68; // 0x44 - ratio -const uint8_t RELATIVE_THROTTLE_POSITION = 69; // 0x45 - % -const uint8_t AMBIENT_AIR_TEMP = 70; // 0x46 - °C -const uint8_t ABS_THROTTLE_POSITION_B = 71; // 0x47 - % -const uint8_t ABS_THROTTLE_POSITION_C = 72; // 0x48 - % -const uint8_t ABS_THROTTLE_POSITION_D = 73; // 0x49 - % -const uint8_t ABS_THROTTLE_POSITION_E = 74; // 0x4A - % -const uint8_t ABS_THROTTLE_POSITION_F = 75; // 0x4B - % -const uint8_t COMMANDED_THROTTLE_ACTUATOR = 76; // 0x4C - % -const uint8_t TIME_RUN_WITH_MIL_ON = 77; // 0x4D - min -const uint8_t TIME_SINCE_CODES_CLEARED = 78; // 0x4E - min -const uint8_t MAX_VALUES_EQUIV_V_I_PRESSURE = 79; // 0x4F - ratio V mA kPa -const uint8_t MAX_MAF_RATE = 80; // 0x50 - g/s -const uint8_t FUEL_TYPE = 81; // 0x51 - ref table -const uint8_t ETHANOL_FUEL_PERCENT = 82; // 0x52 - % -const uint8_t ABS_EVAP_SYS_VAPOR_PRESSURE = 83; // 0x53 - kPa -const uint8_t EVAP_SYS_VAPOR_PRESSURE = 84; // 0x54 - Pa -const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_1_3 = 85; // 0x55 - % -const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_1_3 = 86; // 0x56 - % -const uint8_t SHORT_TERM_SEC_OXY_SENS_TRIM_2_4 = 87; // 0x57 - % -const uint8_t LONG_TERM_SEC_OXY_SENS_TRIM_2_4 = 88; // 0x58 - % -const uint8_t FUEL_RAIL_ABS_PRESSURE = 89; // 0x59 - kPa -const uint8_t RELATIVE_ACCELERATOR_PEDAL_POS = 90; // 0x5A - % -const uint8_t HYBRID_BATTERY_REMAINING_LIFE = 91; // 0x5B - % -const uint8_t ENGINE_OIL_TEMP = 92; // 0x5C - °C -const uint8_t FUEL_INJECTION_TIMING = 93; // 0x5D - ° -const uint8_t ENGINE_FUEL_RATE = 94; // 0x5E - L/h -const uint8_t EMISSION_REQUIREMENTS = 95; // 0x5F - bit encoded - -const uint8_t SUPPORTED_PIDS_61_80 = 96; // 0x60 - bit encoded -const uint8_t DEMANDED_ENGINE_PERCENT_TORQUE = 97; // 0x61 - % -const uint8_t ACTUAL_ENGINE_TORQUE = 98; // 0x62 - % -const uint8_t ENGINE_REFERENCE_TORQUE = 99; // 0x63 - Nm -const uint8_t ENGINE_PERCENT_TORQUE_DATA = 100; // 0x64 - % -const uint8_t AUX_INPUT_OUTPUT_SUPPORTED = 101; // 0x65 - bit encoded - -const uint8_t ODOMETER = 166; // 0xA6 - km * 10 - -const uint8_t SERVICE_01 = 1; -const uint8_t SERVICE_02 = 2; -const uint8_t SERVICE_03 = 3; - - -//-------------------------------------------------------------------------------------// -// AT commands (https://www.sparkfun.com/datasheets/Widgets/ELM327_AT_Commands.pdf) -//-------------------------------------------------------------------------------------// -const char * const DISP_DEVICE_DESCRIPT = "AT @1"; // General -const char * const DISP_DEVICE_ID = "AT @2"; // General -const char * const STORE_DEVICE_ID = "AT @3 %s"; // General -const char * const REPEAT_LAST_COMMAND = "AT \r"; // General -const char * const ALLOW_LONG_MESSAGES = "AT AL"; // General -const char * const AUTOMATIC_RECEIVE = "AT AR"; // OBD -const char * const ADAPTIVE_TIMING_OFF = "AT AT0"; // OBD -const char * const ADAPTIVE_TIMING_AUTO_1 = "AT AT1"; // OBD -const char * const ADAPTIVE_TIMING_AUTO_2 = "AT AT2"; // OBD -const char * const DUMP_BUFFER = "AT BD"; // OBD -const char * const BYPASS_INIT_SEQUENCE = "AT BI"; // OBD -const char * const TRY_BAUD_DIVISOR = "AT BRD %02d"; // General -const char * const SET_HANDSHAKE_TIMEOUT = "AT BRT %02d"; // General -const char * const CAN_AUTO_FORMAT_OFF = "AT CAF0"; // CAN -const char * const CAN_AUTO_FORMAT_ON = "AT CAF1"; // CAN -const char * const CAN_EXTENDED_ADDRESS_OFF = "AT CEA"; // CAN -const char * const USE_CAN_EXTENDED_ADDRESS = "AT CEA %02d"; // CAN -const char * const SET_ID_FILTER = "AT CF %s"; // CAN -const char * const CAN_FLOW_CONTROL_OFF = "AT CFC0"; // CAN -const char * const CAN_FLOW_CONTROL_ON = "AT CFC1"; // CAN -const char * const SET_ID_MASK = "AT CM %s"; // CAN -const char * const SET_CAN_PRIORITY = "AT CP %02d"; // CAN -const char * const SHOW_CAN_STATUS = "AT CS"; // CAN -const char * const CAN_SILENT_MODE_OFF = "AT CSM0"; // CAN -const char * const CAN_SILENT_MODE_ON = "AT CSM1"; // CAN -const char * const CALIBRATE_VOLTAGE_CUSTOM = "AT CV %04d"; // Volts -const char * const RESTORE_CV_TO_FACTORY = "AT CV 0000"; // Volts -const char * const SET_ALL_TO_DEFAULTS = "AT D"; // General -const char * const DISP_DLC_OFF = "AT D0"; // CAN -const char * const DISP_DLC_ON = "AT D1"; // CAN -const char * const MONITOR_FOR_DM1_MESSAGES = "AT DM1"; // J1939 -const char * const DISP_CURRENT_PROTOCOL = "AT DP"; // OBD -const char * const DISP_CURRENT_PROTOCOL_NUM = "AT DPN"; // OBD -const char * const ECHO_OFF = "AT E0"; // General -const char * const ECHO_ON = "AT E1"; // General -const char * const FLOW_CONTROL_SET_DATA_TO = "AT FC SD %s"; // CAN -const char * const FLOW_CONTROL_SET_HEAD_TO = "AT FC SH %s"; // CAN -const char * const FLOW_CONTROL_SET_MODE_TO = "AT FC SM %c"; // CAN -const char * const FORGE_EVENTS = "AT FE"; // General -const char * const PERFORM_FAST_INIT = "AT FI"; // ISO -const char * const HEADERS_OFF = "AT H0"; // OBD -const char * const HEADERS_ON = "AT H1"; // OBD -const char * const DISP_ID = "AT I"; // General -const char * const SET_ISO_BAUD_10400 = "AT IB 10"; // ISO -const char * const SET_ISO_BAUD_4800 = "AT IB 48"; // ISO -const char * const SET_ISO_BAUD_9600 = "AT IB 96"; // ISO -const char * const IFR_VAL_FROM_HEADER = "AT IFR H"; // J1850 -const char * const IFR_VAL_FROM_SOURCE = "AT IFR S"; // J1850 -const char * const IFRS_OFF = "AT IFR0"; // J1850 -const char * const IFRS_AUTO = "AT IFR1"; // J1850 -const char * const IFRS_ON = "AT IFR2"; // J1850 -const char * const IREAD_IGNMON_INPUT_LEVEL = "AT IGN"; // Other -const char * const SET_ISO_SLOW_INIT_ADDRESS = "AT IIA %02d"; // ISO -const char * const USE_J1939_ELM_DATA_FORMAT = "AT JE"; // J1850 -const char * const J1939_HEAD_FORMAT_OFF = "AT JHF0"; // J1850 -const char * const J1939_HEAD_FORMAT_ON = "AT JHF1"; // J1850 -const char * const USE_J1939_SAE_DATA_FORMAT = "AT JS"; // J1850 -const char * const SET_J1939_TIMER_X_TO_1X = "AT JTM1"; // J1850 -const char * const SET_J1939_TIMER_X_TO_5X = "AT JTM5"; // J1850 -const char * const DISP_KEY_WORDS = "AT KW"; // ISO -const char * const KEY_WORD_CHECKING_OFF = "AT KW0"; // ISO -const char * const KEY_WORD_CHECKING_ON = "AT KW1"; // ISO -const char * const LINEFEEDS_OFF = "AT L0"; // General -const char * const LINEFEEDS_ON = "AT L1"; // General -const char * const LOW_POWER_MODE = "AT LP"; // General -const char * const MEMORY_OFF = "AT M0"; // General -const char * const MEMORY_ON = "AT M1"; // General -const char * const MONITOR_ALL = "AT MA"; // OBD -const char * const MONITOR_FOR_PGN = "AT MP %s"; // J1939 -const char * const MONITOR_FOR_RECEIVER = "AT MR %02d"; // OBD -const char * const MONITOR_FOR_TRANSMITTER = "AT MT %02d"; // OBD -const char * const NORMAL_LENGTH_MESSAGES = "AT NL"; // OBD -const char * const SET_PROTO_OPTIONS_AND_BAUD = "AT PB %s"; // OBD -const char * const PROTOCOL_CLOSE = "AT PC"; // OBD -const char * const ALL_PROG_PARAMS_OFF = "AT PP FF OFF";// PPs -const char * const ALL_PROG_PARAMS_ON = "AT PP FF ON"; // PPs -const char * const SET_PROG_PARAM_OFF = "AT PP %s OFF";// PPs -const char * const SET_PROG_PARAM_ON = "AT PP %s ON"; // PPs -const char * const SET_PROG_PARAM_VAL = "AT PP %s SV %s"; // PPs -const char * const DISP_PP_SUMMARY = "AT PPS"; // PPs -const char * const RESPONSES_OFF = "AT R0"; // OBD -const char * const RESPONSES_ON = "AT R1"; // OBD -const char * const SET_RECEIVE_ADDRESS_TO = "AT RA %02d"; // OBD -const char * const READ_STORED_DATA = "AT RD"; // General -const char * const SEND_RTR_MESSAGE = "AT RTR"; // CAN -const char * const READ_VOLTAGE = "AT RV"; // Volts -const char * const PRINTING_SPACES_OFF = "AT S0"; // OBD -const char * const PRINTING_SPACES_ON = "AT S1"; // OBD -const char * const STORE_DATA_BYTE = "AT SD "; // General -const char * const SET_HEADER = "AT SH %s"; // OBD -const char * const PERFORM_SLOW_INIT = "AT SI"; // ISO -const char * const SET_PROTOCOL_TO_AUTO_H_SAVE = "AT SP A%c"; // OBD -const char * const SET_PROTOCOL_TO_H_SAVE = "AT SP %c"; // OBD -const char * const SET_PROTOCOL_TO_AUTO_SAVE = "AT SP 00"; // OBD -const char * const SET_REC_ADDRESS = "AT SR %02d"; // OBD -const char * const SET_STANDARD_SEARCH_ORDER = "AT SS"; // OBD -const char * const SET_TIMEOUT_TO_H_X_4MS = "AT ST %02d"; // OBD -const char * const SET_WAKEUP_TO_H_X_20MS = "AT SW %02d"; // ISO -const char * const SET_TESTER_ADDRESS_TO = "AT TA %02d"; // OBD -const char * const TRY_PROT_H_AUTO_SEARCH = "AT TP A%c"; // OBD -const char * const TRY_PROT_H = "AT TP %c"; // OBD -const char * const VARIABLE_DLC_OFF = "AT V0"; // CAN -const char * const VARIABLE_DLC_ON = "AT V1"; // CAN -const char * const SET_WAKEUP_MESSAGE = "AT WM"; // ISO -const char * const WARM_START = "AT WS"; // General -const char * const RESET_ALL = "AT Z"; // General - - -const uint8_t responseBytes[0xA9] = -{ - 4, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, - 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, - 4, 4, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 4, 4, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, - 4, 1, 1, 2, 5, 2, 5, 3, 3, 7, 5, 5, 5, 11, 9, 3, 10, 6, 5, 5, 5, 7, 7, 5, 9, 9, 7, 7, 9, 1, 1, 13, - 4, 41, 41, 9, 1, 10, 5, 5, 13, 41, 41, 7, 17, 1, 1, 7, 3, 5, 2, 3, 12, 9, 9, 6, 4, 17, 4, 2, 9 -}; - -#endif //ELMulator_DEFINITIONS_H diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ESP32_Simple_ELMulator.h b/10-OBD-Display-2024/elmulator/src/simple/ESP32_Simple_ELMulator.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ESP32_Simple_ELMulator.h rename to 10-OBD-Display-2024/elmulator/src/simple/ESP32_Simple_ELMulator.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ESP32_Simple_ELMulator.ino b/10-OBD-Display-2024/elmulator/src/simple/main.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Simple/ESP32_Simple_ELMulator/ESP32_Simple_ELMulator.ino rename to 10-OBD-Display-2024/elmulator/src/simple/main.cpp diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ESP32_WiFi_Custom_ELMulator.h b/10-OBD-Display-2024/elmulator/src/wifi/ESP32_WiFi_Custom_ELMulator.h similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ESP32_WiFi_Custom_ELMulator.h rename to 10-OBD-Display-2024/elmulator/src/wifi/ESP32_WiFi_Custom_ELMulator.h diff --git a/10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ESP32_WiFi_Custom_ELMulator.ino b/10-OBD-Display-2024/elmulator/src/wifi/main.cpp similarity index 100% rename from 10-OBD-Display-2024/elmulator/examples/ESP32_Wifi/ESP32_WiFi_Custom_ELMulator/ESP32_WiFi_Custom_ELMulator.ino rename to 10-OBD-Display-2024/elmulator/src/wifi/main.cpp diff --git a/2-Program Example/Demo_Arduino/sd/lv_conf.h b/2-Program Example/Demo_Arduino/sd/include/lv_conf.h similarity index 100% rename from 2-Program Example/Demo_Arduino/sd/lv_conf.h rename to 2-Program Example/Demo_Arduino/sd/include/lv_conf.h diff --git a/2-Program Example/Demo_Arduino/sd/pincfg.h b/2-Program Example/Demo_Arduino/sd/include/pincfg.h similarity index 100% rename from 2-Program Example/Demo_Arduino/sd/pincfg.h rename to 2-Program Example/Demo_Arduino/sd/include/pincfg.h diff --git a/2-Program Example/Demo_Arduino/sd/platformio.ini b/2-Program Example/Demo_Arduino/sd/platformio.ini new file mode 100644 index 0000000..f4abb06 --- /dev/null +++ b/2-Program Example/Demo_Arduino/sd/platformio.ini @@ -0,0 +1,25 @@ +; JC3636W518 — ESP32-S3R8, 16 MB QIO flash, 8 MB OPI PSRAM, 360x360 ST77916 QSPI + CST816S +; Settings mirror the vendor Arduino IDE setup (2-Program Example/Demo_Arduino/docs/Arduino set up.png) + +[env:jc3636w518] +; pioarduino = Arduino core 3.0.5 (ESP32_Display_Panel 0.1.4 needs core 3.x) +platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip +board = esp32-s3-devkitc-1 +framework = arduino + +board_build.arduino.memory_type = qio_opi +board_build.flash_mode = qio +board_upload.flash_size = 16MB +board_build.partitions = huge_app.csv + +build_flags = + -DBOARD_HAS_PSRAM + -DARDUINO_USB_CDC_ON_BOOT=1 + +; vendor-bundled libraries (not needed by this sketch, kept for consistency) +lib_extra_dirs = ../library + +upload_port = COM21 +monitor_port = COM21 +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder diff --git a/2-Program Example/Demo_Arduino/sd/sd.ino b/2-Program Example/Demo_Arduino/sd/src/main.cpp similarity index 95% rename from 2-Program Example/Demo_Arduino/sd/sd.ino rename to 2-Program Example/Demo_Arduino/sd/src/main.cpp index 71fc55b..9bbcbb8 100644 --- a/2-Program Example/Demo_Arduino/sd/sd.ino +++ b/2-Program Example/Demo_Arduino/sd/src/main.cpp @@ -1,75 +1,76 @@ -#include "pincfg.h" - -#include "SD_MMC.h" -// #include "FS.h" - -void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { - Serial.printf("Listing directory: %s\n", dirname); - - File root = fs.open(dirname); - if (!root) { - Serial.println("Failed to open directory"); - return; - } - if (!root.isDirectory()) { - Serial.println("Not a directory"); - return; - } - - File file = root.openNextFile(); - while (file) { - if (file.isDirectory()) { - Serial.print(" DIR : "); - Serial.println(file.name()); - if (levels) { - listDir(fs, file.path(), levels - 1); - } - } else { - Serial.print(" FILE: "); - Serial.print(file.name()); - Serial.print(" SIZE: "); - Serial.println(file.size()); - } - file = root.openNextFile(); - } -} - -void setup() { - delay(200); - Serial.begin(115200); - - // Configure the SDMMC host - SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); - - if (!SD_MMC.begin()) { - Serial.println("Card Mount Failed"); - return; - } - - uint8_t cardType = SD_MMC.cardType(); - if (cardType == CARD_NONE) { - Serial.println("No SD card attached"); - return; - } - - Serial.println("SD Card initialized successfully."); - - Serial.print("SD_MMC Card Type: "); - if (cardType == CARD_MMC) { - Serial.println("MMC"); - } else if (cardType == CARD_SD) { - Serial.println("SDSC"); - } else if (cardType == CARD_SDHC) { - Serial.println("SDHC"); - } else { - Serial.println("UNKNOWN"); - } - - uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024); - Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize); - - listDir(SD_MMC, "/", 0); -} - -void loop() { -} +#include +#include "pincfg.h" + +#include "SD_MMC.h" +// #include "FS.h" + +void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { + Serial.printf("Listing directory: %s\n", dirname); + + File root = fs.open(dirname); + if (!root) { + Serial.println("Failed to open directory"); + return; + } + if (!root.isDirectory()) { + Serial.println("Not a directory"); + return; + } + + File file = root.openNextFile(); + while (file) { + if (file.isDirectory()) { + Serial.print(" DIR : "); + Serial.println(file.name()); + if (levels) { + listDir(fs, file.path(), levels - 1); + } + } else { + Serial.print(" FILE: "); + Serial.print(file.name()); + Serial.print(" SIZE: "); + Serial.println(file.size()); + } + file = root.openNextFile(); + } +} + +void setup() { + delay(200); + Serial.begin(115200); + + // Configure the SDMMC host + SD_MMC.setPins(SD_MMC_CLK_PIN, SD_MMC_CMD_PIN, SD_MMC_D0_PIN, SD_MMC_D1_PIN, SD_MMC_D2_PIN, SD_MMC_D3_PIN); + + if (!SD_MMC.begin()) { + Serial.println("Card Mount Failed"); + return; + } + + uint8_t cardType = SD_MMC.cardType(); + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return; + } + + Serial.println("SD Card initialized successfully."); + + Serial.print("SD_MMC Card Type: "); + if (cardType == CARD_MMC) { + Serial.println("MMC"); + } else if (cardType == CARD_SD) { + Serial.println("SDSC"); + } else if (cardType == CARD_SDHC) { + Serial.println("SDHC"); + } else { + Serial.println("UNKNOWN"); + } + + uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024); + Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize); + + listDir(SD_MMC, "/", 0); +} + +void loop() { +} diff --git a/CLAUDE.md b/CLAUDE.md index 84858f5..8086533 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -40,6 +40,17 @@ Free : GPIO38, GPIO39 (on CN2 header) USB : D-=19 D+=20 ``` +## PlatformIO setup (preferred build system, since 2026-10-23) +- All projects are **PlatformIO projects** (`platformio.ini`, `src/main.cpp`, `include/`). They no longer open in the Arduino IDE. +- PlatformIO IDE extension is installed in VS Code. CLI: `%USERPROFILE%\.platformio\penv\Scripts\pio.exe` (Core 6.2.0, not on PATH). +- **JC3636W518 (ESP32-S3)**: platform `https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip` (pioarduino = Arduino core 3.0.5; the official PIO espressif32 only has core 2.x, which ESP32_Display_Panel 0.1.4 can't use). + Board `esp32-s3-devkitc-1` + `board_build.arduino.memory_type = qio_opi`, `flash_mode = qio`, `board_upload.flash_size = 16MB`, `partitions = huge_app.csv`, `-DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=1`, upload/monitor COM21 @115200. + Libraries: `lib_extra_dirs` → vendor `2-Program Example/Demo_Arduino/library`. + **LVGL config:** `-DLV_CONF_INCLUDE_SIMPLE -Iinclude` — the `-Iinclude` is required, otherwise the LVGL library compiles without the project's `lv_conf.h` (symptom: `undefined reference to lv_gif_create`). +- **Classic ESP32** projects (bridge, ELMulator): `espressif32@6.10.0` (core 2.0.17), board `esp32dev`, `huge_app.csv`. +- Template for a new JC3636W518 project: copy `10-OBD-Display-2024/display_speed_wifi/platformio.ini` (+ `include/pincfg.h`, `include/scr_st77916.h`, `include/lv_conf.h`). +- When converting `.ino` → `main.cpp`: add `#include ` and prototypes for functions used before their definition; don't `#include` `.c` files that are also in `src/`. + ## Software stack used by the vendor demo - **Arduino IDE** + **arduino-esp32 core ≥ 3.0.1** (core **3.0.5 already installed** on this PC under `%LOCALAPPDATA%\Arduino15`). - Libraries (bundled in `2-Program Example/Demo_Arduino/library/`):