---
title: 'PC Dashboard with Gauges'
tags: Hardware, Software, Cars
---
> [color=#b294bb][time=Sun, Nov 17, 2024 10:22 PM]
> _2 Minute read_
# PC Dashboard with Custom Gauges :stopwatch:
**Concept:** A car inspired dashboard that merges **analog gauges**, **flick levers** and **real time PC metrics** into a sleek, interactive experience
## Features :key:
### Interactive Controls
- **Flick Levers:** Activate specific gauges to display metrics
- **Start Button:** Power on with a racing-style push button
### Custom Gauges
- Displays system metrics: temperatures, fan RPM, workload, etc
- Analog needles mimic tachometer sweep on startup, idling after 30 seconds
### Monitor Integration
- Custom brackets mount gauges on the top or sides of the monitor
## Hardware & Software :floppy_disk:
### Hardware
- **Switches:** Flick levers and push a button for controls
- **Analog Gauges:** Servo driven precision
- **Mounts:** Secure gauge placement on the monitor
### Software
- **Python:** Captures system stats using the WMI & psutil libraries
- **Microcontroller:** Arduino or Raspberry Pi for servo and gauge control
## System Overview :desktop_computer:
_WIP_
<!-- Add graph here -->
## Installation :gear:
### Prerequisites
1. Install [Open Hardware Monitor](https://openhardwaremonitor.org/downloads/) and leave it running in the background
2. Dependencies
```bash
pip install WMI psutil
```
### Example Code Snippet
```python
import time
import wmi
import os
import psutil
def clear():
os.system('cls' if os.name == 'nt' else 'clear')
def is_hwmonitor_running():
"""check if openhardwaremonitor is running"""
for proc in psutil.process_iter(['pid', 'name']):
if 'OpenHardwareMonitor' in proc.info['name']:
return True
return False
def get_hardware():
"""fetch temps, fan rpm (no aio), utilization, & mem usage from wmi"""
try:
w = wmi.WMI(namespace="root\\OpenHardwareMonitor")
temperature_infos = w.Sensor()
cpu_temp = None
gpu_temp = None
cpu_load = None
gpu_load = None
mem_usage = None
fan_rpm = []
for sensor in temperature_infos:
# cpu temp
if sensor.SensorType == u'Temperature' and 'CPU' in sensor.Name:
cpu_temp = sensor.Value
# gpu temp
if sensor.SensorType == u'Temperature' and 'GPU' in sensor.Name:
gpu_temp = sensor.Value
# cpu load
if sensor.SensorType == u'Load' and 'CPU' in sensor.Name:
cpu_load = sensor.Value
# gpu encode
if sensor.SensorType == u'Load' and 'GPU Video Engine' in sensor.Name:
gpu_load = sensor.Value
# get memory from psutil
mem_usage = psutil.virtual_memory().percent
# fan rpm (collect all fans)
if sensor.SensorType == u'Fan' and 'Fan' in sensor.Name:
fan_rpm.append(sensor.Value)
return cpu_temp, gpu_temp, cpu_load, gpu_load, fan_rpm, mem_usage
except Exception as e:
print(f"Error fetching info: {e}")
return None, None, None, None, None, None
def display_info(cpu_temp, gpu_temp, cpu_utilization, gpu_load, fan_rpm, mem_usage):
clear()
header_width = 15
value_width = 10
print(f"{'System Metrics':^{header_width*2}}")
print("=" * (header_width * 2))
# cpu temp
print(f"{'CPU Temp:':<{header_width}} {round(cpu_temp, 2) if cpu_temp is not None else 'n/a':>{value_width}} °C")
# gpu temp
print(f"{'GPU Temp:':<{header_width}} {round(gpu_temp, 2) if gpu_temp is not None else 'n/a':>{value_width}} °C")
# cpu util
print(f"{'CPU Util:':<{header_width}} {round(cpu_utilization, 2) if cpu_utilization is not None else 'n/a':>{value_width}} %")
# gpu load
print(f"{'GPU Load:':<{header_width}} {round(gpu_load, 2) if gpu_load is not None else 'n/a':>{value_width}} %")
# mem usage
print(f"{'Memory Usage:':<{header_width}} {round(mem_usage, 2):>{value_width}} %")
print("-" * (header_width * 2))
# fan rpm
if fan_rpm:
for i, rpm in enumerate(fan_rpm, 1):
print(f"{f'Fan {i} RPM:':<{header_width}} {int(rpm) if rpm is not None else 'n/a':>{value_width}} RPM")
else:
print(f"{'Fan RPM:':<{header_width}} {'N/A':>{value_width}}")
print("=" * (header_width * 2))
def main():
# check if openhardwaremonitor is running
if not is_hwmonitor_running():
print("OpenHardwareMonitor not detected...")
input("Press enter to exit & relaunch")
return
while True:
# fetch metrics
cpu_temp, gpu_temp, cpu_load, gpu_load, mem_usage, fan_rpm = get_hardware()
# display the information
display_info(cpu_temp, gpu_temp, cpu_load, gpu_load, mem_usage, fan_rpm)
time.sleep(1.5)
if __name__ == "__main__":
main()
```
# For the future :pushpin:
### To-Do
- #### **Design Blueprints**
- [ ] Create detailed schematics for gauges
- [ ] Use the university workshop or find templates online
- #### **Capture System Metrics**
- [x] Write a Python script to capture metrics
- [ ] Integrate AIO metric tracking
- #### **Gauge Mounting**
- [ ] Design secure mounts for gauges
- [ ] Fabricate at the university workshop or buy online
- #### **Hardware Integration**
- [ ] Connect and calibrate gauges, levers, and controllers
- [ ] Test synchronization between hardware and software
## Inspo & Ideas :sparkles:
### Dashboard
<div style="position: relative; display: inline-block; text-align: center; margin-bottom: 20px;">
<img src="https://i.pinimg.com/736x/83/dc/88/83dc88afe591e13e491afa2fbae8a5dd.jpg"
alt="Dashboard with levers"
style="width: 300px; border-radius: 12px; box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.25);">
<div style="position: absolute; top: 10px; left: 0; width: 100%; color: white; font-family: Inter, sans-serif; font-size: 20px; font-weight: bold; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.6);"></div>
</div>
### Gauges for Reference
<div style="position: relative; display: inline-block; text-align: center; margin-bottom: 20px;">
<img src="https://i.pinimg.com/736x/3b/28/26/3b2826ea9c8f06672231c0f952630141.jpg"
alt="Gauges for Reference"
style="width: 300px; border-radius: 12px; box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.25);">
<div style="position: absolute; top: 10px; left: 0; width: 100%; color: white; font-family: Inter, sans-serif; font-size: 20px; font-weight: bold; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.6);"></div>
</div>
### Videos
- [DIY Analog Dashboard](https://www.youtube.com/watch?v=E0ifN2cTgvg) | Cheers to @suppeforpresident
- [Custom PC with tachometer](https://youtu.be/wAEmknxCAe8) | Cheers to @salmon1g