Vamos a programar #98 - Ver el rendimiento del PC usando arduino y C#.
Hola de nuevo a todos, el día de hoy vamos a ver cómo ver el rendimiento del PC usando C# y arduino.
En el post anterior vimos una versión beta de un programa que sirve para monitorear cual es el rendimiento del PC, y si bien ya era algo funcional, le he hecho algunas mejoras para que resulte más fácil de leer.
El código está conformado por dos partes, la primera, un programa en C# para windows que se encarga de obtener la información de cual es la carga del CPU en porcentaje, pero además de la RAM también en porcentaje, luego esa información la envía a un puerto al cual conectamos un arduino. La segunda parte consiste en un arduino que toma la información que recibió del programa y la muestra.
El programa en C#
using System; using System.Windows.Forms; using System.IO.Ports; namespace CPUMeterToArduino { public partial class Form1 : Form { System.Diagnostics.PerformanceCounter CPULoad; System.Diagnostics.PerformanceCounter RAMInUse; System.Diagnostics.PerformanceCounter AvailableRAM; private SerialPort Port = new SerialPort(); private void ArduinoMessage(string Message) { try { Port.Write(Message); } catch (Exception e) { MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { string DATA = string.Concat(((int)CPULoad.NextValue()).ToString("D3") , "," , PercentRAM(RAMInUse.NextValue() , AvailableRAM.NextValue()).ToString("D3") , "\0"); SerialPort sp = (SerialPort)sender; string indata = sp.ReadExisting(); if (indata.Contains("\r\n")) { //ArduinoMessage("100,050\0"); ArduinoMessage(DATA); } } Timer TimerMain; private int PercentRAM(float InUse, float Available) { if (Available == 0) return 100; else { float RamMBInUse = (InUse / 1024 / 1024); float TotalRam = RamMBInUse + Available; float Percent = ((RamMBInUse / TotalRam) * 100); return (int)Percent; } } public Form1() { InitializeComponent(); } private void Form1_Load(object sender, System.EventArgs e) { RAMInUse = new System.Diagnostics.PerformanceCounter("Memory", "Committed Bytes"); AvailableRAM = new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes"); CPULoad = new System.Diagnostics.PerformanceCounter("Processor", "% Processor Time", "_Total"); TimerMain = new Timer(); TimerMain.Interval = 1000; TimerMain.Enabled = true; TimerMain.Tick += new System.EventHandler(TimerMain_Tick); string[] Ports = SerialPort.GetPortNames(); cboportname.Items.AddRange(Ports); cboportname.Text = "COM3"; Port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); TSSLbl.Text = Port.IsOpen ? "Conectado" : "No conectado"; } private void TimerMain_Tick(object sender, EventArgs e) { PBCPUUsage.Value = (int)CPULoad.NextValue(); int PR = PercentRAM(RAMInUse.NextValue(), AvailableRAM.NextValue()); PBRAMUsage.Value = PR; this.Text = "Uso de RAM " + PR + "%" + " | CPU: " + PBCPUUsage.Value; ; NTFYMain.Text = "Uso de RAM " + PR + "%"; TSSLbl.Text = Port.IsOpen ? "Conectado con " + Port.PortName : "No conectado"; } private void Form1_Resize(object sender, EventArgs e) { if (this.WindowState == FormWindowState.Minimized) { Hide(); NTFYMain.Visible = true; } } private void NTFYMain_MouseDoubleClick(object sender, MouseEventArgs e) { Show(); this.WindowState = FormWindowState.Normal; NTFYMain.Visible = false; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (Port.IsOpen == true) { Port.Close(); } NTFYMain.Visible = false; } private void BtnConnect_Click(object sender, EventArgs e) { try { if (Port.IsOpen == false) { Port.BaudRate = 9600; Port.PortName = cboportname.Text; Port.Open(); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void BtnDis_Click(object sender, EventArgs e) { if (Port.IsOpen == true) { Port.Write("Se ha desconectado el cliente\0"); Port.Close(); } } private void TSMIRestore_Click(object sender, EventArgs e) { NTFYMain_MouseDoubleClick(null, null); } private void TSMIExit_Click(object sender, EventArgs e) { Application.Exit(); } } }
El código para arduino.
#include <Wire.h> #include <LiquidCrystal_I2C.h> //SCL - A5 //SDA - A4 LiquidCrystal_I2C lcd(0x27,20,4); char Texto[80]; char BuffCPU[20]; char BuffRAM[20]; byte BarBeginEmpty[] = { B11111, B10000, B10000, B10000, B10000, B10000, B10000, B11111 }; byte BarBeginFull[] = { B11111, B10000, B10111, B10111, B10111, B10111, B10000, B11111 }; byte BarSegmentFull[] = { B11111, B00000, B11111, B11111, B11111, B11111, B00000, B11111 }; byte BarSegmentEmpty[] = { B11111, B00000, B00000, B00000, B00000, B00000, B00000, B11111 }; byte BarEndEmpty[] = { B11111, B00001, B00001, B00001, B00001, B00001, B00001, B11111 }; byte BarEndFull[] = { B11111, B00001, B11101, B11101, B11101, B11101, B00001, B11111 }; void setup() { lcd.init(); lcd.createChar(0 , BarBeginEmpty); lcd.createChar(1 , BarBeginFull); lcd.createChar(2 , BarEndEmpty); lcd.createChar(3 , BarEndFull); lcd.createChar(4 , BarSegmentEmpty); lcd.createChar(5 , BarSegmentFull); lcd.backlight(); Serial.begin(9600); } void DrawProgressBar(uint8_t Value, uint8_t XLocation, uint8_t YLocation){ uint8_t Progress = map(Value , 1 , 100 , 0 , 20); lcd.setCursor(XLocation , YLocation); for (uint8_t i = 0; i < 20; i++) { if (i == 0) { if (Progress == 0) lcd.write(0); else lcd.write(1); } else if (i == 19) { if (Progress == 20) lcd.write(3); else lcd.write(2); } else { if (Progress <= i) lcd.write(4); else lcd.write(5); } } } void loop() { int i = 0; if (Serial.available()) { while (Serial.available() > 0) { Texto[i] = Serial.read(); i++; } Texto[i] = '\0'; } String Text(Texto); int X = Text.substring(0 , 3).toInt(); int Y = Text.substring(5 , 7).toInt(); lcd.setCursor(0 , 0); //lcd.print(Texto); sprintf(BuffCPU , "CPU: %03d", X); sprintf(BuffRAM , "RAM: %03d", Y); lcd.print(BuffCPU); lcd.setCursor(0,2); lcd.print(BuffRAM); DrawProgressBar(X , 0 , 1); DrawProgressBar(Y , 0 , 3); Serial.println("\r\n"); delay(500); }
Para empezar, creamos seis "sprites" que corresponden a los segmentos de la barra de progreso "BarBeginEmpty", "BarBeginFull", "BarSegmentFull", "BarSegmentEmpty", "BarEndEmpty" y "BarEndEmpty", aunque sus nombres pueden resultar auto-explanatorios para algunos, cada uno define cada estado para las diferentes partes de la barra de progreso. Cada uno de los segmentos de la pantalla están conformados por una matriz de 5x8, entonces (y por ahora no entrare en detalles) creamos un array de esa dimensión y para simplificarlo, podemos aprovechar que arduino acepta numero en binario siempre y cuando vayan precedidos por el prefijo "B", ahora observemos la siguiente imagen:
Está es la definición de "BarBeginFull" |
Podemos observar que para formar el sprite, simplemente debemos de decidir si queremos o no usar cada cuadrado de la matriz. Si nos fijamos bien en la imagen, "BarBeginFull" es: "B11111,B10000,B10111,B10111,B10111,B10111,B10000,B11111"
Por lo tanto podemos usar una tabla e iluminar las celdas para formar el sprite que queramos.
Definición de "BarSegmentFull" |
Definición de "BarSegmentEmpty" |
No hay comentarios.