Example of a simple sensor panel for a Linux PC or laptop using an ESP32 microcontroller and an ST7889 TFT screen.
Current code assumes ESP32 serial mounts on /dev/ttyUSB0
, an AMD GPU(with rocm-smi
bash command available, on RHEL systems sudo dnf install rocm-smi
), and that CPU temp is labelled k10temp_tccd1
.
Wire up the ESP32 to a TFT screen using VSPI pins. If using different pins or TFT screen can modify the build flags in firmware/platformio.ini
. If using a different TFT screen may also need to modify include/lv_conf.h
see LVGL docs.
These are the default pins:
GND -> GND
VCC -> 3V3
SCL -> 18 (SCK) (VSPI_CLK)
SDA -> 23 (MOSI) (VSPI_MOSI)
RST -> 22
DC -> 16
CS -> 5
BL -> 5V (Backlight power)
...
build_flags =
-D USER_SETUP_LOADED=1
-D ST7789_DRIVER
-D LOAD_GLCD
-D TFT_WIDTH=240
-D TFT_HEIGHT=320
-D TFT_RST=22
-D TFT_CS=5
-D TFT_DC=21
-D TFT_MOSI=23
-D TFT_SCLK=18
-D TFT_RGB_ORDER=TFT_BGR
-D TFT_INVERSION_OFF
-I include
-D LV_CONF_INCLUDE_SIMPLE
An easy way to do this wiring is using dupont F-F wires like this, alternatively could use a breadboard and mount the TFT screen and ESP32 to it:
Connect the ESP32 with USB to the system which provides power and a serial bus to send the data over. If it's wired correctly the TFT backlight should light up.
Then flash firmware using platformio
:
# sudo chmod 777 /dev/ttyUSB0 # Required sometimes if group permissions not working
cd firmware/
platformio run -t upload
First need to Install Go. On RHEL/Fedora can do this with sudo dnf install go -y
.
Then once ESP32 connected and firmware flashed, to start sending system info:
cd application/controller
go build .
./controller
Output should look something like:
[main][~/dev/flux9-labs/linux_sensor_panel/application/controller]$ go build .
[main][~/dev/flux9-labs/linux_sensor_panel/application/controller]$ ./controller
Serial port opened successfully.
Sending system metrics data to ESP32...
Sent JSON data: {"cpu_usage":2.090301003344634,"cpu_temp":35.75,"ram_usage":17.702701944074867,"gpu_usage":8,"gpu_temp":41,"gpu_vram_usage":9}
Sent JSON data: {"cpu_usage":2.261306532697001,"cpu_temp":36.5,"ram_usage":17.69107151966567,"gpu_usage":8,"gpu_temp":41,"gpu_vram_usage":9}
Sent JSON data: {"cpu_usage":3.0226700251929177,"cpu_temp":37.25,"ram_usage":17.699297024441954,"gpu_usage":7,"gpu_temp":41,"gpu_vram_usage":9}
If everythings working will now have an external sensor panel, to make this look nicer could figure out how to place inside the case and 3D print a case or mount:
Current code is only designed for one Linux desktop I'm using on, the code is simple enough that its easily customizable though.
c := &serial.Config{Name: "/dev/ttyUSB0", Baud: ESP_BAUD, ReadTimeout: time.Second * 5}
s, err := serial.OpenPort(c)
...
cpuTemp := 0.0
gpuTemp := 0.0
for _, sensor := range sensorValues {
switch sensor.SensorKey {
case "k10temp_tccd1":
cpuTemp = sensor.Temperature
case "amdgpu_edge":
gpuTemp = sensor.Temperature
}
}
...
vramCmd := exec.Command("rocm-smi", "--showmemuse", "--json")
vramOutput, err := vramCmd.CombinedOutput()
The JSON object to send to the ESP32 firmware looks like this:
{
"cpu_usage":2.424749163887076,
"cpu_temp":35.5,
"ram_usage":17.292097925976805,
"gpu_usage":8,
"gpu_temp":34,
"gpu_vram_usage":10
}
So for cutomizing for different systems and you don't need to change the TFT screen output or add a new field, you only need to change the JSON object sent by the Go application under application/controller/main.go
.