Files
2026-10-10 01:40:05 +00:00

368 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ITR90 ESP32-S3 vacuum gauge controller
Arduino firmware for a Leybold/Pfeiffer ITR90 vacuum gauge, using the **Waveshare ESP32-S3-Touch-LCD-2, SKU 29667**, with a 240 × 320 touch display.
The controller displays pressure and gauge status, provides touchscreen and web controls, and supports degas through either RS-232 or the carrier board's direct +24 V control circuit. It connects to an existing router and advertises a local browser address, with a password-protected standalone Wi-Fi access point as a fallback. **The webpage and its API have no username/password login.**
> Reproduce the versions, board settings, BSP files and LVGL configuration below before changing the firmware. A successful compilation alone does not prove that the display or PSRAM is configured correctly.
## Quick start
1. Obtain the **complete working sketch folder**, including its Waveshare BSP source/header files. The application `.ino` alone is insufficient.
2. Install the [pinned board package and libraries](#pinned-board-package-and-libraries).
3. Install the working `lv_conf.h` and enable the [required fonts](#lvgl-configuration-and-fonts).
4. Select **ESP32S3 Dev Module** and match every setting in the [Tools table](#arduino-ide-tools-settings).
5. Set the [router credentials and per-board names](#wi-fi-and-multiple-boards) in the application.
6. Open the application, click **Verify**, then **Upload**. Keep the original BSP files in the same project.
7. Open Serial Monitor at **115200 baud**, reset the board, and follow [first-boot checks](#upload-and-first-boot-checks).
If anything fails, start with [troubleshooting](#troubleshooting) rather than upgrading libraries or changing the control logic.
## Pinned board package and libraries
This is the project's recorded working combination:
| Component | Working version | Installation / role |
| --- | --- | --- |
| **esp32 by Espressif Systems** | **3.3.5** | Arduino **Boards Manager**; compiler, ESP32 APIs and USB/Wi-Fi support |
| **GFX Library for Arduino** / Arduino_GFX | **1.5.0** | Library Manager or the matching vendor archive; display BSP dependency |
| **lvgl** | **8.4.0** | Library Manager; GUI library |
| **FastIMU** | **1.2.6** | Library Manager or the matching vendor archive; dependency of the supplied Waveshare BSP where used |
| Waveshare BSP/example files | Exact working copy for **ESP32-S3-Touch-LCD-2** | Keep the complete working source set; do not substitute a similarly named board's BSP |
| `WiFi.h`, `WebServer.h`, `ESPmDNS.h` | Bundled with ESP32 core **3.3.5** | No separate library installation |
Use Arduino IDE 2.x for the instructions below. The exact IDE version of the original working PC was not recorded; record the version used for future releases.
**Do not substitute LVGL 9.x, ESP32 core 3.3.11, or GFX 1.6.x when reproducing this build.** These are not the recorded working versions. Newer versions may be usable after a deliberate port and validation, but are not drop-in assumptions for this BSP.
### Install the ESP32 board package
1. Open **File → Preferences**.
2. Add the stable Espressif package index to **Additional Boards Manager URLs**:
`https://espressif.github.io/arduino-esp32/package_esp32_index.json`
3. Open **Boards Manager**, search for **esp32 by Espressif Systems**, select **3.3.5**, and install it.
4. Select **Tools → Board → ESP32 Arduino → ESP32S3 Dev Module**.
**ESP32 is a board platform, not a Library Manager entry.** If it does not appear in Library Manager, that does not mean it was deleted. Check Boards Manager instead.
### Install the libraries
Install the exact versions in the table using Library Manager's version selector. If using the working PC's supplied library archives, preserve those copies and any vendor modifications.
Enable verbose compilation output in Preferences. Check the actual library folders and versions selected by the compiler, especially if Arduino reports **“Multiple libraries were found”**. A folder name such as `lvgl` does not by itself establish its version; check its `library.properties`.
Avoid keeping several active copies of the same library under names such as `lvgl-master`, `lvgl-old` or `GFX_Library_for_Arduino_backup`. Move backups outside the sketchbook's `libraries` directory.
## Arduino IDE Tools settings
These settings were recorded from the working project:
| Tools item | Value |
| --- | --- |
| Board | **ESP32S3 Dev Module** |
| PSRAM | **OPI PSRAM** |
| Flash Size | **16MB (128Mb)** |
| Flash Mode | **QIO 80MHz** |
| Partition Scheme | **16M Flash (3MB APP/9.9MB FATFS)** |
| Upload Mode | **USB-OTG CDC (TinyUSB)** |
| USB Mode | **Hardware CDC and JTAG** |
| USB CDC On Boot | **Enabled** |
| CPU Frequency | **240MHz (WiFi)** |
| Upload Speed | **921600** |
| Port | The connected board's actual COM/serial port; this varies by PC |
Serial Monitor uses **115200 baud**. The gauge UART uses **9600 baud**. Neither value is the upload speed.
Menu labels and available choices depend on the board package and selected board. If these choices do not match, first check **ESP32 core 3.3.5** and **ESP32S3 Dev Module**. Keep the recorded USB selections; do not silently replace them with a different example's defaults.
**Copying a sketch to another PC does not reliably carry Arduino IDE Tools selections with it.** Check this table on every new PC and after switching boards or reinstalling the board package. Configuration comments in the `.ino` document the settings; they do not apply them.
## Project files and Waveshare BSP
The application must stay with the board-specific LCD, touch, I²C and SPI implementation it was tested with.
| File / location | What it should contain |
| --- | --- |
| `README.md` | This setup and troubleshooting guide |
| `ITR90/ITR90.ino` | Main application, if the sketch is named `ITR90` |
| `ITR90/bsp_*.h` and `ITR90/bsp_*.cpp` | Complete working BSP source/header set, including touch-driver dependencies |
| Other files from the working Waveshare example | Any additional sources/configuration required by that BSP |
| `config/lv_conf.h`, recommended repository copy | The exact working LVGL configuration, with installation instructions below |
| Dependency/version record | Exact versions above, plus vendor archive provenance or checksums where available |
The repository layout above is a packaging recommendation, not a claim that every listed file is already supplied. **If BSP files or `lv_conf.h` are absent, recover them from the working project or matching Waveshare package before attempting a reproducible build.**
Arduino's main sketch filename must match its enclosing folder: `ITR90/ITR90.ino`. If a downloaded file is named `ITR90(1).ino`, rename it to `ITR90.ino` when placing it in `ITR90`. Keep only one application's `setup()` and `loop()` in that sketch folder; remove the original example application after replacing it.
If reconstructing the project, start with a **copy** of the matching [Waveshare example package](https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-2), such as the factory or LVGL brightness example. Preserve its complete BSP and replace its application with this firmware. Do not mix files from different Waveshare board sizes or revisions.
The application uses these BSP functions:
```cpp
bsp_i2c_init();
bsp_lv_port_init();
bsp_spi_init();
bsp_lv_port_run();
lvgl_lock(-1);
lvgl_unlock();
```
The current application includes `bsp_i2c.h`, `bsp_lv_port.h` and `bsp_spi.h`. The BSP may include additional headers such as `bsp_cst816.h`. Those dependencies must be supplied too. If a vendor package uses different header organization, reconcile the real declarations and implementations; creating an empty header does not supply a driver.
## LVGL configuration and fonts
Use **LVGL 8.4.0** and the **working project's `lv_conf.h`**. This configuration affects LVGL's own C source files as well as the application.
For the standard Arduino LVGL 8.4 layout, put `lv_conf.h` **next to the `lvgl` folder**, in the active sketchbook's `libraries` directory:
| Windows path example | Contents |
| --- | --- |
| `C:\Users\<user>\Documents\Arduino\libraries\lvgl\` | Installed LVGL 8.4.0 library |
| `C:\Users\<user>\Documents\Arduino\libraries\lv_conf.h` | Active LVGL configuration |
Use the actual **Sketchbook location** shown in Arduino Preferences; it may differ from this example. Putting the configuration only beside `ITR90.ino` does not ensure that LVGL's library sources will find it. If the BSP explicitly configures `LV_CONF_PATH` or `LV_CONF_INCLUDE_SIMPLE`, follow that existing include setup instead.
If starting from `lv_conf_template.h`, copy the template from **LVGL 8.4.0**, rename it to `lv_conf.h` and change its opening `#if 0` to `#if 1`. Restore the working BSP's color, memory, tick and byte-order settings; an otherwise default template is not a substitute for the working configuration. This display path uses RGB565 / **16-bit color**.
The two pressure labels require these options in the active configuration:
```c
#define LV_FONT_MONTSERRAT_28 1
#define LV_FONT_MONTSERRAT_48 1
```
Keep the working configuration's default font and other enabled fonts as well. These two settings are edits within the complete configuration, **not a complete `lv_conf.h`**.
The application has conditional checks around the 28- and 48-pixel fonts. If those fonts are disabled, it can compile while using the default font, making the pressure labels smaller than intended.
After replacing `lv_conf.h`, rebuild and confirm that the compiler is using the intended library/configuration. If font linking still fails, follow the clean reinstall procedure under troubleshooting.
See the [LVGL 8.4 Arduino configuration guide](https://lvgl.io/docs/open/8.4/get-started/platforms/arduino) and [configuration/include-path guide](https://lvgl.io/docs/open/8.4/porting/project).
## Wi-Fi and multiple boards
Configure these values near the top of the application before uploading:
```cpp
const char *WIFI_SSID = "YOUR_ROUTER_SSID";
const char *WIFI_PASS = "YOUR_ROUTER_PASSWORD";
const char *MDNS_HOSTNAME = "itr90-1";
const bool ENABLE_FALLBACK_AP = true;
const char *FALLBACK_AP_SSID = "ITR90-Controller-1";
const char *FALLBACK_AP_PASS = "YOUR_AP_PASSWORD"; // 8–63 characters
```
The sample credentials above are placeholders; replace them. Enter only the hostname in `MDNS_HOSTNAME`, without `http://` or `.local`. Use letters, digits and hyphens.
### Router connection
Connect the board to a **2.4 GHz** Wi-Fi network and use a browser on the same LAN:
| Board | `MDNS_HOSTNAME` | Browser address |
| --- | --- | --- |
| 1 | `"itr90-1"` | `http://itr90-1.local/` |
| 2 | `"itr90-2"` | `http://itr90-2.local/` |
Use a distinct hostname for every board on that network. Two boards advertising `itr90.local` do not create a device-selection page.
The firmware prints the router-assigned IP address in Serial Monitor. If `.local` resolution is blocked or unsupported on the client/network, open `http://<that-IP>/` instead. A DHCP hostname alone is not the same as working mDNS resolution.
### Standalone fallback
- With no router SSID configured—an empty string or `"CHANGE_ME"`—the fallback AP starts immediately.
- With an SSID configured, the firmware attempts the router connection and retries approximately every **10 seconds**.
- After **30 seconds** without a router connection, it starts the fallback AP while continuing router attempts.
- If the router connection returns, it stops the fallback AP and restores the router browser address.
- A later router outage starts a new 30-second fallback window.
Join the board's `FALLBACK_AP_SSID` using `FALLBACK_AP_PASS`, then open **`http://192.168.1.1/`**. Type the explicit `http://` address if the browser tries HTTPS. A “no internet” warning on this standalone Wi-Fi network is expected; keep the connection.
Give every board a different AP name, such as `ITR90-Controller-1` and `ITR90-Controller-2`. Their separate fallback networks can share the same AP password and `192.168.1.1` address. Select the intended board's Wi-Fi network before opening that address.
There is **no webpage login** in either router or fallback mode. The fallback password protects joining its Wi-Fi network; it is not a dashboard password. Router credentials are still needed when joining a password-protected router.
If the router LAN also uses `192.168.1.x/24`, the identical fallback subnet can complicate routing while AP and station mode run together. Diagnose this separately from mDNS; use a distinct AP subnet for such a deployment and document its revised fallback URL.
Keep real Wi-Fi credentials out of public Git commits. The current firmware stores them in source; use a private configured build copy or implement a separately ignored local configuration file before publishing real credentials.
## Upload and first-boot checks
1. Use a USB **data** cable and the board's appropriate USB connection. Select its actual serial port.
2. Click **Verify** first. Save the full compiler output if it fails; the first specific error is more useful than `exit status 1`.
3. Recheck the Tools settings, then click **Upload**.
4. If upload stalls at connection, try the board's BOOT/RESET recovery procedure: hold **BOOT**, press/release **RESET**, then retry upload and release BOOT once the downloader connects. Re-select the port if it changes.
5. Open Serial Monitor at **115200 baud** and reset the board. Native USB can enumerate on a different port after boot.
6. Confirm the log begins with `ITR90 controller booting...` and progresses to `Controller ready; waiting for valid ITR90 frames`.
7. Confirm the application pressure screen appears. Any BSP RGB startup test should finish; repeated RGB cycling requires investigation.
8. Confirm touch input works. A screen that later turns off after **five minutes** of inactivity is intentional: touch wakes it, while gauge monitoring and networking continue.
9. Test the router URL or fallback URL. Open `/api/status` to inspect live JSON without any login.
10. Connect the correctly powered gauge and confirm fresh RS-232 pressure/status data before testing control functions.
If 921600 upload speed is unreliable, temporarily lower **Upload Speed**, for example to 115200, and retry. This helps transfer reliability; it does not repair a runtime PSRAM/flash configuration problem.
## Hardware and gauge interface
The ESP32 controller's USB connection does not replace the ITR90's required **24 V supply**. Use the carrier board's intended power and interface wiring.
| ESP32 GPIO | Function | Gauge/interface connection |
| --- | --- | --- |
| **17** | Gauge UART TX | MAX3232 T1IN → RS-232 output → ITR90 **pin 14, RxD** |
| **18** | Gauge UART RX | ITR90 **pin 13, TxD** → MAX3232 RS-232 input → R1OUT |
| **4** | Analog pressure diagnostic | ITR90 analog output through the carrier's **33 kΩ / 12 kΩ** divider and **100 nF** filtering |
| **10** | Direct degas request, active HIGH | Carrier's AQY212EH / +24 V switching circuit → ITR90 **pin 7** |
| **1** | LCD backlight | Reserved for the Waveshare board |
Gauge connector essentials: **pin 8 = +24 V supply**, **pin 5 = supply/serial ground**, **pin 2 = analog output**, **pin 12 = analog signal ground**. Use the actual connector's pin numbering/view; the solder side mirrors the mating view.
**Use the MAX3232 for RS-232 level conversion.** The gauge's RS-232 signals are not ESP32 3.3 V UART signals. Likewise, gauge analog output can reach 10 V and must pass through the divider; the direct-degas +24 V circuit must not connect directly to a GPIO.
The older Oerlikon Leybold ITR90 **12090** and the red Pfeiffer ITR90 use the same documented RS-232 frame/command format:
| Protocol item | Value |
| --- | --- |
| UART | **9600 baud, 8 data bits, no parity, 1 stop bit** |
| Measurements | **9-byte binary frames**, transmitted automatically approximately every 20 ms |
| Frame checks used by this firmware | Length byte **7**, page **5**, sensor type **10**, checksum = low byte of the sum of bytes 1–7 |
| Commands | **5-byte binary frames**, including the same degas ON/OFF commands |
No serial protocol change is required solely because of that older ITR90 housing. Confirm that the label actually identifies an ITR90 when substituting gauges.
## Control behavior relevant to debugging
- Fresh RS-232 data are required for degas. Data older than **500 ms** are treated as stale.
- Degas requires valid pressure **below 7.2 × 10⁻⁶ mbar**, no reported warning/error, and the gauge's **5 mA emission state**.
- The controller expects degas acknowledgement within approximately **2 seconds** and stops a request that is not acknowledged.
- Degas is limited to **3 minutes**. STOP removes the direct GPIO request and also sends the serial OFF command.
- The analog pressure estimate can support the displayed pressure when serial data are unavailable, but **does not authorize degas**.
- Touchscreen start uses a confirmation screen and a **2-second hold**. Web start uses confirmation and the same gauge prerequisite checks.
- Controls return to the pressure view after approximately **2 minutes** of inactivity; the LCD backlight turns off after **5 minutes**. The ESP32 stays awake.
An inhibited degas request with a clear reason is expected behavior when those prerequisites are not met. Diagnose the missing prerequisite rather than bypassing it to test communication.
## Troubleshooting
### `bsp_cst816.h: No such file or directory`
The touch-driver header or its BSP source set is missing/mismatched. Restore the **complete working Waveshare sketch/BSP folder**, including the driver implementation and transitive headers. Do not fix this by merely deleting the include or creating an empty file. The same approach applies to missing `bsp_i2c.h`, `bsp_spi.h` or `bsp_lv_port.h`.
### `spiFrequencyToClockDiv`: “too few arguments” / invalid conversion to `spi_t*`
The graphics library and ESP32 core disagree about the SPI API. This project encountered that failure with a compiler path showing **ESP32 core 3.3.11**. Restore **core 3.3.5** and **GFX Library for Arduino 1.5.0** together, and verify the versions/paths in verbose compiler output.
Treat a different core/GFX combination as a port requiring verification; do not patch one failing library call and assume the rest of the BSP is compatible.
### `RED`, `GREEN` or `BLUE` “was not declared in this scope”
The BSP's RGB startup test uses color names that are not provided by the selected graphics headers. First restore the pinned **GFX 1.5.0** library and matching BSP includes. A change to GFX 1.6.x was one of the project's compatibility problems.
If deliberately adapting the BSP to a different graphics version, use that version's documented color constants. For an explicitly RGB565 `fillScreen` argument, the numerical colors are `0xF800` (red), `0x07E0` (green), and `0x001F` (blue). This optional source adaptation does not replace checking the rest of the graphics API.
### `lv_conf.h` cannot be found / LVGL configuration appears ignored
Check the active sketchbook path, the configuration's location beside `lvgl`, and the opening `#if 1`. Check for duplicate configurations or an explicitly configured include path. Renaming a file to `lv_conf.h.txt` on Windows will not work; enable visible filename extensions.
### Fonts are too small, or `undefined reference to lv_font_montserrat_48` / `lv_font_montserrat_28`
Enable **both** `LV_FONT_MONTSERRAT_48` and `LV_FONT_MONTSERRAT_28` in the configuration used by **LVGL's compiled sources**, not just in `ITR90.ino`.
The undefined-reference error is a **linker** error: a font was referenced, but its compiled definition was unavailable. A declaration such as `LV_FONT_DECLARE(...)` alone cannot supply that definition.
If the same copied `lv_conf.h` works on one PC but not another:
1. Check the actual LVGL library path/version and duplicate copies using verbose output.
2. Back up the working `lv_conf.h`.
3. Uninstall the active LVGL library using Library Manager. Move any leftover competing copies outside the library search path.
4. Reinstall **lvgl 8.4.0**, restore the working configuration, restart the IDE and rebuild.
5. If necessary, force a clean rebuild rather than reusing old compiled objects. For an existing Arduino CLI build, `arduino-cli compile --clean` supports this; target only the relevant temporary build cache when cleaning manually.
**Reinstalling LVGL 8.4.0 resolved this exact font-link failure during development.** That outcome does not establish whether the original cause was a stale build, an incomplete installation or conflicting library/configuration copies; check all three.
### Upload succeeds, but the display repeatedly cycles red/green/blue
First distinguish an uninterrupted RGB test from a **reboot loop** using Serial Monitor. Repeated boot messages, watchdog/panic traces, PSRAM errors or brownout messages identify different causes.
For this project, matching the working PC's **Upload Mode, PSRAM, Partition Scheme and Flash Size** resolved the startup problem. Recheck the entire Tools table, particularly **OPI PSRAM**, **16 MB flash** and the exact partition selection. Upload success only means firmware was transferred; it does not validate those runtime settings.
Also confirm that the intended application replaced the factory example, that the BSP matches this board, and that power is stable. If settings match and cycling continues, keep the full boot log for diagnosis.
### No serial port / upload cannot connect / Serial Monitor is blank
Check the USB data cable, selected port, USB CDC settings and upload mode. Try BOOT/RESET recovery, re-select the port after enumeration, and close programs that hold the port open. Select **115200** for Serial Monitor; enabling CDC on boot matters when using the native USB console.
### Router IP works but `itr90-1.local` does not
Use the exact hostname configured for that board and the same LAN. Guest/client isolation, blocked multicast, VPN routing or client mDNS support can prevent name resolution. Test the printed IP as an alternative. If the log says mDNS startup failed, the firmware falls back to the IP while retrying.
### Fallback AP cannot be joined / `192.168.1.1` does not open
Check `ENABLE_FALLBACK_AP`, the 30-second connection window, the actual AP name and an **8–63 character** AP password. Join that AP, stay connected despite “no internet”, and enter **`http://192.168.1.1/`**. Check Serial Monitor for AP startup/configuration failures and subnet overlap. A browser trying HTTPS is not using this HTTP server.
### Browser still prompts for a username/password
Confirm that the **no-web-login firmware** was uploaded to the board you are opening. Check the hostname/AP name and verify that the source has no `server.authenticate(...)`, `server.requestAuthentication()` or `requireWebAuth()` checks. Test `/api/status` as well as the root page.
An older firmware or another board at the address can still have HTTP authentication. A login prompt when joining Wi-Fi is the separate AP/network password and is expected.
### Pressure is absent/stale, but the display and webpage work
Check gauge power, common ground, the MAX3232 level conversion and TX/RX directions in the wiring table. Confirm **9600 baud / 8N1**. Gauge output is binary, so readable text is not expected from a terminal.
Open `/api/status` and inspect `pressureSource`, `frameAge`, `gauge`, `firmware` and `message`. “ADC fallback” does not establish working RS-232 communication. When instrumenting the parser, the internal `goodFrames` and `rejectedWindows` counters help distinguish valid frames from misalignment/noise; they are not currently exported by the API.
### Degas is refused or stops shortly after starting
Read the on-screen/web `message` or Serial Monitor action log. Check fresh serial frames, gauge errors, pressure and 5 mA emission state. A direct-pin request still needs serial feedback. Missing acknowledgement after approximately 2 seconds is an intentional stop condition.
## Moving to another PC and maintaining a reproducible repository
Include the complete working application/BSP source, the exact `lv_conf.h`, this README, and the dependency versions. Record any modifications inside vendor libraries; simply naming a released version will not reproduce an unpublished patch.
For every release, record:
- Git commit/release identifier.
- Arduino IDE and ESP32 core versions.
- Library versions and the selected library paths.
- The complete Tools settings, ideally a screenshot plus this text table.
- The LVGL configuration and any vendor/BSP archive version or checksum.
- The per-board hostname/AP naming convention, with credentials redacted.
- A successful compiler log and a first-boot log.
On the receiving PC, install the pinned versions, restore the configuration into its active location, select the matching Tools settings and perform the same first-boot checks. **Copying only the `.ino` or only `lv_conf.h` is insufficient.**
### Optional Arduino CLI build profile
Arduino CLI supports a `sketch.yaml` build profile that records the full board FQBN/options and pins core/library versions. Generate a profile from a successful CLI build using `--dump-profile`, keep it with the sketch, and name the reviewed profile `verified`. Include any locally configured/vendor libraries and the LVGL configuration/include setup.
Use the **complete FQBN from the working configuration**, including its menu options. The base `esp32:esp32:esp32s3` name alone does not encode the flash, PSRAM, partition or USB choices.
Once that profile exists, from the repository root:
```sh
arduino-cli compile --profile verified ./ITR90
```
No generated/validated CLI profile is supplied by this README. A profile using a fresh stock LVGL library also needs the working `lv_conf.h` available to that library's build; do not assume it will inherit an unrelated IDE library installation. IDE users should still verify their Tools settings.
See [Arduino's build-profile documentation](https://docs.arduino.cc/arduino-cli/sketch-project-file/) and [compile command](https://docs.arduino.cc/arduino-cli/commands-reference/arduino-cli_compile).
## What to include in a bug report
Provide the board/SKU, Git revision, exact core/library versions, all Tools settings, the chosen library/configuration paths, **the first meaningful compiler error** or **full boot log**, and whether the failure occurs in router or fallback mode. Redact router/AP passwords.
Also report whether the problem reproduces on the original working PC with the same project folder and settings. This distinguishes a source regression from an environment mismatch.
## References
- [Waveshare ESP32-S3-Touch-LCD-2 board and example downloads](https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-2)
- [Espressif Arduino-ESP32 installation](https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html)
- [Arduino_GFX project](https://github.com/moononournation/Arduino_GFX)
- [LVGL 8.4 Arduino setup](https://lvgl.io/docs/open/8.4/get-started/platforms/arduino)
- [LVGL 8.4 configuration paths](https://lvgl.io/docs/open/8.4/porting/project)
- [Leybold ITR90 operating manual, GA09420_002_C0](https://www.hv-e.ru/f/manual_manual_itr_90_12090.pdf)
- [Pfeiffer ITR90 operating instructions, BG 5040 BEN](https://www.idealvac.com/files/manuals/Pfeiffer_CenterLine_ITR_90_FullRange_Pirani_Bayard_Alpert_Gauge_Operating_Instructions.pdf)
The pinned versions and Tools table above come from this project's recorded working setup. General vendor documentation may describe different example versions or defaults.