Hello.
Recently, I'm Yukari, who is also an LED shop in the professional field. Well, according to the recent fashion. Oiler also wanted to "make the PC shine with LEDs". I tried to do it.
In such a situation!
It is OK if you collect materials that meet the following conditions and do it with acupoint alchemy.
――A case where you can put LEDs inside and you can see the LEDs from the outside. --Appropriate matrix LED -Maybe it will suffocate, so it is a proper heat dissipation means
Well, I was looking for a case with a "glass or acrylic front". I made a case of NZXT's H510i Elite. Well, I also introduced a simple water cooling called "kraken M22" so that the exhaust heat of the CPU can be taken out.
There are multiple types of "HUB75 surface mount full color matrix LEDs" that are popular these days, depending on the size of the bud. The number after the "P" in the model number is the size of the brim. The case selected this time seems to be able to hold two fans of 12 cm to 14 cm on the front. Select a size that looks like it.
For example, if it is 32x64 of P5, the size is "16cm x 32cm", which is a little big. Well, if you tabulate the typical resolution and size, it looks like this.
pitch | size | size |
---|---|---|
P2 | 64x128 | 12.8cm x 25.6cm |
P2.5 | 32x64 | 8.0cm x 16.0cm |
P3 | 32x64 | 9.6cm x 19.2cm |
P4 | 32x64 | 12.8cm x 25.6cm |
P5 | 32x64 | 16.0cm x 32.0cm |
P6.67 | 32x64 | 21.3cm x 42.6cm |
Well, this time, I decided to use the top "P2 64x128". It's more fun to have resolution, maybe. If the short side is 64 dots or more, there is a high possibility that the address line "E" will be required. Please be careful when selecting the board, which will be described later.
I use a Raspberry Pi to make it shine.
This time, I chose "Raspberry Pi4 4GB". The case is appropriate, but since GPIO is used, the official case is strict.
Next is the LED interface board. This time I decided to use the old Adafruit board, which I had left over.
However! , The following two modifications are required.
--Hardware PWM drive --Addition of address line "E"
Well, referring to this description, it feels like adding two lines and one pattern cut. There are two patterns of address E line, so first check with a tester etc. which panel you are using. The unused address E line falls to GND.
https://github.com/hzeller/rpi-rgb-led-matrix
Wiring is properly fastened with polyimide.
First of all, the front side looks like this.
The back is fixed to the stay for the 12cm fan with M3 screws.
It will look like this when you insert it.
This alone is lonely, so I laid an LED on the bottom as well.
This guy is fixed with a magnet and mounted at the four corners.
This magnet is sold at the LED shop next to Sengoku Densho in Akihabara.
https://www.akiba-led.jp/product/1197
The LED connects the LED on the bottom side to the Raspberry Pi, and from there it connects to the front LED with a chain. This is purely wiring convenience.
I decided to take power from SATA. Well, it's a long-standing promise, but the power supply for personal computers is generally "yellow: 12V", "red: 5V", "orange: 3.3V", and "black: GND". With RaspberryPi4 and LED, it seems to use 5A or more, but it will be okay because it is a PC power supply (appropriate).
The interface between the Raspberry Pi and the PC uses LAN. The PC side is USB LAN. For USB, use the conversion connector for the case from the header of the motherboard.
The connection around the Raspberry Pi looks like this.
After that, push the Raspberry Pi into the gap behind the power supply of H510i Elite, and it is completed.
Well, in other words, this PC. It's a "dual configuration PC" that lives in two environments. Well from the outside it looks like a normal PC.
The back is also an ordinary PC.
It is not batting with the genuine NZXT control mechanism "HUE2".
While keeping things up to this point, it's "no modification of the case".
On the PC side, monitoring software is required. This time, I used "Open Hardware Monitor". This software has a Web server function, so I can grasp the situation from the outside. It is a strategy to get the JSON used for rendering on the Raspberry Pi side. https://forest.watch.impress.co.jp/docs/review/383668.html
However, the above software does not support recent architecture. Actually, I am using "LibreHardwareMonitor" of Nora build from the following URL. http://takkun87.blog40.fc2.com/blog-category-6.html
If you enable the web server, set the F / W appropriately, and get the following JSON from the outside, it is successful. http://[IPアドレス]:8085/data.json
The content looks like this (partial excerpt):
data.json
{
"id": 0,
"Text": "Sensor",
"Min": "Min",
"Value": "Value",
"Max": "Max",
"ImageURL": "",
"Children": [
{
"id": 1,
"Text": "DESKTOP-HOGEHOGE",
"Min": "",
"Value": "",
"Max": "",
"ImageURL": "images_icon/computer.png ",
"Children": [
{
"id": 2,
"Text": "ASRock Z390 Phantom Gaming 6",
"Min": "",
"Value": "",
"Max": "",
"ImageURL": "images_icon/mainboard.png ",
"Children": [
{
"id": 3,
"Text": "Nuvoton NCT6791D",
"Min": "",
"Value": "",
"Max": "",
"ImageURL": "images_icon/chip.png ",
"Children": [
{
"id": 4,
"Text": "Voltages",
"Min": "",
"Value": "",
"Max": "",
"ImageURL": "images_icon/voltage.png ",
"Children": [
{
"id": 5,
"Text": "Vcore",
"Min": "1.392 V",
"Value": "1.392 V",
"Max": "1.408 V",
"SensorId": "/lpc/nct6791d/voltage/0",
"Type": "Voltage",
"ImageURL": "images/transparent.png ",
"Children": []
},
{
"id": 6,
"Text": "Voltage #2",
"Min": "1.680 V",
"Value": "1.688 V",
"Max": "1.688 V",
"SensorId": "/lpc/nct6791d/voltage/1",
"Type": "Voltage",
"ImageURL": "images/transparent.png ",
"Children": []
},
{
"id": 7,
"Text": "AVCC",
"Min": "3.488 V",
"Value": "3.488 V",
"Max": "3.488 V",
"SensorId": "/lpc/nct6791d/voltage/2",
"Type": "Voltage",
"ImageURL": "images/transparent.png ",
"Children": []
},
{
"id": 8,
"Text": "3VCC",
"Min": "3.488 V",
"Value": "3.488 V",
"Max": "3.488 V",
"SensorId": "/lpc/nct6791d/voltage/3",
"Type": "Voltage",
"ImageURL": "images/transparent.png ",
"Children": []
},
{
"id": 9,
"Text": "Voltage #5",
"Min": "1.016 V",
"Value": "1.032 V",
"Max": "1.032 V",
"SensorId": "/lpc/nct6791d/voltage/4",
"Type": "Voltage",
"ImageURL": "images/transparent.png ",
"Children": []
},
{
"id": 10,
"Text": "Voltage #6",
"Min": "1.088 V",
"Value": "1.088 V",
After that, let's assign an appropriate local IP to the USB LAN and Raspberry Pi of the PC to secure communication.
What to do is like this
--Addition of library for LED panel --Program --Definition of RAMDISK and SYSTEMD
For the LED panel library, refer to the URL below. https://qiita.com/eucalyhome/items/e871e297bfd527ccaf2c
I implemented "status display" and "life game (busyness changes depending on temperature)". Since the LEDs are chained together, the first 128 dots are for life games, and the latter 128 dots are for vertical writing status display.
ledstat.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PIL import Image, ImageDraw, ImageOps, ImageFont, ImageFilter, ImageChops, ImageColor
from rgbmatrix import RGBMatrix, RGBMatrixOptions
import time, re, copy, os, codecs, random, datetime, json
import numpy as np
from scipy import signal
class ledworker(object):
def ledinit(self):
self.options = RGBMatrixOptions()
self.options.hardware_mapping = "adafruit-hat-pwm"
self.options.led_rgb_sequence = "RGB"
self.options.rows = 64
self.options.chain_length = 8
self.options.parallel = 1
self.options.pwm_bits = 11
self.options.brightness = 50
self.options.pwm_lsb_nanoseconds = 130
self.options.gpio_slowdown = 1
self.options.panel_type = "FM6126A"
self.matrix = RGBMatrix(options = self.options)
def ledoutput(self,handle):
self.matrix.SetImage(handle)
def imagenew(self):
imagecolorspace = 'RGB'
imagecolorfill = (0, 0, 80)
imagesizex = 256
imagesizey = 64
image = Image.new(imagecolorspace, (imagesizex, imagesizey), imagecolorfill)
return (image)
class lifeworker(object):
def initstate(self, width, height, init_alive_prob=0.5):
N = width*height
v = np.array(np.random.rand(N) + init_alive_prob, dtype=int)
return v.reshape(height, width)
def addstate(self, F, width, height, init_alive_prob=0.5):
N = width*height
v = np.array(np.random.rand(N) + init_alive_prob, dtype=int).reshape(height, width)
v = F + v
return v
def countneighbor(self, F):
mask = np.ones((3, 3), dtype=int)
return signal.correlate2d(F, mask, mode="same", boundary="wrap")
def nextgeneration(self, F):
N = self.countneighbor(F)
G = (N == 3) + F * (N == 4)
return G
def toimage(self, F):
nparray = np.array(F, dtype=np.uint8)*255
image = Image.fromarray(np.uint8(nparray)).convert("1")
return image
class monitorworker(object):
def getdata(self):
datafile_hwdata = '/ramdisk/hwdata.json'
outdata = {}
outdata['cpuload'] = 0
outdata['cputemp'] = 0
outdata['gpuload'] = 0
outdata['gputemp'] = 0
outdata['cpuclock'] = 0
if not os.path.exists(datafile_hwdata):
return (outdata)
try:
with open(datafile_hwdata) as f:
hwdata = json.load(f)
except:
return (outdata)
for primarykey in hwdata['Children'][0]['Children']:
if 'cpu' in primarykey['ImageURL']:
for secondarykey in primarykey['Children']:
if 'Clocks' in secondarykey['Text']:
for thirdkey in secondarykey['Children']:
if 'CPU Core #1' in thirdkey['Text']:
outdata['cpuclock'] =re.sub("[^0-9\.]","",thirdkey['Value'])
if 'Load' in secondarykey['Text']:
for thirdkey in secondarykey['Children']:
if 'CPU Total' in thirdkey['Text']:
outdata['cpuload'] =re.sub("[^0-9\.]","",thirdkey['Value'])
if 'nvidia' in primarykey['ImageURL']:
for secondarykey in primarykey['Children']:
if 'Temperatures' in secondarykey['Text']:
outdata['gputemp'] = re.sub("[^0-9\.]","",secondarykey['Children'][0]['Value'])
if 'Load' in secondarykey['Text']:
outdata['gpuload'] = re.sub("[^0-9\.]","",secondarykey['Children'][0]['Value'])
if 'mainboard' in primarykey['ImageURL']:
for secondarykey in primarykey['Children'][0]['Children']:
if 'Temperatures' in secondarykey['Text']:
outdata['cputemp'] = re.sub("[^0-9\.]","",secondarykey['Children'][0]['Value'])
outdata['cpuload'] = "{0:5.1f}".format(float(outdata['cpuload']))
outdata['gpuload'] = "{0:5.1f}".format(float(outdata['gpuload']))
outdata['cpuclock'] = "{0:4d}".format(int(outdata['cpuclock']))
return (outdata)
def writetext(draw,hpos,message,color,font):
w, h = draw.textsize(str(message), font)
w = 48 - w
draw.text((w,hpos), str(message), color,font=font)
def main():
led = ledworker()
led.ledinit()
image = led.imagenew()
fontdata = "./GDhwGoJA-OTF112b2.otf"
life = lifeworker()
lifedatablue = life.initstate(128, 64, init_alive_prob=0.08)
lifedatagreen = life.initstate(128, 64, init_alive_prob=0.08)
monitor = monitorworker()
outdata = monitor.getdata()
imagebasel = Image.open('/data/ledstat/nzx_log_w.png').convert("RGB")
imagebasel = imagebasel.transpose(Image.ROTATE_180)
imagebaseh = copy.copy(imagebasel)
imagebaseh = imagebaseh.transpose(Image.ROTATE_90)
imageh = copy.copy(imagebasel)
image = Image.new('RGB', (256, 64), (0, 0, 0))
image.paste(imageh,(128, 0))
imagehtemp = copy.copy(imagebaseh)
draw = ImageDraw.Draw(imagehtemp)
font = ImageFont.truetype(fontdata, 16)
fontsmall = ImageFont.truetype(fontdata, 7)
addcount = 0
while True:
imageblue = life.toimage(lifedatablue)
imagegreen = life.toimage(lifedatagreen)
imagel = copy.copy(imagebasel)
imagel.paste(Image.new("RGB", imagel.size, (0,255,255)), mask=imageblue)
imagel.paste(Image.new("RGB", imagel.size, (0,0,255)), mask=imagegreen)
image.paste(imagel,(128, 0))
led.ledoutput(image)
lifedatablue = life.nextgeneration(lifedatablue)
lifedatagreen = life.nextgeneration(lifedatagreen)
time.sleep(0.05)
addcount = addcount + 1
if addcount > 20:
addcount = 0
outdatatemp = monitor.getdata()
if outdatatemp['cputemp'] != 0:
outdata = outdatatemp
blueseed = (float(outdata['cputemp'])-40) / 200
greenseed = (float(outdata['gputemp'])-40) / 200
if blueseed < 0:
blueseed = 0
if greenseed < 0:
greenseed = 0
lifedatablue = life.addstate(lifedatablue,128, 64, init_alive_prob=blueseed)
lifedatagreen = life.addstate(lifedatagreen,128, 64, init_alive_prob=greenseed)
lifedatablue = life.nextgeneration(lifedatablue)
lifedatagreen = life.nextgeneration(lifedatagreen)
imagehtemp.paste(imagebaseh,(0, 0))
draw.text((0,0), "CPU", (0, 255, 255),font=font)
writetext(draw,16,outdata['cpuload'],(255, 255, 255),font)
draw.text((48,24), "%", (0, 255, 255),font=fontsmall)
writetext(draw,32,outdata['cputemp'],(255, 255, 255),font)
draw.text((48,40), "'C", (0, 255, 255),font=fontsmall)
writetext(draw,48,outdata['cpuclock'],(255, 255, 255),font)
draw.text((48,56), "MHz", (0, 255, 255),font=fontsmall)
draw.text((0,74), "GPU", (0, 0, 255),font=font)
writetext(draw,90,outdata['gpuload'],(255, 255, 255),font)
draw.text((48,98), "%", (0, 0, 255),font=fontsmall)
writetext(draw,106,outdata['gputemp'],(255, 255, 255),font)
draw.text((48,116), "'C", (0, 0, 255),font=fontsmall)
imageh = copy.copy(imagehtemp)
imageh = imageh.transpose(Image.ROTATE_90)
image.paste(imageh,(0, 0))
if __name__ == '__main__':
main()
For the implementation of Life Game, I referred to the following URL. https://qiita.com/sage-git/items/c6c175887faa4cf737fb
The prerequisite files are as follows 128x64 background logo: /data/ledstat/nzx_log_w.png Data.json for PC status: /ramdisk/data.json Font: ./GDhwGoJA-OTF112b2.otf
The font is the one on the highway, if you like. https://forest.watch.impress.co.jp/library/software/gdhighway/
Next, a suitable program to get JSON from your PC
getdata.py
import urllib.request
import json
import time
url = 'http://[ip address]:8085/data.json'
datafile = '/ramdisk/hwdata.json'
req = urllib.request.Request(url)
while True:
try:
with urllib.request.urlopen(req) as res:
body = json.load(res)
fw = open(datafile,'w')
json.dump(body,fw,indent=4)
fw.close()
except:
time.sleep(30)
time.sleep(2)
It works with Python3 Note, well, unscrupulous.
RAMDISK definition is easy. First, create a 777 directory with "/ ramdisk /" as root. Add "tmpfs / ramdisk tmpfs defaults, size = 16m 0 0" to FSTAB. Just "mount -a" or reboot. If you df and have "tmpfs 16384 84 16300 1% / ramdisk", it's OK.
Registration to systemd looks like the following.
/etc/system/getdata.service
[Unit]
Description=getdata
[Service]
ExecStart=/usr/bin/python3 /data/ledstat/getdata.py
Restart=always
Type=simple
User=pi
[Install]
WantedBy=multi-user.target
/etc/systemd/system/ledstat.service
[Unit]
Description=ledstat
[Service]
WorkingDirectory=/data/ledstat
ExecStart=/usr/bin/python /data/ledstat/ledstat.py
Restart=always
Type=simple
[Install]
WantedBy=multi-user.target
Then, from "systemctl daemon -reload"
systemctl start getdata
systemctl enable getdata
systemctl start ledstat
systemctl enable ledstat
With a feeling. If an error occurs, check the status.
The front panel looks like this! ..
The bottom panel looks like this if you're not busy.
When I'm busy and the temperature rises, I get confused.
It's quite fun w.
I mean. I wonder if I could make something like oil.
By the way, I don't see another computer while playing games. It's covered with LED panels, so the temperature seems to rise. In the first place, the LED is generating heat.
There is nothing good to think about seriously. It's good because it's fun! .. It's beautiful! ..
Manzoku! ..
Recommended Posts