with an ESP32 and an SSD1306 OLED display.
Since microcontrollers cannot read PC data natively through a standard USB port, you need a simple script on the computer to read the performance stats and stream them over the USB cord to the ESP32.
Step 1: The Concept & Communication
The architecture for this setup relies on a clean python stream:
- On the PC: A lightweight Python script runs in the background. It reads CPU, GPU, and Laptop Battery status using standard Python libraries, bundles the data into a text string, and shoots it down the USB Serial port (COM port) once every second.
- On the ESP32: The ESP32 stays plugged into a computer USB port. It listens to its
Serialbuffer, breaks the text string apart, and paints the layout onto the OLED screen.
Step 2: The PC Side (Python Script)
You will need to install two libraries on your computer via your command prompt/terminal:
bash
pip install psutil pyserial GPUtilCreate a file named
pc_stats.py and run it on your computer while your ESP32 is plugged in. Make sure to change "COM3" to whatever port your ESP32 is using.python
import time
import psutil
import serial
import GPUtil
# Configure this to match your ESP32's COM port
SERIAL_PORT = "COM3"
BAUD_RATE = 115200
try:
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
print(f"Streaming data to {SERIAL_PORT}...")
except Exception as e:
print(f"Error opening port: {e}")
exit()
while True:
try:
# 1. Get CPU Usage
cpu = int(psutil.cpu_percent())
# 2. Get GPU Usage (Accounts for integrated vs dedicated cards)
gpus = GPUtil.getGPUs()
gpu = int(gpus[0].load * 100) if gpus else 0
# 3. Get Battery Stats
battery = psutil.sensors_battery()
bat_percent = int(battery.percent) if battery else 100
is_charging = 1 if (battery and battery.power_plugged) else 0
# Package data into a clean comma-separated string: "CPU,GPU,BAT,CHARGING"
# Example: "42,65,80,1"
data_packet = f"{cpu},{gpu},{bat_percent},{is_charging}\n"
# Send data across the USB cable
ser.write(data_packet.encode('utf-8'))
time.sleep(1) # Send update once per second
except KeyboardInterrupt:
ser.close()
break
except Exception as e:
print(f"Connection lost: {e}")
time.sleep(2)Step 3: The ESP32 Code
This code handles parsing the text coming from the PC and formatting it onto your screen. Connect your SSD1306 display's SCL to GPIO 22 and SDA to GPIO 21.
cpp
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
// Start serial communications at the same speed as the python script
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 25);
display.println("Waiting for PC...");
display.display();
}
void loop() {
// Check if the Python script has pushed a new data packet down the wire
if (Serial.available() > 0) {
String inputData = Serial.readStringUntil('\n');
// Parse the comma-separated string back into distinct data pieces
int firstComma = inputData.indexOf(',');
int secondComma = inputData.indexOf(',', firstComma + 1);
int thirdComma = inputData.indexOf(',', secondComma + 1);
if (firstComma != -1 && secondComma != -1 && thirdComma != -1) {
String cpuStr = inputData.substring(0, firstComma);
String gpuStr = inputData.substring(firstComma + 1, secondComma);
String batStr = inputData.substring(secondComma + 1, thirdComma);
String chargeStr = inputData.substring(thirdComma + 1);
// Update screen layout
display.clearDisplay();
// Header
display.setCursor(20, 0);
display.println("SYSTEM MONITOR");
display.println("---------------------");
// CPU Metrics
display.setCursor(0, 20);
display.print("CPU Usage: "); display.print(cpuStr); display.println("%");
// GPU Metrics
display.setCursor(0, 34);
display.print("GPU Usage: "); display.print(gpuStr); display.println("%");
// Laptop Battery Metrics
display.setCursor(0, 48);
display.print("Battery: "); display.print(batStr); display.print("%");
if(chargeStr.toInt() == 1) {
display.print(" [ + ]"); // Show charging icon indicator
}
display.display();
}
}
}
No comments:
Post a Comment