[PYTHON] Control the display of RGB LED matirix electric bulletin board freely with Raspberry Pi 3B +

environment

Raspberry Pi 3B + (including SD card) RGB LED matrix (6mm pitch 32x32) 6 sheets Connector for LED matrix MAXWELL switching power supply 3 power cords for LED panel 6 IDC flat cables 50 jump wires, male and female, and 50 male and female bread board Except for Raspberry Pi, I bought it at LED Picari Hall in Akihabara. LED Picarikan

What you want to achieve

I want to freely switch the score display of LEDmatrix using Raspberry Pi. If you can handle LEDmatrix with Raspberry Pi, you can switch from your smartphone by connecting to the Internet, so the range of applications should be wide!

What is LEDmatrix?

LED matrix is a collection of LEDs (laughs as it is) It is the same as the electric bulletin board that you often see at stations. There are various types, but basically the difference is the pitch (distance between LEDs), the color that can be expressed, and the number of vertical and horizontal LED arrangements. This time, I used 6 RGB (all colors can be expressed) 32x32 LED matrix with 6mm pitch.

wiring

First of all, we will wire. Make sure you have everything you need.

Wiring around the power supply and between LED matrix

The power supply uses a switching power supply. The current required for each card is about 2A, so if you use multiple cards, buy a power supply that corresponds to that. I used 6 sheets this time, so I needed 12A or more. As long as you don't mistake GND for V㏄, it's okay. Follow the notation on the power outlet on the back as shown in the picture below. Wire the matrices only horizontally with a flat cable. iOS の画像.jpg

Wiring of Raspberry Pi and LED matrix

This wiring was done according to the following site. hzeller github To explain by quoting this site, the connector side must be wired to each of the 16 locations in the photo below. コネクタの写真 Each connection destination is a handwritten table below. dsc_5857.jpg The two rows in the middle point to the 40 pin of the Raspberry Pi. Each connection destination is written next to it. In this library, LEDmatrix can display up to 3 levels. The connection destinations from the first to the third row are entered in order from the top. Wire the LED matrix on the far right of each row to the Raspberry Pi as shown in the picture below. ラズパイ接続 It is possible to connect to the connector as it is with a jump wire if it is one stage, but if it is two or more stages, a breadboard is required. If the wiring is messy, it will look like the picture below. IMG_1177.JPG

Control LED matrix with Raspberry Pi

I used the following library. LEDmatrix Control Library

Installation

Install the library from github immediately. Please move to the directory of the installed library and build.

git clone https://github.com/hzeller/rpi-rgb-led-matrix/
cd rpi-rgb-led-matrix
make -C examples-api-use

To enable python, execute the following command.

sudo apt-get update && sudo apt-get install python3-dev python3-pillow -y
cd rpi-rgb-led-matrix/python
make build-python PYTHON=$(which python3)
sudo make install-python PYTHON=$(which python3)

Run the demo program

You can run the demo program by going to the rpi-rgb-led-matrix directory. Do the following:

cd rpi-rgb-led-matrix
sudo examples-api-use/demo

Then, the following operation options will be displayed. Follow these options. Let me explain what is important. Specify the matrix of LED matrix per LED matrix with --led-rows, --led-cols. When using multiple stages, specify --led-parallel for the number of stages and --led-chain for the number connected horizontally. Brightness is specified by --led-brightness and display time is specified by -t.

Expected required option -D <demo>
usage: examples-api-use/demo <options> -D <demo-nr> [optional parameter]
Options:
    -D <demo-nr>              : Always needs to be set
    -t <seconds>              : Run for these number of seconds, then exit.
    --led-gpio-mapping=<name> : Name of GPIO mapping used. Default "regular"
    --led-rows=<rows>         : Panel rows. Typically 8, 16, 32 or 64. (Default: 32).
    --led-cols=<cols>         : Panel columns. Typically 32 or 64. (Default: 32).
    --led-chain=<chained>     : Number of daisy-chained panels. (Default: 1).
    --led-parallel=<parallel> : Parallel chains. range=1..3 (Default: 1).
    --led-multiplexing=<0..9> : Mux type: 0=direct; 1=Stripe; 2=Checkered; 3=Spiral; 4=ZStripe; 5=ZnMirrorZStripe; 6=coreman; 7=Kaler2Scan; 8=ZStripeUneven; 9=P10-128x4-Z (Default: 0)
    --led-pixel-mapper        : Semicolon-separated list of pixel-mappers to arrange pixels.
                                Optional params after a colon e.g. "U-mapper;Rotate:90"
                                Available: "Rotate", "U-mapper". Default: ""
    --led-pwm-bits=<1..11>    : PWM bits (Default: 11).
    --led-brightness=<percent>: Brightness in percent (Default: 100).
    --led-scan-mode=<0..1>    : 0 = progressive; 1 = interlaced (Default: 0).
    --led-row-addr-type=<0..2>: 0 = default; 1 = AB-addressed panels; 2 = direct row select(Default: 0).
    --led-show-refresh        : Show refresh rate.
    --led-inverse             : Switch if your matrix has inverse colors on.
    --led-rgb-sequence        : Switch if your matrix has led colors swapped (Default: "RGB")
    --led-pwm-lsb-nanoseconds : PWM Nanoseconds for LSB (Default: 130)
    --led-pwm-dither-bits=<0..2> : Time dithering of lower bits (Default: 0)
    --led-no-hardware-pulse   : Don't use hardware pin-pulse generation.
    --led-slowdown-gpio=<0..2>: Slowdown GPIO. Needed for faster Pis/slower panels (Default: 1).
    --led-daemon              : Make the process run in the background as daemon.
    --led-no-drop-privs       : Don't drop privileges from 'root' after initializing the hardware.
Demos, choosen with -D
    0  - some rotating square
    1  - forward scrolling an image (-m <scroll-ms>)
    2  - backward scrolling an image (-m <scroll-ms>)
    3  - test image: a square
    4  - Pulsing color
    5  - Grayscale Block
    6  - Abelian sandpile model (-m <time-step-ms>)
    7  - Conway's game of life (-m <time-step-ms>)
    8  - Langton's ant (-m <time-step-ms>)
    9  - Volume bars (-m <time-step-ms>)
    10 - Evolution of color (-m <time-step-ms>)
    11 - Brightness pulse generator
Example:
    examples-api-use/demo -t 10 -D 1 runtext.ppm
Scrolls the runtext for 10 seconds

Therefore, to run the demo, you can type the following command (change as appropriate according to your own number). By design, an error will occur if you do not run it with sudo. You can also change the demo by tweaking the number after the last -D.

sudo  examples-api-use/demo --led-no-hardware-pulse --led-rows=32 --led-cols=32 --led-chain=3 -t 10 --led-brightness=80 --led-parallel=2 -D 0

Japanese text display in Python

The sample code of python is also included in this library, so I will remodel the program so that it can display Japanese text with reference to it. Since it is a library for foreigners, there is a sample program for displaying text, but it can only display alphabets. As a result of various searches, I made a specification to convert Japanese text into an image and display it, referring to this article. Any Japanese font is fine, but please download it to Raspberry Pi. The font used this time was downloaded from this site.

text_image_ledmatrix.py


#!/usr/bin/env python
# -*- encoding:utf8 -*-
import time
import sys
import os
import numpy as np
from PIL import Image, ImageFont, ImageDraw
from rgbmatrix import RGBMatrix, RGBMatrixOptions
import subprocess, os, sys, re

def imaged_text(text, fontfile, fontsize, color, scale_bias=4):
    font = ImageFont.truetype(fontfile, fontsize * scale_bias)
    image = Image.new('RGBA', (1, 1))
    draw = ImageDraw.Draw(image)
    w,h = draw.textsize(text, font=font)
    del draw
    image = Image.new('RGBA', (w, h))
    draw = ImageDraw.Draw(image)
    draw.text((0, 0), text, font=font, fill=color)
    del draw
    return image.resize((w // scale_bias, h // scale_bias), Image.ANTIALIAS)



def draw_text_to(target, position, text, fontfile, fontsize, color):
    image = imaged_text(text, fontfile, fontsize, color)
    target.paste(image , position, image)



def select_color(threshold, color, destcolor = '#FFFFFF'):
    mean = np.array(color).mean()
    if mean > threshold:
        #return (255, 255, 255)
        return (int(destcolor[1:3],16),int(destcolor[3:5],16),int(destcolor[5:7],16))

    else:
        return (0, 0, 0)



#Character image binarization
def to_bin(img, w, h, color = '#FFFFFF'):
    #R for each pixel value,g,Find the average of b
    means = np.array([[img.getpixel((x,y)) for x in range(w)] for y in range(h)]).mean(axis=2).reshape(w * h,)
    #Make a histogram
    hist = np.array([np.sum(means == i) for i in range(256)])
    max_v = 0
    threshold = 0
    #Calculate from 0 to 255 in order to find the appropriate threshold
    #Pixel values larger than the threshold are classified as class 1, and pixel values smaller than the threshold value are classified as class 2.
    for th in range(256):
        n1 = sum(hist[:th])                                 #Number of class 1
        m1 = np.dot(hist[:th], np.array(range(256))[:th])   #Average of class 1 values
        n2 = sum(hist[th:])                                 #Number of class 2
        m2 = np.dot(hist[th:], np.array(range(256))[th:])   #Average of class 2 values
        if n1 == 0 or n2 == 0:
            v = 0
        else:
            #Find the molecule of interclass dispersion
            v = n1 * n2 * (m1 / n1 - m2 / n2) ** 2
        #Update the threshold at which the numerator of interclass variance is maximum
        if max_v < v:
            max_v = v
            threshold = th
    bin_img = Image.new('RGB', (w, h))
    np.array([[bin_img.putpixel((x, y), select_color(threshold, img.getpixel((x,y)), color)) for x in range(w)] for y in range(h)])
    return bin_img
#Connect images side by side
def get_concat_h(im1, im2):
    dst = Image.new('RGB', (im1.width + im2.width, im1.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, 0))
    return dst


#Connect images vertically
def get_concat_w(im1, im2):
    dst = Image.new('RGB', (im1.width,im1.height + im2.height,))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (0, im1.height))
    return dst

def get_text(str, width, separator = u"", col = '#B5E61D'):
    image = Image.new("RGB", (width, 16))
    draw_text_to(image, (0, 0), separator + str, 'KH-Dot-Kodenmachou-16.ttf', 16, col)
    bin = to_bin(image, image.width, image.height, col)
    return bin

def get_large_text(str, width, separator = u"", col = '#B5E61D'):
    image = Image.new("RGB", (width,64))
    draw_text_to(image, (0, 16), separator + str, 'KH-Dot-Kodenmachou-16.ttf', 32, col)
    bin = to_bin(image, image.width, image.height, col)
    return bin

def add_text(tex):

    filename='clear.txt'

    with open(filename,'a') as file_object:

        file_object.write(tex+'\n')

def clearmatrix():
    f=open('clear.txt')
    line=f.readline()
    while line:
        ans=line
        line=f.readline()			
    f.close()
    ans=ans.strip()
    if ans=='clear':
        return True
    else:
        return False


# Configuration for the matrix
options = RGBMatrixOptions()
options.rows = 32
options.chain_length = 3
options.parallel = 2
options.hardware_mapping = 'regular'
options.brightness = 40
options.pwm_lsb_nanoseconds = 100
matrix = RGBMatrix(options = options)

def textscroll(text):
    add_text("on")
    width=full_width_decision(text)+32*6
    text1="      "
    left=0
    right=96
    result = Image.new("RGB", (96, 32))
    text=text1+text
    text_im = get_large_text(text, width, u"", '#FF7F27')
    while clearmatrix()==False:
        result=text_im.crop((left,0,right,64))
        left+=1
        right=left+96
        if left>=width:
            left=0
        matrix.SetImage(result)
        time.sleep(0.005)#Changing this value will change the scroll speed.
    matrix.Clear()
    add_text("off")

def ledprint(text):
    add_text("on")
    length=len(text)
    row=int((length-1)/6)
    text1="      "
    text2="      "
    text3="      "
    text4="      "
    if row==0:
        text1=text
    if row==1:
        text1=text[0:6]
        text2=text[6:]
    if row==2:
        text1=text[0:6]
        text2=text[6:12]
        text3=text[12:]
    if row>=3:
        text1=text[0:6]
        text2=text[6:12]
        text3=text[12:18]
        text4=text[18:]
    text1_im = Image.new("RGB", (96, 16))
    text2_im = Image.new("RGB", (96, 16))
    text3_im = Image.new("RGB", (96, 16))
    text4_im = Image.new("RGB", (96, 16))
    while clearmatrix()==False:
        text1_im = get_text(text1, 96, u"", '#FF7F27')
        text2_im = get_text(text2, 96, u"", '#FF7F27')
        text3_im = get_text(text3, 96, u"", '#FF7F27')
        text4_im = get_text(text4, 96, u"", '#FF7F27')
        result = get_concat_w(text1_im,text2_im)
        result = get_concat_w(result,text3_im)
        result = get_concat_w(result,text4_im)
        matrix.SetImage(result)
        time.sleep(1)
    matrix.Clear()
    add_text("off")

if __name__ == '__main__':
    ledprint(u"It is possible to display in this way")

You can now view and scroll the text with the two functions defined below. Please change the number part according to the size of your LED matrix. Also, as I will explain in the latter half of the article this time, since the display is switched by reading and writing the text file (program beginner), I read'clear.txt' and decide whether to delete it. .. iOS の画像 (1).jpg ezgif.com-video-to-gif (1).gif

What I was allowed to refer to

In controlling LED matrix with Raspberry Pi this time, I referred to the following article. Thank you for the wonderful article. https://qiita.com/sousan/items/19425d5eac43786003a7/ https://qiita.com/t_slash_k/items/35ccf49ce85e5cbd045b/ https://qiita.com/eucalyhome/items/e871e297bfd527ccaf2c/ https://www.buildinsider.net/small/raspisinage/01/ https://yomon.hatenablog.com/entry/2018/09/p3rgbdisplay/

in conclusion

Now it is possible to prepare and wire LEDmatrix and display Japanese text. From the next time, I will try to link Raspberry Pi and Slack so that it will be easier to handle.

Recommended Posts

Control the display of RGB LED matirix electric bulletin board freely with Raspberry Pi 3B +
Use python on Raspberry Pi 3 to light the LED with switch control!
Display images taken with the Raspberry Pi camera module
Take the value of SwitchBot thermo-hygrometer with Raspberry Pi
Log the value of SwitchBot thermo-hygrometer with Raspberry Pi
Production of temperature control system with Raspberry Pi and ESP32 (1)
Real-time classification of multiple objects in the camera image with deep learning of Raspberry Pi 3 B + & PyTorch
Control the motor with a motor driver using python on Raspberry Pi 3!
I learned how the infrared remote control works with Raspberry Pi
Graph display of household power consumption with 3GPI and Raspberry Pi
Periodically log the value of Omron environment sensor with Raspberry Pi
Servo motor control with Raspberry Pi
[AtCoder explanation] Control the A, B, C problems of ABC182 with Python!
[AtCoder explanation] Control the A, B, C problems of ABC186 with Python!
[AtCoder explanation] Control the A, B, C problems of ABC185 with Python!
[AtCoder explanation] Control the A, B, C problems of ABC187 with Python!
Logging the value of Omron environment sensor with Raspberry Pi (USB type)
[AtCoder explanation] Control the A, B, C problems of ABC184 with Python!
Production of temperature control system with Raspberry Pi and ESP32 (2) Production of transmission device
Connect to the console of Raspberry PI and display local IP and SD information
[AtCoder explanation] Control the A, B, (C), D problems of ABC165 with Python!
[AtCoder explanation] Control the A, B, C, D problems of ABC183 with Python!
Periodically notify the processing status of Raspberry Pi with python → Google Spreadsheet → LINE
[AtCoder explanation] Control the A, B, C, D problems of ABC181 with Python!
Control Akizuki's I2C-connected OLED display from Raspberry Pi
CSV output of pulse data with Raspberry Pi (CSV output)
Observe the Geminids meteor shower with Raspberry Pi 4
Get CPU information of Raspberry Pi with Python
GPS tracking with Raspberry Pi 4B + BU-353S4 (Python)
Measure CPU temperature of Raspberry Pi with Python