Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9703

ArduinoとC#でパソコンのCPU使用率を7SegLEDに表示してみた

$
0
0
はじめに 今回は夏休みの自由研究と称して 7SegLEDにCPU使用率を表示してみたいと思います FPS(主にApex)にはまっている自分がぱっと見でCPU使用率を把握して ゲームでカクついているときに何が悪いのかをあたりを付けるという意味で作成しました 目次 実現したいこと 準備するもの 回路の設計 C#側プログラミング Arduino側プログラミング 完成 参考にしたサイト 実現したいこと 7segLEDに現在のCPU使用率を1秒おきに転送し、表示すること 完成したものはこちらです 夏休みの自由研究Arduino uno + C#でCPU使用率を7セグLEDに表示してみたマルチスレッドとかSerial.readStringの仕様とかいろいろ学ぶところあったので後日qiitaに投稿しようかな pic.twitter.com/99eoPnAssx— uechan (@uechang16) August 5, 2021 CPU-Zで負荷をかけるとそれに応じてタスクマネージャと一緒に7SegLEDの表示が変わっていることがわかると思います 準備するもの Arduino Uno ブレッドボードおよびジャンパ線(回路試作のため) 7SegLEDと4.7kΩ炭素被膜抵抗 ArduinoにつなげるUSBケーブル ブレッドボードは回路の試作のためなので いつかユニバーサル基盤に実装したいと思います 回路の設計 まずは表示を担う7SegLEDの回路を設計します 今回使う7SegLEDは秋月電子通商で買えるこちらにしました ダイナミック接続4桁赤色7セグメントLED表示器です こいつのデータシートを見るとアノードコモンでダイナミック接続との記載があるので アノード側の表示させたい桁に5Vをかけ カソード側で表示する数字に対応する部分を出力する方式で行きます 回路図は デジタル10番ピンからからデジタル11番ピンまでがアノードで5Vをかけること デジタル2番ピンからデジタル9番ピンまでは表示したい部分をLOWにすることで表示、 HIGHにすることで非表示という制御になりますので4.7kΩでプルダウンしてあります 例えば デジタル10番ピンがHIGHの時にデジタル3番ピン,4番ピンにLOW 残りの2,5,6,7,8,9番ピンにHIGHがかかっていると7SegLEDの一桁目に「1」が表示されます 回路図をもとにブレッドボードに配線を行っていきます ぐちゃぐちゃですがこんな感じ C#側プログラム C#(PC)側はCPUの使用率を取得し、シリアル経由でArduinoの文字列として送信する役割を持ちます Arduinoとの通信はSerialPortで行います シリアルポート探索 private void AnalyzeComPort() { string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { comboBox1.Items.Add(port); } } シリアルポートの利用可能なものを列挙して 選択式のコンボボックスに格納しています シリアル通信開始/終了 private void button1_Click(object sender, EventArgs e) { if (button1.Text == "Connect") { serialPort1.PortName = comboBox1.SelectedItem.ToString(); // 選択されたCOMをポート名に設定 serialPort1.Open(); // ポートを開く button1.Text = "Disconnect"; } else { serialPort1.Close(); button1.Text = "Connect"; } } ボタンが押されるとコンボボックスで選択されたCOMポート名を指定して serialPort1.Open()で通信開始 serialPort1.Close()で切断しています CPU使用率取得 public void getCPUUsege() { var cpuUsage = new PerformanceCounter("Processor", "% Processor Time", "_Total"); Thread.Sleep(1000); var firstCall = cpuUsage.NextValue(); while(true) { Thread.Sleep(1000); CPUperStr = cpuUsage.NextValue().ToString(); label3.Text = "Now:" + CPUperStr; if (button1.Text == "Disconnect") { serialPort1.Write(CPUperStr + "\0"); } } } C#でCPU使用率をとるならPerformanceCounterでしょ!という安直な考えです… ひたすらwhileで回してserialPort1.Write();で一秒おきに送信しています SerialPort1.Write(CPUperStr + "\0");の最後になぜナル文字(\0)が入っているかは Arudino側のプログラムでわかります Arduino側プログラム Arduino側はPCからCPU使用率の数字を文字列(100.0とか58.5とか)として送信されたものを しかるべきLEDに表示する役割を持ちます こちらの記事 arduinoで並列処理(ノンプリエンプティブ)を参考に 7segLEDの表示タスクと USBのシリアル通信でCPU使用率の数字を受け取るタスクに分けて 並列処理として実装してます CPUDisplay #include <TimedAction.h> String str = ""; //受信した文字列を格納する double num = 0; void LEDtask(); void Serialtask(); TimedAction ledAction = TimedAction(5,LEDtask); //LED表示タスクを5msのインターバルで実行する TimedAction serialAction = TimedAction(30,Serialtask); //シリアル通信タスクを30msのインターバルで実行する LED表示タスクは各桁を5msごとにダイナミック点灯させて制御しています 0-9までの表示は各関数に定義してどの桁でその表示を行うかを引数に渡すことでダイナミック点灯を実現しています LEDTask void LEDtask() { void digitalWriteTo0(int); void digitalWriteTo1(int); void digitalWriteTo2(int); void digitalWriteTo3(int); void digitalWriteTo4(int); void digitalWriteTo5(int); void digitalWriteTo6(int); void digitalWriteTo7(int); void digitalWriteTo8(int); void digitalWriteTo9(int); num = str.toDouble(); // 各桁に分解 int numBef = num * 10; int num1 = numBef / 1000; int num2 = numBef % 1000 / 100; int num3 = numBef % 100 / 10; int num4 = numBef % 10 ;   // 桁ごとに表示 switch(num1){ case 0: digitalWriteTo0(1); break; case 1: digitalWriteTo1(1); break; case 2: digitalWriteTo2(1); break; case 3: digitalWriteTo3(1); break; case 4: digitalWriteTo4(1); break; case 5: digitalWriteTo5(1); break; case 6: digitalWriteTo6(1); break; case 7: digitalWriteTo7(1); break; case 8: digitalWriteTo8(1); break; case 9: digitalWriteTo9(1); break; } delay(5); switch(num2){ case 0: digitalWriteTo0(2); break; case 1: digitalWriteTo1(2); break; case 2: digitalWriteTo2(2); break; case 3: digitalWriteTo3(2); break; case 4: digitalWriteTo4(2); break; case 5: digitalWriteTo5(2); break; case 6: digitalWriteTo6(2); break; case 7: digitalWriteTo7(2); break; case 8: digitalWriteTo8(2); break; case 9: digitalWriteTo9(2); break; }  /* 以下略 */ } シリアル通信タスクは少し試行錯誤しました SerialTaskの第一弾 void Serialtask() { if (Serial.available() > 0){ str = Serial.readString(); } } Serial.readString();でUSBシリアル通信で来た文字列を受信しているのですが 以下の様な動作になりました データが来てから表示されるまでに謎のラグがあります このラグをどうにかしてなくしたい!! とArduinoの言語リファレンスをよく読んでみると Serial.readString()は、シリアルバッファから文字を読み、文字列に書き込む。この関数はタイムアウトすれば終了する との記述を発見 この受信してからデータが表示されるまでのラグは 受信のタイムアウトをわざわざ待っていたということに気が付きました その後リファレンスを見返すと Serial.readStringUntil()は、シリアルバッファから文字を読み、文字列に書き込む。この関数は、終端文字を検出するかタイムアウトすれば終了する(Serial.setTimeout()参照)。 めちゃくちゃいい関数あんじゃん!!! ということで以下のように変更しました SerialTaskの改良版 void Serialtask() { if (Serial.available() > 0){ str = Serial.readStringUntil('\0'); } } Serial.readString()をSerial.readStringUntil()に書き換え 終端文字としてナル文字を指定、C#側でナル文字を文字列の末尾につけて送信するようにしました すると… ラグがなくなってすんなりと表示ができるようになりました loop() void loop() { // put your main code here, to run repeatedly: ledAction.check(); serialAction.check(); } 冒頭で宣言したタスクをcheckすることで起動しています digitalWriteTo1() void digitalWriteTo1(int port){ // アノードコモン側のどの桁に表示するかの選択 switch (port){ case 1: digitalWrite(9, HIGH); digitalWrite(10, HIGH); digitalWrite(11, LOW); digitalWrite(12, LOW); digitalWrite(13, LOW); break; case 2: digitalWrite(9, HIGH); digitalWrite(10, LOW); digitalWrite(11, HIGH); digitalWrite(12, LOW); digitalWrite(13, LOW); break; case 3: digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(11, LOW); digitalWrite(12, HIGH); digitalWrite(13, LOW); break; case 4: digitalWrite(9, HIGH); digitalWrite(10, LOW); digitalWrite(11, LOW); digitalWrite(12, LOW); digitalWrite(13, HIGH); break; } // 数字の表示 digitalWrite(2, HIGH); digitalWrite(3, LOW); digitalWrite(4, LOW); digitalWrite(5, HIGH); digitalWrite(6, HIGH); digitalWrite(7, HIGH); digitalWrite(8, HIGH); } 上記の様な感じで0-9までの表示を行っています 完成!! 完成しました これを表示しながらゲームするなり レンダリングするなりベンチマークとったりすると非常に面白いです 夏休みの自由研究Arduino uno + C#でCPU使用率を7セグLEDに表示してみたマルチスレッドとかSerial.readStringの仕様とかいろいろ学ぶところあったので後日qiitaに投稿しようかな pic.twitter.com/99eoPnAssx— uechan (@uechang16) August 5, 2021 夏休みの自由研究(暇つぶし)としてやってみましたが 所要時間3時間程度で終わってしまったため また何かネタを探してちょろちょろやっていきたいと思います 参考にしたサイト とても参考になりました ありがとうございました

Viewing all articles
Browse latest Browse all 9703

Trending Articles