感圧センサーの値をRGB LED Matrix Displayでグラフ表示してみた

先週やったことなのですが、そのままだとすぐに忘れそうなので書いておきます。

使ったパーツ

感圧センサー

yomon.hatenablog.com

RGB LED Matrix 64 x 32

yomon.hatenablog.com

配線

LED Matrix側でGPIO消費してしまっている関係で、SPIがもう1系統必要でした。そこで以下の記事の設定でSPI1を使えるようにしました。下のマップの赤字の部分です。

yomon.hatenablog.com

Connection Pin Pin Connection
- 1 2 -
- 3 4 -
- 5 6 (GND)
strobe 7 8 -
(GND) 9 10 E
clock 11 12 OE-
G1 13 14 (GND)
A 15 16 B
- 17 18 C
B2 19 20 (GND)
G2 21 22 D
R1 23 24 R2
(GND) 25 26 B1
- 27 28 -
- 29 30 (GND)
- 31 32 -
- 33 34 (GND)
SPI1 MISO 35 36 設定でSPI1のCE#0として割当
- 37 38 SPI1 MOSI
(GND) 39 40 SPI1 SCLK

プログラム

準備

こちらにお世話になっています。

github.com

READMEに沿ってpythonのBindingをビルド、インストールします。

$ git clone https://github.com/hzeller/rpi-rgb-led-matrix.git
$ cd rpi-rgb-led-matrix/bindings/
$ sudo apt-get update && sudo apt-get install python3-dev  python3-pillow -y
$ make build-python PYTHON=$(which python3)
$ sudo make install-python PYTHON=$(which python3)

配置

上記のリポジトリからsamplebase.py というファイルをもらってきます。オプション処理とかが書いてあるので便利です。

$ cp -ai /path/to/rpi-rgb-led-matrix/bindings/python/samples/samplebase.py .

samplebase.py と同じフォルダに適当に graph.py などの名前で以下のスクリプトを保存します。

#!/usr/bin/env python
from samplebase import SampleBase
import random
from time import sleep
import spidev

SPI_BUS = 1
SPI_DEVICE = 0
spi = spidev.SpiDev()
spi.open(SPI_BUS, SPI_DEVICE)
spi.max_speed_hz = 1000000

class mcp3002:
    def __init__(self, ch, rate=1):
        self.vref = 3.3
        self.ch = 0
        self.rate = rate

    # ここで取得できる値は抵抗で調整
    def get_value(self):
        chdata = 0x6800 | (0x1800 * self.ch)
        chbyte = chdata.to_bytes(2, byteorder='big')
        resp = spi.xfer2(chbyte)
        value = ((resp[0] << 8) + resp[1]) & 0x3ff
        return int(value/self.rate)


class GraphGenerator(SampleBase):
    def __init__(self, *args, **kwargs):
        self.interval = 0.2
        self.threasholdYellow = 16
        self.threasholdOrange = 24
        self.barWidth = 2
        super(GraphGenerator, self).__init__(*args, **kwargs)

    def drawBarPixel(self, bar, y, r, g, b):
        for x in range(bar * self.barWidth, (bar + 1) * self.barWidth):
            self.offset_canvas.SetPixel(x, y, r, g, b)

    def run(self):
        self.offset_canvas = self.matrix.CreateFrameCanvas()
        data = [0] * int(self.matrix.width / self.barWidth)
        adc = mcp3002(1, 10)

        while True:
            data.pop(0)
            data.append(adc.get_value())
            for bar in range(0, len(data)):
                for y in range(0, data[bar]):
                    if y < self.threasholdYellow:
                        self.drawBarPixel(bar, y, 0, 200, 0)
                    elif y < self.threasholdOrange:
                        self.drawBarPixel(bar, y, 150, 150, 0)
                    else:
                        self.drawBarPixel(bar, y, 250, 100, 0)
                for y in range(data[bar], self.matrix.height):
                    self.drawBarPixel(bar, y, 0, 0, 0)

            self.offset_canvas = self.matrix.SwapOnVSync(self.offset_canvas)
            sleep(self.interval)


# Main function
if __name__ == "__main__":
    graph_generator = GraphGenerator()
    if (not graph_generator.process()):
        graph_generator.print_help()

実行

オプション入れて実行します。

$ sudo python3 graph.py --led-no-hardware-pulse LED_NO_HARDWARE_PULSE --led-rows 32 --led-cols 64

感圧センサー押す強さに合わせて、グラフが緑から黄や赤のゾーンに上がります。バーの幅やグラフ更新のスピードはスクリプトの変数で簡単に調整可能です。

youtu.be