息抜きコーナ

【Python】Raspberry Pi Zeroと3Dプリンタを使った、オブジェ制作 – 外部PCのGPU使用率を計測して、LEDを色を変えてみる –

【Python】Raspberry Pi Zeroと3Dプリンタを使った、オブジェ制作 - 外部PCのGPU使用率を計測して、LEDを色を変えてみる -

こんにちは、Zero-Cheeseです。

今回は、久々に趣味で制作した物を、紹介いたします。

制作した物は

  • 外部PCのGPU使用率を計測して、
  • 目の色を変化させるオブジェ

です。

下記の属性をお持ちの方は、楽しめると、思います。

  • Python初心者以上の方
  • ワクワクした物を作りたい人!!
  • (3Dモデル、3Dプリンタの知見は、なくても大丈夫です)
  • (Raspberry Pi(ラズパイ)の知見がなくても、問題なしです。)

【構想時の絵】

今回、計測に用いた外部PCは、GPUが2個、付いています。(自作PCです。)

  • Nvidiaの、「GTX1080Ti」と「GTX1080」が付いています。

きしょい・・・

この子のスペック:

  • 外部パソコンのGPU使用率に応じて、目の色を変えられる

筆者が勢いで作った物なので、軽い気持ちで、流し読みしてやって下さい。

動機

家の自作PCが、ディープラーニング学習のために、ずーと働いてくれてます。

ディープラーニングの学習をしていると、GPU使用率が気になるところです。

ターミナルを開いて、コマンドを打ち込めば、簡単に分かりますが、

  • なにかもっと、感情的に訴えるものがほしい!!

と思い、本企画を実行に移しました。

制作に必要なモノ

一覧

  • RaspBerry Pi Zero WH
  • LED(フルカラータイプ)
  • 抵抗
  • ブレッドボード
  • ブレッドボード用ジャンバー線
  • 3Dプリンタ

RaspBerry Pi Zero WH

とても、小さなコンピュータです。

コンピュータなのに、手のひらにのるサイズです!

WiFi、Bluetooth 等も付属しています。

CPUは、クロック1GHzもあります。

月に行った、アポロのコンピュータのクロックが、0.002GHzだったとか・・ (あちらは、リアルタイム組込なので、単純比較が難しい所ですが・・)

主な特徴

  • 802.11 b/g/n wireless LAN
  • Bluetooth 4.1
  • Bluetooth Low Energy (BLE)
  • 1GHz, single-core CPU
  • 512MB RAM 等々

より詳細を知りたい方は、公式サイトをご参照ください。

マルチスレッド性能が5倍向上した、「Raspberry Pi Zero 2 W」が発売予定です。

しかし、半導体不足等の影響により、まだ入手困難な状況です。(2022年6月現在)

LED(フルカラータイプ)

RGB全部ありの、フルカラーLEDを使いました。

ピンは、

  • RGBのそれぞれに対応するピン(+側:アノードと呼ばれます。)
  • GNDに対応するピン(−側:カソードと呼ばれます。)

の合計、4本になります。

秋月電子通商さんのリンクを貼っておきます。

RGBフルカラーLED 5mm OSTAMA5B31A アノードコモンhttps://akizukidenshi.com/catalog/g/gI-12167/

電源とLEDの直接接続は、NGです。

LEDは、抵抗がほぼゼロのため、大電流が流れ、一発で壊れるからです。

よって、電源と抵抗との間に、必ず抵抗を入れ、LEDの許容電流以下にします。

抵抗

今回使用した抵抗は、330Ωです。

一般的な、抵抗を使用しました。

ブレッドボードとブレッドボード用ジャンバー線

ちょっとテストする場合、配線のハンダ付けとか、面倒だと思います。

そんなとき、ブレッドボードとジャンバー線は、とても便利です。

【ブレッドボードに、ジャンバー線が、刺さっている写真】

こんな感じで、ブレッドボードに、抵抗や、ジャンバー線をさすだけで、簡単に、電子工作が楽しめます。

制作手順

以下の手順で、制作しました。

  1. 「ガイコツ」の3Dモデルを制作
  2. 3Dプリンタで、「ガイコツ」制作
  3. 電子工作(ラズパイとLED接続等)
  4. プログラム制作

① 「ガイコツ」の3Dモデル制作

3Dモデル制作には、Fusion 360を使用しました。

制作したモデルは、こちらです。

【斜め上から】

【下から】

下部には、ラズパイ設置用スペースを設けました。

また、目にLEDの配線するため、 ラズパイまでの配線スペースである、貫通穴も作りました。

【配線イメージ】

3Dモデルでは、配線が太く描かれてしますが、ただのリード線を使っています。

もっとガイコツっぽい外観にしたかったのですが、作者のスキルが・・

② 3Dプリンタで、「ガイコツ」制作

うちにある、3Dプリンタは、こちらになります。

主なスペック

  • メーカー:QIDI Technology
  • 型番:X-Plus
  • 造形材料:PLA, ABS TPU PETG, PC, Nylon, Carbon fiber
  • ビルドサイズ:270×200×200mm
  • 層の厚さ:0.05 – 0.4 mm
  • 位置決め精度:Z:0.0025mm; XY:0.011mm

様々な材料が使える!(カーボンが使えるのはGood!)、 積層厚も0.05mm とGood!、あと結構大きいモノまで作れるので、購入しました。

制作した「ガイコツ」は、こちらです。

【3Dプリンタ直後 (サポート材有りの状態)】

せっかくなので、金色で作ってみました!

結構、色がリアルです!

③ 電子工作(ラズパイとLED接続等)

電子回路は、本当に単純です。

ラズパイのピンと、LEDと、抵抗を直列に繋ぐだけになります。

ラズパイのピンは、番号がふられています。

Raspberry Pi Documentation より引用

上図の、GPIO(汎用入出力)と記載されている「ピン」を使用します。

制作した回路 (+から−まで、接続の順番を、記しています。)

◆ GTX1080Ti 用の LED

  • LEDのR用回路: GPIO 17ピン → LED R → 抵抗 → GND ピン
  • G用回路:GPIO 27ピン → LED G → 抵抗 → GND ピン
  • B用回路:GPIO 22ピン → LED B → 抵抗 → GND ピン

◆ GTX1080 用の LED

  • LEDのR用回路: GPIO 13ピン → LED R → 抵抗 → GND ピン
  • G用回路:GPIO 19ピン → LED G → 抵抗 → GND ピン
  • B用回路:GPIO 26ピン → LED B → 抵抗 → GND ピン

回路図でご紹介しようと思いましたが、単純なので、省略しました。

④ プログラム制作

ソフトウェア部分は、下記の構成になっています。

  • 外部PCのWebサーバを立てて、GPU使用率を知らせるAPIを作る
  • ラズパイで、そのAPIを叩いて、GPU使用率を取得 → LEDを光らせる

<構成イメージ>

外部PCにWebサーバを立てる

Webアプリ フレームワークである、Flaskを使用しました。

このプログラムは、外部PC側で、走らせます。

エンドポイント「/get_gpu_usage」を叩くと、JSONで、GPUの使用率が返ります。

import os
import subprocess
from flask import Flask
from flask import jsonify

app = Flask(__name__)

@app.route('/')
def get_main():
    # この部分は、特にいらない
    return 'world'

@app.route('/get_gpu_usage')
def get_gpu_usage():
    try:
        p1 = subprocess.Popen(['nvidia-smi', '--query-gpu=utilization.gpu', '--format=csv,noheader,nounits'], stdout=subprocess.PIPE)
        output = p1.communicate()[0]
        output = output.decode()
        output = output.split()

        output_json = {
            'GTX1080Ti': {
                'usage': output[0],
                'temp': None
            },
            'GTX1080': {
                'usage': output,
                'temp': None
            }
        }
        return jsonify(output_json)

    except:
        return {'message': 'Error'}


if __name__ == '__main__':
    app.run(debug='True', host='0.0.0.0', port=8000)

ラズパイ側のプログラム

外部PCのAPIを叩いて、GPU使用率を取得するコード

「gpu_usage.py」 というファイル名で作成しました。

import json
import requests
import time

class GpuUsage(object):
    def __init__(self, url):
        self.url = url

    def get_both_usage(self):
        try:
            r = requests.get(self.url)
            r = r.json()

            gtx1080ti_usage = r['GTX1080Ti']['usage']
            gtx1080_usage = r['GTX1080']['usage']

            return gtx1080ti_usage, gtx1080_usage

        except Exception as e:
            print(e)

LEDを光らせるクラスと、全体管理するクラス

「monitor_controller.py」というファイル名で、作成しています。

import time
import RPi.GPIO as GPIO
import gpu_usage

GPIO.setmode(GPIO.BCM)


class Led(object):

    def __init__(self, name: str):
        self.name = name
        self.port_R = 0
        self.port_G = 0
        self.port_B = 0

        if self.name == 'GTX1080ti':
            self.port_R = 17
            self.port_G = 27
            self.port_B = 22
        elif self.name == 'GTX1080':
            self.port_R = 13
            self.port_G = 19
            self.port_B = 26

        self.ports = [self.port_R, self.port_G, self.port_B]

        for port in self.ports:
            GPIO.setup(port, GPIO.OUT)

    def _set_color(self, r, g, b):
        GPIO.output(self.ports[0], r)
        GPIO.output(self.ports, g)
        GPIO.output(self.ports, b)

    def red_light_on(self):
        self._set_color(1, 0, 0)
        print('red')

    def green_light_on(self):
        self._set_color(1, 0, 1)
        print('green')

    def blue_light_on(self):
        self._set_color(0, 0, 1)
        print('blue')

    def light_off(self):
        self._set_color(0, 0, 0)
        print('off')


class MonitorController(object):

    PROCESS_TIME = 0.5 # 何秒おきに、GPU使用率をチェックするか
    MAX_USAGE_LOW_LEVEL = 80 # GPU使用率 80%以上でLEDの色を変える
    MAX_USAGE_MIDDLE_LEVEL = 95 # GPU使用率 95%以上でLEDの色を変える

    def __init__(self, gpu_usage: GpuUsage, led_gtx1080: Led, led_gtx1080ti: Led):
        self.gpu_usage = gpu_usage
        self.led_gtx1080 = led_gtx1080
        self.led_gtx1080ti = led_gtx1080ti

    def process(self):
        while True:

            gtx1080ti_usage, gtx1080_usage = self.gpu_usage.get_both_usage()

            gtx1080ti_usage = int(gtx1080ti_usage)
            gtx1080_usage = int(gtx1080_usage)

            self._change_led_color(gtx1080ti_usage, self.led_gtx1080ti)
            self._change_led_color(gtx1080_usage, self.led_gtx1080)

            time.sleep(PROCESS_TIME)

    def _change_led_color(self, usage: int, led: Led):
        if usage <= MAX_USAGE_LOW_LEVEL:
            led.blue_light_on()
        elif usage <= MAX_USAGE_MIDDLE_LEVEL:
            led.green_light_on()
        else:
            led.red_light_on()


if __name__ == '__main__':
    # 外部PCのIPアドレスが、192.168.10.100   ポートが、8000の場合
    gpu_usage_obj = gpu_usage.GpuUsage('http://192.168.10.100:8000/get_gpu_usage')
    gtx1080_led = Led('GTX1080')
    gtx1080ti_led = Led('GTX1080ti')

    monitor_controller = MonitorController(gpu_usage_obj, gtx1080_led, gtx1080ti_led)
    monitor_controller.process()

制作物を鑑賞

さっそく、制作したオブジェを、PCにセットしてみました!

うん! ばっちり!!

・・・・・・・

最後に

夜、ふと目がさめて、このパソコン部屋に行ってみたら、すごいびっくり!!

このオブジェを動かしているのを、完全に忘れてました。

その時の写真 ↓

本当にガイコツ! PCの中身が、まるで肋骨に・・・

けっこう、ビビりました(笑)

最後まで読んでいただき、ありがとうございました。

また、お会いしましょう!