---
# System prepended metadata

title: PC Dashboard with Gauges
tags: [' Software', ' Cars', Hardware]

---

---
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

&nbsp;

## 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

&nbsp;

## 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

&nbsp;

## System Overview :desktop_computer:


_WIP_
<!-- Add graph here -->

&nbsp;

## 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()
```

&nbsp;

# 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

&nbsp;

## 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>

&nbsp;

### 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>

&nbsp;

### 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