「Raspberry Pi」カテゴリーアーカイブ

【ラズパイ】【いろいろ計測モニター】時計表示を大きくしたい。

サービスでプログラムを稼働させてからは安定して動作しております。

ラズパイZeroで稼働させていますが、本体を手で触っても全然熱を感じないので、省エネだし、熱で壊れることもありません。

いいね、これ。

ただ、文字が小さいので、時刻だけ大きく表示させてもいいんじゃないかなって思っています。

ということで、フォントデータを作成中です。

Array = [
    [ #0
        [
            0x00, 0x00, 0x00, 0x80, 0xc0, 0xf0, 0xf8, 0xf8,
            0xfc, 0xfe, 0x7e, 0x3e, 0x3e, 0x1f, 0x1f, 0x1f,
            0x1f, 0x1f, 0x1f, 0x1f, 0x3f, 0x3e, 0x7e, 0xfe,
            0xfc, 0xf8, 0xf8, 0xf0, 0xc0, 0x80, 0x00, 0x00
        ],
        [
            0x00, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x0f,
            0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x03, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe0
        ],
        [
            0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff
        ],
        [
            0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff
        ],
        [
            0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x80, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f
        ],
        [
            0x00, 0x00, 0x00, 0x03, 0x07, 0x1f, 0x3f, 0x3f,
            0x7f, 0xfe, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xf0,
            0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfe,
            0x7f, 0x3f, 0x3f, 0x1f, 0x07, 0x03, 0x00, 0x00
        ]
    ],
:
:

ちょっと大きくしすぎた感がありますが、最低限数字4文字入ればなんとかなるので、このままフォントデータのビットパターンを作成していきます。(残り6文字)

【ラズパイ】スイッチ操作を割り込みで行う。

最新ソースはこちら。

https://github.com/takishita2nd/RaspiDisplayMonitor

以前使用していた12個のスイッチは3つの信号と4つの制御線の組み合わせで検出していましたが、

いまはスイッチは1個なので、エッジの割り込みで操作できるはずです。

スレッドが一つ無くなるので、ラズパイZeroでも動作が軽くなると思います。

import RPi.GPIO as GPIO
import time
import datetime
import calendar
import GLCD
import AM2320
import Weather

sw = False

def __main__():
    global sw
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(22,GPIO.IN) 
    GPIO.add_event_detect(22, GPIO.FALLING, callback=callback, bouncetime=300)
    GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCD.GLCDInit()
    GLCD.GLCDDisplayClear()

    roop = 10 * 60 * 60
    mode = 1
    try:
        while True:
            if sw == True:
                GLCD.GLCDDisplayClear()
                mode += 1
                if mode > 3:
                    mode = 1
                sw = False

            if mode == 1:
                if roop >= 10 * 60 * 60:
                    GLCD.GLCDDisplayClear()
                    Weather.RequestAPI()
                    weather = Weather.GetWeather()
                    temp = Weather.GetTemp()
                    roop = 0

                GLCD.GLCDPuts(1, 0, "Date :")
                GLCD.GLCDPuts(5, 8, datetime.datetime.now().strftime('%Y:%m:%d %A '))
                GLCD.GLCDPuts(1, 16, "Weather :")
                GLCD.GLCDPuts(10,24, weather)
                GLCD.GLCDPuts(10,32, "Temp : " + format(temp) + 'C')
                GLCD.GLCDPuts(1, 40, "Time : " + datetime.datetime.now().strftime('%H:%M'))
                GLCD.GLCDPuts(1, 48, "Humidity    : " + AM2320.GetHum() + '%')
                GLCD.GLCDPuts(1, 56, "Temperature : " + AM2320.GetTemp() + 'C')

                roop += 1
            elif mode == 2:
                cal = calendar.month(datetime.datetime.now().year, datetime.datetime.now().month)
                cals = cal.split("\n")
                y = 0
                for c in cals:
                    GLCD.GLCDPuts(1, y, c)
                    y += 8
            
            elif mode == 3:
                GLCD.drowMashiro()

            time.sleep(1)
    except KeyboardInterrupt:
        GLCD.GLCDDisplayClear()
        GPIO.cleanup()

def callback(channel):
    global sw
    sw = True

__main__()

GPIO.add_event_detect()で割り込み処理の登録を行います。

監視するGPIOの番号、エッジ(HIGH/LOW)、コールバック関数、検出間隔指定します。

上の処理では、GPIO22が下りエッジを検出したらcallback()が実行されます。

スイッチ検出がかなりスムーズになりました。

【ラズパイ】pythonプログラムをサービスで実行する

ラズパイZeroで作成したpythonプログラムをサービスに登録して、起動と同時に実行するように設定します。

以下のファイルを作成

pimonitor.service

[Unit]
Description=PIMonitor
After=syslog.target

[Service]
Type=simple
WorkingDirectory=/opt/pimonitor
ExecStart=/usr/bin/python3 main.py
TimeoutStopSec=5
StandardOutput=null

[Install]
WantedBy = multi-user.target

このファイルを/etc/systemd/system/配下にコピー

$ cp pimonitor.service /etc/systemd/system

※ /opt/pimonitor配下にソースファイル全て揃っている前提。

パーミッションの設定でrootでも実行できようにしておく

$ chmod 777 *

サービス開始

$ sudo systemctl start pimonitor.service

サービス登録

$ sudo systemctl enable pimonitor.service

【ラズパイ】【いろいろ計測モニター】実際に組んでみる。

今日は9時間頑張りました。

実際にこの回路を組んでみました。

材料はこちらの記事にあります。

結果はこうなりました。

挫けた。

そもそも、

このラズパイZero用の基板に全部盛り込もうとしたのが間違い。

かなり難易度の高いはんだ付け作業になりました。

また、穴と穴が繋がっていない(ユニバーサル基板とはそういうもの)ので、その線をつなぐのも苦労しました。

さらに、


GLCD側のピッチ幅がラズパイZero側の基板より小さい事が発覚。

これがさらにはんだ付けの難易度を上げました。

はんだの熱で基板と部品が若干溶けてました。

このままじゃ悔しいので、ブレッドボードに回路を作り直して、ラズパイZeroで動かしました。

今回はこれで勘弁してください。

9時間頑張ったんだよ・・・

でもラズパイZeroで動かしているので、長時間稼働していても全然暑くないです。

でも性能は明らかに劣っているからモッサリしているけどね。

損傷して使い物にならなくなってしまいました。

残念ながらゴミ箱行きです。

【ラズパイ】【いろいろ計測モニター】

どうせならきちんとして使える物を作りたい。

前回まではラズパイ4(2GB)を使用しましたが、これって、ファンを使わないと発熱がやばいらしいですね。

なので、消費電力が少なくて、発熱も少ないラズパイZERO HWを買いました。

使用する部品も買いました。

MicroUSBのACアダプター

MicroSDカード(16GB)

8GBでも十分だったんだけどね。

これらは今まで使用していた部品と同じです。

ラズパイZero用の基板です。

これにピンヘッダを取り付けて、基板と本体を取り外しできるようにします。

スイッチに使用する抵抗とダイオード。

(たぶん)同じ物を購入しました。

それらをつなぐジャンパ線です。

こんな感じで回路を組もうと思ってます。

結構ごちゃごちゃしてる。

まぁ、ピンの位置とか実際の位置に合わせて書いているので仕方が無い。

問題はスイッチが正しく動くかどうか。

前回は12個のスイッチでしたが、今回は1個のスイッチを使います。それに合わせて同じような回路を組んでいます。

ちゃんと機能するか、ブレッドボードに簡単に組んでみました。

上手くいけば、スイッチ押下時にインプット信号がHIGH→LOWになるはずです。

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.IN)
swState = 0

try:
    while True:
        if GPIO.input(21) == 0 and swState == 0:
            time.sleep(0.05)
            if GPIO.input(21) == 0:
                print("ON")
                swState = 1
        elif GPIO.input(21) == 1 and swState == 1:
            print("OFF")
            swState = 0
        time.sleep(0.005)

except KeyboardInterrupt:
    GPIO.cleanup()
$ python3 test.py 
ON
OFF
ON
OFF
ON
OFF
ON
OFF
ON
OFF

うん、うまく動いているようです。

じゃあ、制作開始といきますか。

【ラズパイ】これまでやってきたことを組み合わせる。

ここまでやってきたことを全て組み合わせます。

GLCDに表示するのは、

  • 時刻、天気、温度、湿度
  • カレンダー
  • 倉田ましろの絵

この3つの表示を、スイッチの1番を押すことで切り替えます。

import RPi.GPIO as GPIO
import time
import datetime
import calendar
import GLCD
import AM2320
import Weather
import SW


def __main__():
    GPIO.setmode(GPIO.BCM)
    GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCD.GLCDInit()
    GLCD.GLCDDisplayClear()

    SW.PinsInit(21, 22, 23, 24, 25, 26, 27)
    SW.Start()

    roop = 10 * 60 * 60
    mode = 1
    try:
        while True:
            key = SW.GetKey()
            if key == "1":
                GLCD.GLCDDisplayClear()
                mode += 1
                if mode > 3:
                    mode = 1

            if mode == 1:
                if roop >= 10 * 60 * 60:
                    Weather.RequestAPI()
                    weather = Weather.GetWeather()
                    temp = Weather.GetTemp()
                    roop = 0

                GLCD.GLCDPuts(1, 0, "Date :")
                GLCD.GLCDPuts(5, 8, datetime.datetime.now().strftime('%Y:%m:%d %A'))
                GLCD.GLCDPuts(1, 16, "Weather :")
                GLCD.GLCDPuts(10,24, weather)
                GLCD.GLCDPuts(10,32, "Temp : " + format(temp) + 'C')
                GLCD.GLCDPuts(1, 40, "Time : " + datetime.datetime.now().strftime('%H:%M:%S'))
                GLCD.GLCDPuts(1, 48, "Humidity    : " + AM2320.GetHum() + '%')
                GLCD.GLCDPuts(1, 56, "Temperature : " + AM2320.GetTemp() + 'C')

                roop += 1
            elif mode == 2:
                cal = calendar.month(datetime.datetime.now().year, datetime.datetime.now().month)
                cals = cal.split("\n")
                y = 0
                for c in cals:
                    GLCD.GLCDPuts(1, y, c)
                    y += 8
            
            elif mode == 3:
                GLCD.drowMashiro()

            time.sleep(0.1)
    except KeyboardInterrupt:
        SW.Stop()
        GLCD.GLCDDisplayClear()
        GPIO.cleanup()

__main__()

スイッチ押下でmodeの値が変化し、表示処理の内容を変えています。

なかなか上手くいったので、これで完成品を作ってみようか。

ラズパイ遊びの集大成です。

【ラズパイ】【GLCD】カレンダーを表示する

GLCDにカレンダーを表示させたいと思います。

import RPi.GPIO as GPIO
import time
import datetime
import calendar
import GLCD
import AM2320
import Weather
import SW


def __main__():
    GPIO.setmode(GPIO.BCM)
    GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCD.GLCDInit()
    GLCD.GLCDDisplayClear()

    try:
        while True:
            cal = calendar.month(datetime.datetime.now().year, datetime.datetime.now().month)
            cals = cal.split("\n")
            y = 0
            for c in cals:
                GLCD.GLCDPuts(1, y, c)
                y += 8

            time.sleep(0.1)
    except KeyboardInterrupt:
        GLCD.GLCDDisplayClear()
        GPIO.cleanup()

__main__()

calendar.month(year, month)で現在月のカレンダーを文字列で出力されます。

これは改行文字を使って整形されているので、改行文字で分割し一行ずつ表示位置を変えながら表示させています。

出来れば今日の日付の部分が分かるようにしたかったんだけど、無理っぽい。

よし、これでやりたいことは一通り出来た。

【ラズパイ】スイッチをモジュール化する

前回までの状況はこちら。

前回作成したサンプルソースコードを元に、スイッチ処理をモジュール化します。

やり方としては、スイッチの押下検出をスレッドで動かしてメインスレッドで取り出す、という方式が良いと思います。

GPIOのエッジ検出で割り込み処理する、という方法もありますが、このスイッチモジュールの仕様上、それは難しそうです。

import RPi.GPIO as GPIO
import time
import threading

X_p = 0
Y_p = 0
Z_p = 0
A_p = 0
B_p = 0
C_p = 0
D_p = 0

Non = ""
Key = Non

thread = None
Loop = True

def PinsInit(x, y, z, a, b, c, d):
 省略

def Start():
    thread = threading.Thread(target=threadProcess)
    thread.start()

def Stop():
    global Loop
    Loop = False

def GetKey():
    global Key
    ret = Key
    Key = Non
    return ret

def threadProcess():
    global Key

    col = 1
    swState = [0] * 12
    while Loop:
        if col == 1:
            GPIO.output(X_p, GPIO.LOW)
            GPIO.output(Y_p, GPIO.HIGH)
            GPIO.output(Z_p, GPIO.HIGH)
        elif col == 2:
            GPIO.output(X_p, GPIO.HIGH)
            GPIO.output(Y_p, GPIO.LOW)
            GPIO.output(Z_p, GPIO.HIGH)
        else:
            GPIO.output(X_p, GPIO.HIGH)
            GPIO.output(Y_p, GPIO.HIGH)
            GPIO.output(Z_p, GPIO.LOW)

        # 1押下
        if swState[1] == 0 and col == 1 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                Key = "1"
                swState[1] = 1
        # 1押下戻し
        elif swState[1] == 1 and col == 1 and GPIO.input(D_p) == 1:
            Key = Non
            swState[1] = 0
        # 2押下
        if swState[2] == 0 and col == 2 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                Key = "2"
                swState[2] = 1
        # 2押下戻し
        elif swState[2] == 1 and col == 2 and GPIO.input(D_p) == 1:
            Key = Non
            swState[2] = 0
        # 3押下
        if swState[3] == 0 and col == 3 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                Key = "3"
                swState[3] = 1
        # 3押下戻し
        elif swState[3] == 1 and col == 3 and GPIO.input(D_p) == 1:
            Key = Non
            swState[3] = 0
        # 4押下
        if swState[4] == 0 and col == 1 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                Key = "4"
                swState[4] = 1
        # 4押下戻し
        elif swState[4] == 1 and col == 1 and GPIO.input(C_p) == 1:
            Key = Non
            swState[4] = 0
        # 5押下
        if swState[5] == 0 and col == 2 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                Key = "5"
                swState[5] = 1
        # 5押下戻し
        elif swState[5] == 1 and col == 2 and GPIO.input(C_p) == 1:
            Key = Non
            swState[5] = 0
        # 6押下
        if swState[6] == 0 and col == 3 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                Key = "6"
                swState[6] = 1
        # 6押下戻し
        elif swState[6] == 1 and col == 3 and GPIO.input(C_p) == 1:
            Key = Non
            swState[6] = 0
        # 7押下
        if swState[7] == 0 and col == 1 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                Key = "7"
                swState[7] = 1
        # 7押下戻し
        elif swState[7] == 1 and col == 1 and GPIO.input(B_p) == 1:
            Key = Non
            swState[7] = 0
        # 8押下
        if swState[8] == 0 and col == 2 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                Key = "8"
                swState[8] = 1
        # 8押下戻し
        elif swState[8] == 1 and col == 2 and GPIO.input(B_p) == 1:
            Key = Non
            swState[8] = 0
        # 9押下
        if swState[9] == 0 and col == 3 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                Key = "9"
                swState[9] = 1
        # 9押下戻し
        elif swState[9] == 1 and col == 3 and GPIO.input(B_p) == 1:
            Key = Non
            swState[9] = 0
        # *押下
        if swState[10] == 0 and col == 1 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                Key = "*"
                swState[10] = 1
        # *押下戻し
        elif swState[10] == 1 and col == 1 and GPIO.input(A_p) == 1:
            Key = Non
            swState[10] = 0
        # 0押下
        if swState[0] == 0 and col == 2 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                Key = "0"
                swState[0] = 1
        # 0押下戻し
        elif swState[0] == 1 and col == 2 and GPIO.input(A_p) == 1:
            Key = Non
            swState[0] = 0
        # #押下
        if swState[11] == 0 and col == 3 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                Key = "#"
                swState[11] = 1
        # #押下戻し
        elif swState[11] == 1 and col == 3 and GPIO.input(A_p) == 1:
            Key = Non
            swState[11] = 0

        col += 1
        if col > 3:
            col = 1
        
        time.sleep(0.005)

Start()でthreadProcess()をバックグラウンドで実行、Stop()でLoop=Falseになるまで実行します。

スイッチを押すと、その値がKeyに入るので、それをGetKey()で取り出します。

変数でワンクッション置いているのは、ボタン押しっぱなしで複数回キー入力を検出するのを防ぐためです。

def __main__():
    GPIO.setmode(GPIO.BCM)

    SW.PinsInit(21, 22, 23, 24, 25, 26, 27)
    SW.Start()

    try:
        while True:
            key = SW.GetKey()
            if key != "":
                print(key)

            time.sleep(0.1)
    except KeyboardInterrupt:
        SW.Stop()
        GPIO.cleanup()

__main__()

ここまで出来れば、他モジュールと組み合わせることも出来そうです。

【ラズパイ】スイッチを動かしてみる。

前回までの状況はこちら。

前回はスイッチをはんだ付けして、ブレッドボードに取り付けました。

今回はこのスイッチを動かしてみます。

import RPi.GPIO as GPIO
import time

X_p = 0
Y_p = 0
Z_p = 0
A_p = 0
B_p = 0
C_p = 0
D_p = 0

def PinsInit(x, y, z, a, b, c, d):
    global X_p
    global Y_p
    global Z_p
    global A_p
    global B_p
    global C_p
    global D_p

    X_p = x
    Y_p = y
    Z_p = z
    A_p = a
    B_p = b
    C_p = c
    D_p = d

    GPIO.setup(X_p, GPIO.OUT)
    GPIO.setup(Y_p, GPIO.OUT)
    GPIO.setup(Z_p, GPIO.OUT)
    GPIO.setup(A_p, GPIO.IN)
    GPIO.setup(B_p, GPIO.IN)
    GPIO.setup(C_p, GPIO.IN)
    GPIO.setup(D_p, GPIO.IN)

    GPIO.output(X_p, GPIO.HIGH)
    GPIO.output(Y_p, GPIO.HIGH)
    GPIO.output(Z_p, GPIO.HIGH)

def SW_Sample():
    col = 1
    swState = [0] * 12
    while True:
        if col == 1:
            GPIO.output(X_p, GPIO.LOW)
            GPIO.output(Y_p, GPIO.HIGH)
            GPIO.output(Z_p, GPIO.HIGH)
        elif col == 2:
            GPIO.output(X_p, GPIO.HIGH)
            GPIO.output(Y_p, GPIO.LOW)
            GPIO.output(Z_p, GPIO.HIGH)
        else:
            GPIO.output(X_p, GPIO.HIGH)
            GPIO.output(Y_p, GPIO.HIGH)
            GPIO.output(Z_p, GPIO.LOW)

        # 1押下
        if swState[1] == 0 and col == 1 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                print("push 1")
                swState[1] = 1
        # 1押下戻し
        elif swState[1] == 1 and col == 1 and GPIO.input(D_p) == 1:
            print("release 1")
            swState[1] = 0
        # 2押下
        if swState[2] == 0 and col == 2 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                print("push 2")
                swState[2] = 1
        # 2押下戻し
        elif swState[2] == 1 and col == 2 and GPIO.input(D_p) == 1:
            print("release 2")
            swState[2] = 0
        # 3押下
        if swState[3] == 0 and col == 3 and GPIO.input(D_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(D_p) == 0:
                print("push 3")
                swState[3] = 1
        # 3押下戻し
        elif swState[3] == 1 and col == 3 and GPIO.input(D_p) == 1:
            print("release 3")
            swState[3] = 0
        # 4押下
        if swState[4] == 0 and col == 1 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                print("push 4")
                swState[4] = 1
        # 4押下戻し
        elif swState[4] == 1 and col == 1 and GPIO.input(C_p) == 1:
            print("release 4")
            swState[4] = 0
        # 5押下
        if swState[5] == 0 and col == 2 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                print("push 5")
                swState[5] = 1
        # 5押下戻し
        elif swState[5] == 1 and col == 2 and GPIO.input(C_p) == 1:
            print("release 5")
            swState[5] = 0
        # 6押下
        if swState[6] == 0 and col == 3 and GPIO.input(C_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(C_p) == 0:
                print("push 6")
                swState[6] = 1
        # 6押下戻し
        elif swState[6] == 1 and col == 3 and GPIO.input(C_p) == 1:
            print("release 6")
            swState[6] = 0
        # 7押下
        if swState[7] == 0 and col == 1 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                print("push 7")
                swState[7] = 1
        # 7押下戻し
        elif swState[7] == 1 and col == 1 and GPIO.input(B_p) == 1:
            print("release 7")
            swState[7] = 0
        # 8押下
        if swState[8] == 0 and col == 2 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                print("push 8")
                swState[8] = 1
        # 8押下戻し
        elif swState[8] == 1 and col == 2 and GPIO.input(B_p) == 1:
            print("release 8")
            swState[8] = 0
        # 9押下
        if swState[9] == 0 and col == 3 and GPIO.input(B_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(B_p) == 0:
                print("push 9")
                swState[9] = 1
        # 9押下戻し
        elif swState[9] == 1 and col == 3 and GPIO.input(B_p) == 1:
            print("release 9")
            swState[9] = 0
        # *押下
        if swState[10] == 0 and col == 1 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                print("push *")
                swState[10] = 1
        # *押下戻し
        elif swState[10] == 1 and col == 1 and GPIO.input(A_p) == 1:
            print("release *")
            swState[10] = 0
        # 0押下
        if swState[0] == 0 and col == 2 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                print("push 0")
                swState[0] = 1
        # 0押下戻し
        elif swState[0] == 1 and col == 2 and GPIO.input(A_p) == 1:
            print("release 0")
            swState[0] = 0
        # #押下
        if swState[11] == 0 and col == 3 and GPIO.input(A_p) == 0:
            # チャタリング回避
            time.sleep(0.05)
            if GPIO.input(A_p) == 0:
                print("push #")
                swState[11] = 1
        # #押下戻し
        elif swState[11] == 1 and col == 3 and GPIO.input(A_p) == 1:
            print("release #")
            swState[11] = 0

        col += 1
        if col > 3:
            col = 1
def __main__():
    GPIO.setmode(GPIO.BCM)
    GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
    GLCD.GLCDInit()
    GLCD.GLCDDisplayClear()

    roop = 10 * 60 * 60
    try:
        while True:
            SW.PinsInit(21, 22, 23, 24, 25, 26, 27)
            SW.SW_Sample()
            time.sleep(0.1)
    except KeyboardInterrupt:
        GLCD.GLCDDisplayClear()
        GPIO.cleanup()

__main__()

思った以上に長くなった。

まずピン設定ですが、X,Y,Zに繋がるピンが出力用、A,B,C,Dに繋がるピンが入力用になります。

そして、X,Y,ZはHIGHで初期化します。

サンプル処理では、whileの無限ループの中で、

X=LOW、Y=HIGH、Z=HIGH

X=HIGH、Y=LOW、Z=HIGH

X=HIGH、Y=HIGH、Z=LOW

を繰り返します。

その中で、A~Dの中にLOWの信号があれば、X,Y,ZのLOW出力の状態とA~DのLOW入力の状態を

この表に当てはめて、押下されたボタンを特定します。

ただ、無限ループで動いているので、普通に信号だけを見ていると、ものすごい数の入力をプログラムが検出してしまうので、スイッチの状態を保持し、その値と変化があるか、ということを確認する必要があります。

また、物理スイッチが入ったとき、信号が一瞬の短い間、HIGH/LOWを繰り返すような信号になります。

これをチャタリングといいます。

何も対策していないと、スイッチ1回しか押していなくても、プログラムは数回スイッチを押したと判断してしまうことがあります。

なので、それを回避するために、スイッチの検出を行った後、50ミリ秒後にもう一度信号を確認、信号に変化が無ければスイッチオンとする、という風にする必要があります。

実行結果はこうなりました。

pi@raspberrypi:~/RaspiDisplayMonitor $ python3 main.py
push 1
release 1
push 2
release 2
push 3
release 3
push 4
release 4
push 5
release 5
push 6
release 6
push 7
release 7
push 8
release 8
push 9
release 9
push *
release *
push 0
release 0
push #
release #
push 1
push #
release 1
release #
push 2
push 8
release 8
push 9
release 9
release 2

同時押しも動きましたね。

これで基本的な動きは出来ました。

次回は、これをモジュール化して今までのプログラムと組み合わせていましょう。

【ラズパイ】スイッチを設置して使用できるようにする。

次は、スイッチを繋げてみます。

購入したのはスイッチが12個付いている簡易的なキットです。

この基板に部品を設置して、はんだ付けします。

ダイオード。

向きに注意。

向きを間違えると動きません。

黒い印が付いている方がカソードになります。

基板に向きがきちんと書かれているので、それに従って配置します。

抵抗。

で、これがスイッチ。

はんだ付け完了。

ブレッドボードに設置。

さらに配線も接続します。

もうこれ以上部品を設置するのは不可能ですね。

ちなみに、配線は以下の様になっています。

12SWとあるのが、今回追加したスイッチモジュールです。

スイッチが押されたかの確認は、

X=LOW、Y=HIGH、Z=HIGH

X=HIGH、Y=LOW、Z=HIGH

X=HIGH、Y=HIGH、Z=LOW

の状態を繰り返し、そのときのA,B,C,Dの出力状態(押されたときにLOWになる)を確認します。

XYZとABCDの組み合わせはこんな感じです。

回路はこんな感じ。

これを見たところ、おそらく、スイッチを押していないときは、▼から入ってきた入力がそのままA~Dに流れていく(HIGH)のでしょう。

そして、X~YがLOWの時にスイッチを押すと、▼の入力がスイッチの方へ流れていくので、その結果、A~DがLOWとなるのでは、と思います。

まぁ、この回路を流用すれば、自分で部品を調達してスイッチ回路を組むことも可能でしょう。

次回はこれを動かすためのプログラムコードを作成します。