Raspberry Pi Zeroを使って簡単なタイマー装置を作ってみた。

#Raspberry Pi Zeroを使って簡単なタイマー放送装置を作ってみた。

##制作のきっかけ
職場で毎朝ラジオ体操をやっているのだが、これの送出装置と館内放送アンプについて、老朽化とリース料削減のために返却と相成った。

始業前にラジオ体操と朝礼があることもさることながら、年間2〜3000円のリース料までケチってしまう会社の体制に落胆したような気もしなくもない。

と愚痴っても仕方ないので本題に戻るが、ラジオ体操を営業日の毎朝９時前に、何らかの手法で流す必要があった。

CDラジカセとCD(CD-DA)の組み合わせも検討されたが、煩わしいので却下された。
そこで、自宅に転がっていたRaspberry Pi ZeroとUSBオーディオインターフェイス、5Vで動くUSBスピーカーなどを組み合わせ、ボタン押下でラジオ体操ほか、時間を報知する機能を持ち合わせたプレーヤー装置の制作を行った。

##材料（主なもの）
*Raspberry Pi Zero(余剰品)
*Micro SDカード(8GBのものを使用・余剰品)
*電気工作用プラケース(大須電気街で調達)
*プッシュボタン(大須電気街で調達)
*フルカラーLED1個(大須電気街で調達)
*DC5V 2口出力可能なACアダプタ(余剰品)
*Micro USB OTGケーブル（100均で調達）
*USB-Audioインターフェイス(余剰品)
*USB 5V電源で動作するスピーカー(余剰品)

##環境

*指定機器以外のLAN接続禁止。
*そもそも、社内外問わず、アクセス制限多数。NTPサーバーほか、アクセス不能→時計合わせ不能。オンラインでのメンテナンス、外部リソースの参照も不能。
*確保できるのは、100V電源のみ。
*会社からの予算はなし。趣味の片手間でジャンク品を寄せ集めて作成。

##要求定義
*毎朝8:55に掛け時計のチャイムが鳴るので、これを合図にプレーヤー装置の起動ボタンを押下(5秒間連続押し)する。この時、定期退勤日とそれ以外で、押下するボタンを変える(つまりボタンは２つある)事で、曜日判定を行う。ボタン長押し時、0.2秒間隔でLEDを高速点滅させる。
*ボタン連続押下5秒経過した時刻を起点として秒をカウント開始。
*上記カウント（秒数）が奇数秒の時にLEDを点灯、偶数秒の時にLEDを消灯させ、1秒サイクルで点滅させる。
*ボタン押下直後、ラジオ体操を流すこと。
*5,700秒後(10:30ごろ)、報知チャイムを鳴らすこと。
*12,600秒後(14:00ごろ)、報知チャイムを鳴らすこと。
###通常日
*20,700秒後(19:45ごろ)、帰宅予告音楽を鳴らすこと。
*600秒後(19:55ごろ)、帰宅促進音楽を鳴らすこと。
###定時退勤日
*13,800秒後(17:50ごろ)、帰宅予告音楽を鳴らすこと。
*600秒後(18:00ごろ)、帰宅促進音楽を鳴らすこと。
##終了処理
*LEDを点灯状態（待機モード）に戻し、翌朝8:55のボタン押下を待つ。

##Python3ソース

```python:job-player.py

#!/usr/bin/python
# coding: utf-8
#
# お仕事サウンドプレイヤー
#

import RPi.GPIO as GPIO
import datetime
import time
import subprocess
from decimal import Decimal




#
# sub_wait：次の時間まで待つ
#    wait_sec:待機時間（秒）
#    start_mode:起動モード（水曜以外か否か）
#
def sub_wait(wait_sec,start_mode):
    wk_sec = 0
    while (wait_sec > wk_sec):
        wk_sec = wk_sec + 1
        time.sleep(1)
        #LEDチカチカ
        LED = wk_sec % 2
        if (LED != 0):
            if (start_mode == 1):
                GPIO.output(GPIO_LED_START,GPIO.LOW)
            else:
                GPIO.output(GPIO_LED_START_WED,GPIO.LOW)
        else:
            if (start_mode == 1):
                GPIO.output(GPIO_LED_START,GPIO.HIGH)
            else:
                GPIO.output(GPIO_LED_START_WED,GPIO.HIGH)



#
# メインロジック
#



# GPIO端子の定義
GPIO_START = 5
GPIO_START_WED = 6

GPIO_LED_START = 13
GPIO_LED_START_WED = 19
GPIO_LED_WAIT = 26

# GPIO定義1:初期設定
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

# GPIO定義2:ボタン定義
GPIO.setup(GPIO_START, GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(GPIO_START_WED, GPIO.IN,pull_up_down=GPIO.PUD_DOWN)

# GPIO定義3:LED設定
GPIO.setup(GPIO_LED_START, GPIO.OUT)
GPIO.setup(GPIO_LED_START_WED, GPIO.OUT)
GPIO.setup(GPIO_LED_WAIT, GPIO.OUT)



#ずっとくりかえす
while True:

    start_cnt = 0
    start_sw = 0
    start_sw_wed = 0

    start_push = GPIO.input(GPIO_START)
    start_push_wed = GPIO.input(GPIO_START_WED)

    while ((start_push == 1 or start_push_wed == 1 or start_sw == 1 or start_sw_wed ==1) and start_cnt < 5):

        # 連続ボタン押し判定
        time.sleep(0.1)
        start_push = GPIO.input(GPIO_START)
        start_push_wed = GPIO.input(GPIO_START_WED)

        #水曜ボタンと水曜以外ボタンの同時押しを考慮
        #・同時押し時、水曜以外として扱う。
        #・押し直し時、タイマーリセットする。
        if (start_push == 1):
            start_sw = 1
            if (start_sw_wed == 1):
                start_cnt = 0
                start_sw_wed = 0
            start_cnt = start_cnt + Decimal("0.1")
        elif (start_push_wed ==1):
            start_sw_wed = 1
            if (start_sw == 1):
                start_cnt = 0
                start_sw = 0
            start_cnt = start_cnt + Decimal("0.1")
        else:
            start_sw = 0
            start_sw_wed = 0
            start_cnt = 0

        #LEDチカチカ
        LED = start_cnt % Decimal("0.2")
        if (LED != 0):
            if (start_sw == 1):
                GPIO.output(GPIO_LED_START,GPIO.HIGH)
                GPIO.output(GPIO_LED_START_WED,GPIO.HIGH)
                GPIO.output(GPIO_LED_WAIT,GPIO.HIGH)
            else:
                GPIO.output(GPIO_LED_START,GPIO.HIGH)
                GPIO.output(GPIO_LED_START_WED,GPIO.HIGH)
                GPIO.output(GPIO_LED_WAIT,GPIO.HIGH)
        else:
            if (start_sw == 1):
                GPIO.output(GPIO_LED_START,GPIO.LOW)
                GPIO.output(GPIO_LED_START_WED,GPIO.HIGH)
                GPIO.output(GPIO_LED_WAIT,GPIO.HIGH)
            else:
                GPIO.output(GPIO_LED_START,GPIO.HIGH)
                GPIO.output(GPIO_LED_START_WED,GPIO.LOW)
                GPIO.output(GPIO_LED_WAIT,GPIO.HIGH)


    # ボタン確定後の処理
    if (start_sw == 1 or start_sw_wed == 1):

        # ラジオ体操第一 8:55
        subprocess.Popen('mpg321 /home/pi/mp3/taisou_1_on_voice.mp3', shell=True)

        # 次まで待つ
        wk_wait = 5700
        sub_wait(wk_wait,start_sw)

        # 午前のFAXパトロール 10:30
        subprocess.Popen('mpg321 /home/pi/mp3/Chime.mp3', shell=True)

        # 次まで待つ
        wk_wait = 12600
        sub_wait(wk_wait,start_sw)

        # 午後のFAXパトロール 14:00
        subprocess.Popen('mpg321 /home/pi/mp3/Chime.mp3', shell=True)


        # 水曜以外
        if (start_sw == 1):
            
            # 次まで待つ
            wk_wait = 20700
            sub_wait(wk_wait,start_sw)
            
            # 完全帰宅予告 19:45
            subprocess.Popen('mpg321 /home/pi/mp3/hamabe.mp3', shell=True)

            # 次まで待つ
            wk_wait = 600
            sub_wait(wk_wait,start_sw)

            # 完全帰宅時刻 19:55
            subprocess.Popen('mpg321 /home/pi/mp3/hotaru_no_hikari.mp3', shell=True)

            # 次まで待つ
            wk_wait = 600
            sub_wait(wk_wait,start_sw)


        # 水曜
        if (start_sw_wed == 1):
            
            # 次まで待つ
            wk_wait = 13800
            sub_wait(wk_wait,start_sw)
            
            # 完全帰宅予告 17:50
            subprocess.Popen('mpg321 /home/pi/mp3/hamabe.mp3', shell=True)

            # 次まで待つ
            wk_wait = 600
            sub_wait(wk_wait,start_sw)

            # 完全帰宅時刻 18:00
            subprocess.Popen('mpg321 /home/pi/mp3/hotaru_no_hikari.mp3', shell=True)

            # 次まで待つ
            wk_wait = 600
            sub_wait(wk_wait,start_sw)


    # LED赤点灯
    GPIO.output(GPIO_LED_START,GPIO.HIGH)
    GPIO.output(GPIO_LED_START_WED,GPIO.HIGH)
    GPIO.output(GPIO_LED_WAIT,GPIO.LOW)

    # 1秒待つ
    time.sleep(1)

```
##苦戦した点
*押しボタンのチャタリング対策。(GPIOの設定で回避)
*フルカラーLEDの光らせ方が特殊だったような。(現物がないので不詳)

##心配事
この機械を勝手に作成し、会社に納品したのち、私は会社を離職している。非開発企業なので、残された人員ではメンテナンス不能。
メンテナンスが必要になった時、お声がかかるか、別の手段を見つけて、タイマー装置を廃棄処分されるかは未知数。

##ユーザーの反応
帰宅予告音楽（浜辺の唄）と完全帰宅音楽（蛍の光）が哀愁漂いすぎててちょっと悲しい、とのこと。