PC Data to Arduino

I want to send some data from my PC to my Arduino using Serial.

This is my PC python code, which works.

import psutil
import serial
import time
import GPUtil

# Initialize the serial connection
arduino = serial.Serial('COM5', 9600)  # Replace 'COMX' with the correct COM port

while True:
    # Get CPU and RAM usage
    cpu_percent = psutil.cpu_percent()
    ram_percent = psutil.virtual_memory().percent

    # Get GPU temperature
    gpu_temperature = None
    try:
        # Assuming you have only one GPU. You can modify the code if you have multiple GPUs.
        gpu = GPUtil.getGPUs()[0]
        gpu_temperature = gpu.temperature
    except Exception as e:
        print(f"Error getting GPU temperature: {e}")

    # Format the data as a single string
    data = f"CPU: {cpu_percent:.2f}%\nRAM: {ram_percent:.2f}%\nGPU Temp: {gpu_temperature or 'N/A'}\n"

    # Send data to Arduino
    print("Sending data to Arduino: ", data)
    arduino.write(data.encode())

    # Delay to prevent flooding the Arduino
    time.sleep(1)

This is the Arduino code.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3f, 16, 2);  // Adjust the I2C address if needed

unsigned long lastDataReceivedTime = 0;
const unsigned long backlightTimeout = 10000;  // 10 seconds in milliseconds

// Define the pins for the RGB LED
const int redPin = 11;    // Red LED connected to digital pin 11
const int greenPin = 9;   // Green LED connected to digital pin 9
const int bluePin = 10;   // Blue LED connected to digital pin 10

// Duration for each color transition in milliseconds
const unsigned long transitionDuration = 1500; // 2 seconds per transition

unsigned long startTime = 0; // Time when the transition started
int startRed, startGreen, startBlue; // Starting color values
int endRed, endGreen, endBlue; // Ending color values

enum ColorTransitionState {
  RED_TO_GREEN,
  GREEN_TO_BLUE,
  BLUE_TO_RED
};

ColorTransitionState currentTransitionState = RED_TO_GREEN;
unsigned long transitionStartTime = 0;

String cpuUsage;
String ramUsage;
bool isCPURamDataReceived = false;

void setup() {
  // Initialize the RGB pins as OUTPUT
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  digitalWrite(redPin, HIGH);
  digitalWrite(greenPin, HIGH);
  digitalWrite(bluePin, HIGH);
  lcd.init();
  lcd.clear();
  Serial.begin(9600);
}

void loop() {
  ledloop();

  // Non-blocking Serial data reception
  while (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n') {
      processSerialData();
    } else {
      if (!isCPURamDataReceived) {
        // Append the characters to the CPU data string
        cpuUsage += c;
      } else {
        // Append the characters to the RAM data string
        ramUsage += c;
      }
    }
  }

  if (millis() - lastDataReceivedTime >= backlightTimeout) {
    lcd.noBacklight();  // Turn off the backlight
  } else {
    lcd.backlight();
  }
}

void processSerialData() {
  if (!isCPURamDataReceived) {
    // CPU data is received, switch to RAM data
    isCPURamDataReceived = true;
  } else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(cpuUsage);
    lcd.setCursor(0, 1);
    lcd.print(ramUsage);

    // Reset data variables
    cpuUsage = "";
    ramUsage = "";
    isCPURamDataReceived = false;
  }

  lastDataReceivedTime = millis();
}

void ledloop() {
  unsigned long currentTime = millis();

  if (currentTransitionState == RED_TO_GREEN &&
      currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = GREEN_TO_BLUE;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == GREEN_TO_BLUE &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = BLUE_TO_RED;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == BLUE_TO_RED &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = RED_TO_GREEN;
    transitionStartTime = currentTime;
  }

  switch (currentTransitionState) {
    case RED_TO_GREEN:
      startRed = 0; startGreen = 255; startBlue = 255;
      endRed = 255; endGreen = 0; endBlue = 255;
      break;
    case GREEN_TO_BLUE:
      startRed = 255; startGreen = 0; startBlue = 255;
      endRed = 255; endGreen = 255; endBlue = 0;
      break;
    case BLUE_TO_RED:
      startRed = 255; startGreen = 255; startBlue = 0;
      endRed = 0; endGreen = 255; endBlue = 255;
      break;
  }

  float progress = (currentTime - transitionStartTime) / (float)transitionDuration;
  int redValue = startRed + (endRed - startRed) * progress;
  int greenValue = startGreen + (endGreen - startGreen) * progress;
  int blueValue = startBlue + (endBlue - startBlue) * progress;

  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

It all works, I'm receiving CPU, RAM, and GPU data. However, instead of displaying the GPU data on the LCD, I want it on a bargraph.

So I tried this:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3f, 16, 2);  // Adjust the I2C address if needed

unsigned long lastDataReceivedTime = 0;
const unsigned long backlightTimeout = 10000;  // 10 seconds in milliseconds

const int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 13};  // Define the LED pins
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]);

// Define the pins for the RGB LED
const int redPin = 11;    // Red LED connected to digital pin 11
const int greenPin = 9;   // Green LED connected to digital pin 9
const int bluePin = 10;   // Blue LED connected to digital pin 10

// Duration for each color transition in milliseconds
const unsigned long transitionDuration = 1500; // 2 seconds per transition

unsigned long startTime = 0; // Time when the transition started
int startRed, startGreen, startBlue; // Starting color values
int endRed, endGreen, endBlue; // Ending color values

enum ColorTransitionState {
  RED_TO_GREEN,
  GREEN_TO_BLUE,
  BLUE_TO_RED
};

ColorTransitionState currentTransitionState = RED_TO_GREEN;
unsigned long transitionStartTime = 0;

String cpuUsage;
String ramUsage;
String gpuTemp;
bool isDataReceived = false;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  digitalWrite(redPin, HIGH);
  digitalWrite(greenPin, HIGH);
  digitalWrite(bluePin, HIGH);
  lcd.init();
  lcd.clear();
  Serial.begin(9600);

  // Set LED pins as OUTPUT
  for (int i = 0; i < numLeds; ++i) {
    pinMode(ledPins[i], OUTPUT);
  }
}

void loop() {
  ledloop();

  // Non-blocking Serial data reception
  while (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n') {
      processSerialData();
    } else {
      if (!isDataReceived) {
        // Append the characters to the CPU data string
        cpuUsage += c;
      } else {
        // Append the characters to the RAM data string
        ramUsage += c;
      }
    }
  }

  if (millis() - lastDataReceivedTime >= backlightTimeout) {
    lcd.noBacklight();  // Turn off the backlight
  } else {
    lcd.backlight();
  }

  displayGPUTemperatureBar();
}

void processSerialData() {
  if (!isDataReceived) {
    // CPU data is received, switch to RAM data
    isDataReceived = true;
  } else {
    // RAM data is received, switch to GPU data
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(cpuUsage);
    lcd.setCursor(0, 1);
    lcd.print(ramUsage);

    // Reset data variables
    cpuUsage = "";
    ramUsage = "";
    gpuTemp = "";

    isDataReceived = false;
  }

  lastDataReceivedTime = millis();
}

void displayGPUTemperatureBar() {
  if (isDataReceived) {
    int gpuTemperature = gpuTemp.toInt();
    int ledsToLight = map(gpuTemperature, 0, 100, 0, numLeds);

    // Turn on LEDs based on the GPU temperature
    for (int i = 0; i < numLeds; ++i) {
      if (i < ledsToLight) {
        digitalWrite(ledPins[i], HIGH);
      } else {
        digitalWrite(ledPins[i], LOW);
      }
    }
  }
}

void ledloop() {
  unsigned long currentTime = millis();

  if (currentTransitionState == RED_TO_GREEN &&
      currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = GREEN_TO_BLUE;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == GREEN_TO_BLUE &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = BLUE_TO_RED;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == BLUE_TO_RED &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = RED_TO_GREEN;
    transitionStartTime = currentTime;
  }

  switch (currentTransitionState) {
    case RED_TO_GREEN:
      startRed = 0; startGreen = 255; startBlue = 255;
      endRed = 255; endGreen = 0; endBlue = 255;
      break;
    case GREEN_TO_BLUE:
      startRed = 255; startGreen = 0; startBlue = 255;
      endRed = 255; endGreen = 255; endBlue = 0;
      break;
    case BLUE_TO_RED:
      startRed = 255; startGreen = 255; startBlue = 0;
      endRed = 0; endGreen = 255; endBlue = 255;
      break;
  }

  float progress = (currentTime - transitionStartTime) / (float)transitionDuration;
  int redValue = startRed + (endRed - startRed) * progress;
  int greenValue = startGreen + (endGreen - startGreen) * progress;
  int blueValue = startBlue + (endBlue - startBlue) * progress;

  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

But it still doesn't display on the bargraph, only the LCD.
What have I overlooked?

The LED bar displays gputemp.toInt(), but I could not find where you give gputemp a value.

Perhaps it is me who overlooked something

That would be from void loop...

void loop() {
  ledloop();

  // Non-blocking Serial data reception
  while (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n') {
      processSerialData();
    } else {
      if (!isDataReceived) {
        // Append the characters to the CPU data string
        cpuUsage += c;
      } else {
        // Append the characters to the RAM data string
        ramUsage += c;
      }
    }
  }

  if (millis() - lastDataReceivedTime >= backlightTimeout) {
    lcd.noBacklight();  // Turn off the backlight
  } else {
    lcd.backlight();
  }

  displayGPUTemperatureBar();
}

But how do you give it a value?

Tried this:
PC Code

import psutil
import serial
import time
import GPUtil

# Initialize the serial connection
arduino = serial.Serial('COM5', 9600)  # Replace 'COMX' with the correct COM port

while True:
    # Read a single character from the serial port
    data = arduino.read().decode('utf-8')

    # If the received character is 'C', retrieve and print CPU usage
    if data == 'C':
        # Get CPU usage
        cpu_percent = psutil.cpu_percent()
        print(f'CPU: {cpu_percent:.2f}%\n')
        cpuData = f"CPU: {cpu_percent:.2f}%\n"
        arduino.write(cpuData.encode())
        
    elif data == 'R':
        # Get RAM usage
        ram_percent = psutil.virtual_memory().percent
        print(f'RAM: {ram_percent:.2f}%\n') 
        ramData = f"RAM: {ram_percent:.2f}%\n"
        arduino.write(ramData.encode())
        
    elif data == 'R':
        # Get GPU temperature
        gpu_temperature = None
        try:
            # Assuming you have only one GPU. You can modify the code if you have multiple GPUs.
            gpu = GPUtil.getGPUs()[0]
            gpu_temperature = gpu.temperature
        except Exception as e:
            print(f"Error getting GPU temperature: {e}")   
        print(f'GPU: {gpu_temperature:.2f}%\n')
        gpuData = f"GPU: {gpu_temperature:.2f}%\n"
        arduino.write(gpuData.encode())

Arduino Code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3f, 16, 2);  // Adjust the I2C address if needed

unsigned long lastDataReceivedTime = 0;
unsigned long lastLoopTime = 0;
const unsigned long backlightTimeout = 10000;  // 10 seconds in milliseconds
const unsigned long loopTime = 1000;  // 1 second in milliseconds

const int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 13};  // Define the LED pins
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]);

// Define the pins for the RGB LED
const int redPin = 11;    // Red LED connected to digital pin 11
const int greenPin = 9;   // Green LED connected to digital pin 9
const int bluePin = 10;   // Blue LED connected to digital pin 10

// Duration for each color transition in milliseconds
const unsigned long transitionDuration = 1500; // 2 seconds per transition

unsigned long startTime = 0; // Time when the transition started
int startRed, startGreen, startBlue; // Starting color values
int endRed, endGreen, endBlue; // Ending color values

enum ColorTransitionState {
  RED_TO_GREEN,
  GREEN_TO_BLUE,
  BLUE_TO_RED
};

ColorTransitionState currentTransitionState = RED_TO_GREEN;
unsigned long transitionStartTime = 0;

String cpuUsage;
String ramUsage;
String gpuTemp;
bool isDataReceived = false;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  digitalWrite(redPin, HIGH);
  digitalWrite(greenPin, HIGH);
  digitalWrite(bluePin, HIGH);
  lcd.init();
  lcd.clear();
  Serial.begin(9600);

  // Set LED pins as OUTPUT
  for (int i = 0; i < numLeds; ++i) {
    pinMode(ledPins[i], OUTPUT);
  }
}

void loop() {
  ledloop();

  if (millis() - lastLoopTime >= loopTime) {
    // Non-blocking Serial data reception
    Serial.println("C");
    while (Serial.available() > 0) {
      char c = Serial.read();
      if (c == '\n') {
        processCpuData();
      } else {
        if (!isDataReceived) {
          // Append the characters to the CPU data string
          cpuUsage += c;
        }
      }
    }
    Serial.println("R");
    while (Serial.available() > 0) {
      char c = Serial.read();
      if (c == '\n') {
        processRamData();
      } else {
        if (!isDataReceived) {
          // Append the characters to the CPU data string
          ramUsage += c;
        }
      }
    }
    Serial.println("G");
    while (Serial.available() > 0) {
      char c = Serial.read();
      if (c == '\n') {
        processGpuData();
      } else {
        if (!isDataReceived) {
          // Append the characters to the CPU data string
          gpuTemp += c;
        }
      }
    }
  }

  if (millis() - lastDataReceivedTime >= backlightTimeout) {
    lcd.noBacklight();  // Turn off the backlight
  } else {
    lcd.backlight();
  }

  displayGPUTemperatureBar();
  lastLoopTime = millis();
}

void processCpuData() {
  if (!isDataReceived) {
    // CPU data is received
    isDataReceived = true;
  } else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(cpuUsage);

    // Reset data variables
    cpuUsage = "";

    isDataReceived = false;
  }

  lastDataReceivedTime = millis();
}

void processRamData() {
  if (!isDataReceived) {
    // RAM data is received
    isDataReceived = true;
  } else {
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print(ramUsage);

    // Reset data variables
    ramUsage = "";
    //    gpuTemp = "";

    isDataReceived = false;
  }

  lastDataReceivedTime = millis();
}

void processGpuData() {
  if (!isDataReceived) {
    // GPU data is received
    isDataReceived = true;
  } else {
    // Reset data variables
    gpuTemp = "";

    isDataReceived = false;
  }

  lastDataReceivedTime = millis();
}

void displayGPUTemperatureBar() {
  if (isDataReceived) {
    int gpuTemperature = gpuTemp.toInt();
    int ledsToLight = map(gpuTemperature, 0, 100, 0, numLeds);

    // Turn on LEDs based on the GPU temperature
    for (int i = 0; i < numLeds; ++i) {
      if (i < ledsToLight) {
        digitalWrite(ledPins[i], HIGH);
      } else {
        digitalWrite(ledPins[i], LOW);
      }
    }
  }
}

void ledloop() {
  unsigned long currentTime = millis();

  if (currentTransitionState == RED_TO_GREEN &&
      currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = GREEN_TO_BLUE;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == GREEN_TO_BLUE &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = BLUE_TO_RED;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == BLUE_TO_RED &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = RED_TO_GREEN;
    transitionStartTime = currentTime;
  }

  switch (currentTransitionState) {
    case RED_TO_GREEN:
      startRed = 0; startGreen = 255; startBlue = 255;
      endRed = 255; endGreen = 0; endBlue = 255;
      break;
    case GREEN_TO_BLUE:
      startRed = 255; startGreen = 0; startBlue = 255;
      endRed = 255; endGreen = 255; endBlue = 0;
      break;
    case BLUE_TO_RED:
      startRed = 255; startGreen = 255; startBlue = 0;
      endRed = 0; endGreen = 255; endBlue = 255;
      break;
  }

  float progress = (currentTime - transitionStartTime) / (float)transitionDuration;
  int redValue = startRed + (endRed - startRed) * progress;
  int greenValue = startGreen + (endGreen - startGreen) * progress;
  int blueValue = startBlue + (endBlue - startBlue) * progress;

  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

RGB led still works smoothly, everything seems ok, however the LCD never displays anything.

Shouldn't this elif be 'G' not 'R'?

1 Like

I did notice that, but it made no difference.

I tried this:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3f, 16, 2);  // Adjust the I2C address if needed

String cpuUsage;
String ramUsage;
String gpuTemp;
bool isDataReceived = false;

void setup() {
  lcd.init();
  lcd.clear();
  Serial.begin(9600);
}

void loop() {
  // Non-blocking Serial data reception
  Serial.println("C");
  while (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n') {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(cpuUsage);
      cpuUsage = "";
    } else {
      if (!isDataReceived) {
        // Append the characters to the CPU data string
        cpuUsage += c;
      }
    }
  }
  delay(500);
}

It works, 100%!
But if I replace loop with this, it does not work AT ALL!

void loop() {
  // Non-blocking Serial data reception
  Serial.println("R");
  while (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n') {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(ramUsage);
      ramUsage = "";
    } else {
      if (!isDataReceived) {
        // Append the characters to the CPU data string
        ramUsage += c;
      }
    }
  }
  delay(500);
}

Does the python code from post one work correctly with RAM and CPU?

1 Like

What output do you get with this code in the Arduino monitor?

When I have the python code running, I am not able to run the Serial monitor. If the python code isn't running, I get C printed

Yes. Flawlessly.

maybe something like this..

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3f, 16, 2);  // Adjust the I2C address if needed

unsigned long lastDataReceivedTime = 0;
const unsigned long backlightTimeout = 10000;  // 10 seconds in milliseconds

// Define the pins for the RGB LED
const int redPin = 11;    // Red LED connected to digital pin 11
const int greenPin = 9;   // Green LED connected to digital pin 9
const int bluePin = 10;   // Blue LED connected to digital pin 10

// Duration for each color transition in milliseconds
const unsigned long transitionDuration = 1500; // 2 seconds per transition

unsigned long startTime = 0; // Time when the transition started
int startRed, startGreen, startBlue; // Starting color values
int endRed, endGreen, endBlue; // Ending color values

enum ColorTransitionState {
  RED_TO_GREEN,
  GREEN_TO_BLUE,
  BLUE_TO_RED
};

ColorTransitionState currentTransitionState = RED_TO_GREEN;
unsigned long transitionStartTime = 0;


char cpuUsage[20];
char ramUsage[20];
char gpuUsage[20];
byte recvCount = 0;
byte paramCount = 0;


void setup() {
  // Initialize the RGB pins as OUTPUT
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  digitalWrite(redPin, HIGH);
  digitalWrite(greenPin, HIGH);
  digitalWrite(bluePin, HIGH);
  lcd.init();
  lcd.clear();
  Serial.begin(9600);
  Serial.println("Ready..");
}

void loop() {
  ledloop();

  // Non-blocking Serial data reception
  if (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n') {
      recvCount = 0;
      paramCount++;
      if (paramCount > 2) {
        processSerialData();
        memset(cpuUsage, 0, sizeof(cpuUsage));
        memset(ramUsage, 0, sizeof(cpuUsage));
        memset(gpuUsage, 0, sizeof(cpuUsage));
      }

    } else {
      switch (paramCount) {
        case 0: cpuUsage[recvCount] = c;
          recvCount++;
          break;
        case 1: ramUsage[recvCount] = c;
          recvCount++;
          break;
        case 2: gpuUsage[recvCount] = c;
          recvCount++;
          break;
      }
    }
  }

  if (millis() - lastDataReceivedTime >= backlightTimeout) {
    lcd.noBacklight();  // Turn off the backlight
  } else {
    lcd.backlight();
  }
}

void processSerialData() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(cpuUsage);
  lcd.setCursor(0, 1);
  lcd.print(ramUsage);
  lastDataReceivedTime = millis();
}

void ledloop() {
  unsigned long currentTime = millis();

  if (currentTransitionState == RED_TO_GREEN &&
      currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = GREEN_TO_BLUE;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == GREEN_TO_BLUE &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = BLUE_TO_RED;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == BLUE_TO_RED &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = RED_TO_GREEN;
    transitionStartTime = currentTime;
  }

  switch (currentTransitionState) {
    case RED_TO_GREEN:
      startRed = 0; startGreen = 255; startBlue = 255;
      endRed = 255; endGreen = 0; endBlue = 255;
      break;
    case GREEN_TO_BLUE:
      startRed = 255; startGreen = 0; startBlue = 255;
      endRed = 255; endGreen = 255; endBlue = 0;
      break;
    case BLUE_TO_RED:
      startRed = 255; startGreen = 255; startBlue = 0;
      endRed = 0; endGreen = 255; endBlue = 255;
      break;
  }

  float progress = (currentTime - transitionStartTime) / (float)transitionDuration;
  int redValue = startRed + (endRed - startRed) * progress;
  int greenValue = startGreen + (endGreen - startGreen) * progress;
  int blueValue = startBlue + (endBlue - startBlue) * progress;

  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

used the first code posted, so doesn't do anything with gpu but gets it..
also used fixed char arrays for incoming data..

hope this helps.. ~q

1 Like

this should add the gpu temp led graph..

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3f, 16, 2);  // Adjust the I2C address if needed

unsigned long lastDataReceivedTime = 0;
const unsigned long backlightTimeout = 10000;  // 10 seconds in milliseconds


const int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 13};  // Define the LED pins
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]);


// Define the pins for the RGB LED
const int redPin = 11;    // Red LED connected to digital pin 11
const int greenPin = 9;   // Green LED connected to digital pin 9
const int bluePin = 10;   // Blue LED connected to digital pin 10

// Duration for each color transition in milliseconds
const unsigned long transitionDuration = 1500; // 2 seconds per transition

unsigned long startTime = 0; // Time when the transition started
int startRed, startGreen, startBlue; // Starting color values
int endRed, endGreen, endBlue; // Ending color values

enum ColorTransitionState {
  RED_TO_GREEN,
  GREEN_TO_BLUE,
  BLUE_TO_RED
};

ColorTransitionState currentTransitionState = RED_TO_GREEN;
unsigned long transitionStartTime = 0;


char cpuUsage[20];
char ramUsage[20];
char gpuTemp[20];
byte recvCount = 0;
byte paramCount = 0;


void setup() {
  // Initialize the RGB pins as OUTPUT
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  digitalWrite(redPin, HIGH);
  digitalWrite(greenPin, HIGH);
  digitalWrite(bluePin, HIGH);
  lcd.init();
  lcd.clear();
  Serial.begin(9600);
  Serial.println("Ready..");


  // Set LED pins as OUTPUT
  for (int i = 0; i < numLeds; ++i) {
    pinMode(ledPins[i], OUTPUT);
  }

}

void loop() {
  ledloop();

  // Non-blocking Serial data reception
  if (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '\n') {
      recvCount = 0;
      paramCount++;
      if (paramCount > 2) {
        processSerialData();
        memset(cpuUsage, 0, sizeof(cpuUsage));
        memset(ramUsage, 0, sizeof(cpuUsage));
        memset(gpuTemp, 0, sizeof(cpuUsage));
      }

    } else {
      if (recvCount>=sizeof(cpuUsage)) recvCount = 0;//why!!??
      switch (paramCount) {
        case 0: cpuUsage[recvCount] = c;
          recvCount++;
          break;
        case 1: ramUsage[recvCount] = c;
          recvCount++;
          break;
        case 2: gpuTemp[recvCount] = c;
          recvCount++;
          break;
      }
    }
  }

  if (millis() - lastDataReceivedTime >= backlightTimeout) {
    lcd.noBacklight();  // Turn off the backlight
  } else {
    lcd.backlight();
  }
}

void processSerialData() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(cpuUsage);
  lcd.setCursor(0, 1);
  lcd.print(ramUsage);
  lastDataReceivedTime = millis();
  displayGPUTemperatureBar();
}


void displayGPUTemperatureBar() {

    int gpuTemperature = ParseGPU(gpuTemp);
    int ledsToLight = map(gpuTemperature, 0, 100, 0, numLeds);

    // Turn on LEDs based on the GPU temperature
    for (int i = 0; i < numLeds; ++i) {
      if (i < ledsToLight) {
        digitalWrite(ledPins[i], HIGH);
      } else {
        digitalWrite(ledPins[i], LOW);
      }
  }

}


int ParseGPU(char* abuff) {

  int returnVal = -1;
  int splits = 0;
  char* str;
  char* value;
  for ( char* piece = strtok( abuff, ":");
        piece != nullptr;
        piece = strtok( nullptr, ":")) {
    if (splits == 0) {
      str = piece;
      splits++;
    } else if (splits == 1) {
      value = piece;
      splits++;
    }
  }
  //convert and store our value
  if (value != nullptr) {
    returnVal = atoi(value);
  }
    return returnVal;
}




void ledloop() {
  unsigned long currentTime = millis();

  if (currentTransitionState == RED_TO_GREEN &&
      currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = GREEN_TO_BLUE;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == GREEN_TO_BLUE &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = BLUE_TO_RED;
    transitionStartTime = currentTime;
  } else if (currentTransitionState == BLUE_TO_RED &&
             currentTime - transitionStartTime >= transitionDuration) {
    currentTransitionState = RED_TO_GREEN;
    transitionStartTime = currentTime;
  }

  switch (currentTransitionState) {
    case RED_TO_GREEN:
      startRed = 0; startGreen = 255; startBlue = 255;
      endRed = 255; endGreen = 0; endBlue = 255;
      break;
    case GREEN_TO_BLUE:
      startRed = 255; startGreen = 0; startBlue = 255;
      endRed = 255; endGreen = 255; endBlue = 0;
      break;
    case BLUE_TO_RED:
      startRed = 255; startGreen = 255; startBlue = 0;
      endRed = 0; endGreen = 255; endBlue = 255;
      break;
  }

  float progress = (currentTime - transitionStartTime) / (float)transitionDuration;
  int redValue = startRed + (endRed - startRed) * progress;
  int greenValue = startGreen + (endGreen - startGreen) * progress;
  int blueValue = startBlue + (endBlue - startBlue) * progress;

  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

fun.. ~q

1 Like

That does not work with the Python code, I'm assuming I need to rewrite the python.

import psutil
import serial
import time
import GPUtil

# Initialize the serial connection
arduino = serial.Serial('COM3', 9600)  # Replace 'COMX' with the correct COM port

while True:
    # Read a single character from the serial port
    data = arduino.read().decode('utf-8')

    # If the received character is 'C', retrieve and print CPU usage
    if data == 'C':
        # Get CPU usage
        cpu_percent = psutil.cpu_percent()
        print(f"CPU: {cpu_percent:.2f}%\n")
        cpuData = f"CPU: {cpu_percent:.2f}%\n"
        arduino.write(cpuData.encode())
        
    elif data == 'R':
        # Get RAM usage
        ram_percent = psutil.virtual_memory().percent
        print(f"RAM: {ram_percent:.2f}%\n") 
        ramData = f"RAM: {ram_percent:.2f}%\n"
        arduino.write(ramData.encode())
        
    elif data == 'G':
        # Get GPU temperature
        gpu_temperature = None
        try:
            # Assuming you have only one GPU. You can modify the code if you have multiple GPUs.
            gpu = GPUtil.getGPUs()[0]
            gpu_temperature = gpu.temperature
        except Exception as e:
            print(f"Error getting GPU temperature: {e}")   
        print(f"GPU: {gpu_temperature:.2f}\n")
        gpuData = f"GPU: {gpu_temperature:.2f}\n"
        arduino.write(gpuData.encode())