Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
.cursorignore
src/credentials.h
platformio.ini
glances.conf
156 changes: 114 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A sleek system monitoring display powered by ESP32 that shows real-time system metrics from a Glances server. Features a customizable UI with dark/light theme support using LVGL graphics library and power-saving display controls.

Forked from [iamlite/CYD-System-Monitor](https://github.com/iamlite/CYD-System-Monitor) to add compatibility for the ESP32-2432S028R and Windows hosts.

![Unraid](Images/device.jpeg)

## Features
Expand Down Expand Up @@ -30,72 +32,142 @@ A sleek system monitoring display powered by ESP32 that shows real-time system m
- Device status monitoring & control
- Remote theme control

## Requirements
## Hardware Requirements

Tested on **ESP32-2432S028R** ("Cheap Yellow Display")
- ESP32-D0WD-V3 (revision v3.1)
- 2.8" ILI9341 TFT Display (320x240)
- Integrated touch controller
- Built-in USB-to-serial converter

- ESP32 development board
- TFT display compatible with TFT_eSPI library
- I'm using this cheap yellow display with ESP32 built in: [aliexpress](https://s.click.aliexpress.com/e/_olrdG2w)
- The settings in this project are for this display.
- Glances server running on the target system
Alternatively, it should work with any ESP32 development board a TFT display compatible with
the lvgl and TFT_eSPI libraries

## Setup

1. Clone this repository
2. Open the project in PlatformIO
### 1. Install PlatformIO
Visit [https://platformio.org/](https://platformio.org/) and install PlatformIO IDE or the
PlatformIO Core CLI.

### 2. Install USB Drivers (if needed)
For ESP32-2432S028R on Windows:
- Download and install CH340 drivers from the manufacturer
- Verify the device appears in Device Manager after connection (should be under "Ports (COM & LPT)"
as USB-SERIAL CH340 or something similar)

You can also test connectivity with `esptool`:

```bash
$ pip install esptool # Install first if necessary
$ esptool read-mac
esptool v5.0.2
Connected to ESP32 on COM3:
Chip type: ESP32-D0WD-V3 (revision v3.1)
Features: Wi-Fi, BT, Dual Core + LP Core, 240MHz, Vref calibration in eFuse, Coding Scheme None
...
```

### 3. Clone the repo

```bash
$ git clone https://github.com/your-username/CYD-System-Monitor.git
$ cd CYD-System-Monitor
```

### 4. Configure PlatformIO

Rename `platformio.example.ini` to `platformio.ini` and update the library path:

```ini
# Default Arduino library locations:
# Windows: C:\Users\<username>\Documents\Arduino\libraries
# Linux: ~/Arduino/libraries
# macOS: ~/Documents/Arduino/libraries

lib_extra_dirs = /path/to/your/Arduino/libraries
```

### 5. Configure Network Credentials

Rename `credentials.example.h` to `credentials.h` and update:

- Rename the `platformio.example.ini` file to `platformio.ini`
- Edit the `platformio.ini` file to set the correct path to your Arduino libraries
```cpp
const char* const WIFI_SSID = "your_wifi_network";
const char* const WIFI_PASSWORD = "your_wifi_password";
```

3. Configure your TFT display settings:
- Modify TFT_eSPI settings according to your display's configuration
- Adjust screen resolution in config.h if needed:
### 6. Build and Upload

```cpp
```bash
# Build the project
pio run

extern const uint16_t screenWidth = 240;
extern const uint16_t screenHeight = 320;
# Upload firmware
pio run -t upload

```
# Upload filesystem (web files)
pio run -t uploadfs

4. Configure your network settings in credentials.example.h:
# Monitor serial output
pio device monitor
```

- Rename the file to `credentials.h`
- Edit the file to set your WiFi SSID and password
### 7. Configure Glances Server

```cpp
#### Option A: Use Web Interface
1. Connect to the CYD device's IP address in your browser (you can see the IP in the serial output when the device boots)
2. Configure Glances server host and port in the settings

const char*const WIFI_SSID = "your_ssid_here";
const char* const WIFI_PASSWORD = "your_password_here";
#### Option B: Use CURL
```bash
curl -X POST http://[ESP32_IP]/settings \
-H "Content-Type: application/json" \
-d '{"glances_host": "192.168.1.50", "glances_port": 61208}'
```

```
## Troubleshooting

5. Build and upload the project using PlatformIO
### Display Not Working
1. Check TFT_eSPI configuration matches your hardware
2. Verify pin connections in `User_Setup.h`
3. Enable debug mode to see initialization messages

6. Set up your Glances server configuration in the web interface:
### No Glances Data
1. Verify Glances server is running and accessible
2. Check network connectivity
3. Enable debug mode to see API call details

- Access the web interface at the device's IP address
- Configure the Glances server IP address and port
- Choose theme colors if you want to change them
- Save the configuration
Some Glances modules can be very slow on Windows, which can cause the ESP32 application to become
unresponsive while waiting on HTTP calls. You may need to disable slow modules in glances.conf,
particularly `processcount` and `sensors`. See https://github.com/nicolargo/glances/issues/3046

### Home Assistant Integration
### USB Connection Issues
1. Install CH340 drivers on Windows
2. Check cable supports data transfer (not just power)
3. Try different USB ports
4. Verify device appears in Device Manager/system logs

The device exposes REST API endpoints for Home Assistant integration:
## Debug Mode

- GET `/api/status` - Device status and metrics
- POST `/api/command` - Control endpoints for theme switching and device restart
To print extra diagnostic messages, you can enable debug mode either by setting
`bool debug_mode = true;` in config.cpp, or at runtime with `curl`:

#### Easy Integration
```bash
$ curl -X POST http://[ESP32_IP]/settings \
-H "Content-Type: application/json" \
-d '{"debug_mode": true}'
```

A complete Home Assistant configuration example is provided in [homeassistant_example.yml](homeassistant_example.yml). This includes:
## Configuration Files

- System sensors (temperature, memory, WiFi signal, uptime)
- Binary sensors for dark mode and display state
- Switches for controlling dark mode and display power
- Commands for device restart and theme reset
### Core Configuration
- `credentials.h` - WiFi network settings
- `platformio.ini` - Build configuration and library paths
- `include/config.h` - Display resolution and debug settings

Simply copy the configuration, replace `YOUR.DEVICE.IP.HERE` with your device's IP address, and add it to your Home Assistant configuration.
You should see the entities show up in home assistant after a restart.
### Hardware Configuration
- `include/User_Setup.h` - TFT_eSPI pin mappings for CYD
- Pin configuration automatically applied via build flags

## API Endpoints

Expand Down
28 changes: 28 additions & 0 deletions include/User_Setup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// User_Setup.h for ESP32-2432S028R (CYD - Cheap Yellow Display)
// This file configures TFT_eSPI for the specific CYD hardware

#define ILI9341_DRIVER // Generic driver for common displays

// ESP32 CYD specific pin configuration
#define TFT_MISO 12
#define TFT_MOSI 13
#define TFT_SCLK 14
#define TFT_CS 15 // Chip select control pin
#define TFT_DC 2 // Data Command control pin
#define TFT_RST -1 // Reset pin (could connect to RST pin)
#define TFT_BL 21 // Backlight control pin

#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel high font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel high font, needs ~2438 bytes in FLASH, only characters 1234567890:.
#define LOAD_FONT8 // Font 8. Large 75 pixel high font needs ~3256 bytes in FLASH, only characters 1234567890:-.
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts

#define SMOOTH_FONT

// SPI frequency for reading (5MHz maximum)
#define SPI_FREQUENCY 27000000
#define SPI_READ_FREQUENCY 20000000
#define SPI_TOUCH_FREQUENCY 2500000
6 changes: 6 additions & 0 deletions include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ extern String glances_host;
extern uint16_t glances_port;
#define GLANCES_UPDATE_INTERVAL 2000

// Debug configuration
extern bool debug_mode;
#define DEBUG_PRINT(x) if(debug_mode) { Serial.print(x); }
#define DEBUG_PRINTLN(x) if(debug_mode) { Serial.println(x); }
#define DEBUG_PRINTF(format, ...) if(debug_mode) { Serial.printf(format, __VA_ARGS__); }

extern const uint16_t screenWidth;
extern const uint16_t screenHeight;
struct ThemeColors
Expand Down
24 changes: 23 additions & 1 deletion platformio.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,32 @@ board = esp32dev
framework = arduino
monitor_speed = 115200
lib_extra_dirs = /YOUR_PATH/libraries
build_flags = -I include -I lib/**
build_flags =
-I include
-I lib/**
-D USER_SETUP_LOADED=1
-D ILI9341_DRIVER=1
-D TFT_MISO=12
-D TFT_MOSI=13
-D TFT_SCLK=14
-D TFT_CS=15
-D TFT_DC=2
-D TFT_RST=-1
-D TFT_BL=21
-D LOAD_GLCD=1
-D LOAD_FONT2=1
-D LOAD_FONT4=1
-D LOAD_FONT6=1
-D LOAD_FONT7=1
-D LOAD_FONT8=1
-D LOAD_GFXFF=1
-D SPI_FREQUENCY=27000000
-D SPI_READ_FREQUENCY=20000000

lib_deps =
bblanchon/ArduinoJson @ ^6.21.3
lvgl/lvgl@^8.3.0
bodmer/TFT_eSPI@^2.5.43
ESP32WebServer
Preferences

Expand Down
7 changes: 5 additions & 2 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
#include <Arduino.h>

// Screen resolution
const uint16_t screenWidth = 240;
const uint16_t screenHeight = 320;
const uint16_t screenWidth = 320;
const uint16_t screenHeight = 240;

// Debug mode - set to true for verbose logging, false for quiet operation
bool debug_mode = false;

// Glances settings
String glances_host;
Expand Down
33 changes: 24 additions & 9 deletions src/display.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "display.h"
#include <Arduino.h>

#define TFT_BL 27
#define TFT_BL 21 // Correct backlight pin for CYD
#define TFT_BACKLIGHT_ON HIGH

TFT_eSPI tft = TFT_eSPI();
Expand All @@ -15,25 +15,40 @@ void init_display()
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);

tft.begin();
tft.setRotation(3);
tft.setRotation(3); // Landscape orientation
tft.initDMA();
tft.fillScreen(TFT_BLACK);

// Allocate display buffers
// Allocate display buffers - fix the width/height issue
extern const uint16_t screenHeight;
extern const uint16_t screenWidth;
buf1 = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenHeight * 10, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
buf2 = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenHeight * 10, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, screenHeight * 10);

// For landscape mode (rotation 3), actual dimensions are swapped
uint16_t buffer_width = screenWidth; // 240
uint16_t buffer_height = screenHeight; // 320

// Allocate buffers with proper size calculation
size_t buffer_size = buffer_width * 10; // 10 lines buffer
buf1 = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
buf2 = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);

if (buf1 == NULL || buf2 == NULL) {
Serial.println("Failed to allocate display buffers!");
return;
}

lv_disp_draw_buf_init(&draw_buf, buf1, buf2, buffer_size);

// Initialize display driver
// Initialize display driver with correct resolution
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = screenHeight;
disp_drv.ver_res = screenWidth;
disp_drv.hor_res = screenWidth; // 240
disp_drv.ver_res = screenHeight; // 320
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);

Serial.println("Display initialized successfully");
}

void display_sleep(bool sleep)
Expand Down
Loading