最終更新日
記事公開日

【ラズパイPico】子供がテレビに近づくと、強制的にテレビの電源が切れる装置を作ってみた

子供がテレビに近づくと、強制的にテレビの電源が切れる装置

「もう少し離れてテレビを見なさい!」

「そんなに近くで見ると、目が悪くなるよ!」

何度注意しても、数分後にはテレビの目の前に座っている息子。

きりがないので、子供がテレビに近づくと強制的にテレビの電源が切れる装置をラズパイPicoで作ってみました。

「あれ?反応しないな?」と思ったら、お腹を突き出したところがちょうど検出範囲だったみたいです。

配線・回路図

子供がテレビに近づくと、強制的にテレビの電源が切れる装置の回路図
全体配線画像
基板(表)拡大
基板(裏)拡大

使用パーツ

  • 焦電型赤外線センサーモジュール(SB612A) - 秋月電子 または Amazon
  • 5mm赤外線LED(OSI5FU5111C-40)- 秋月電子
  • ラズベリーパイPico
  • トランジスタ(2SC1815)
  • 抵抗(51Ω)
  • 抵抗(3.9kΩ)
  • 5mmLED(抵抗内蔵タイプ)
  • 電池ケース&単三電池×3本
  • ユニバーサル基板
  • プラスチックスペーサー(10mm×4)
  • ラズPico用ピンソケット(20ピン×2)
  • センサー用ピンソケット(3ピン)
  • 電源用ピンソケット(2ピン)
  • QIコネクタ(3ピン用、2ピン用)
  • フラットケーブル
  • 人感センサー取り付け用ネジ(M2)
  • プラスチックケース(セリアで購入)

プログラム(MicroPython)

※三菱のテレビリモコンを解析したデータを使用しています。他メーカーのテレビを制御する場合には、赤外線フォーマットに合わせてコードを書き換える必要があります。

# GPIOピン制御・PWM制御・アナログ-デジタル変換のライブラリを読み込み
from machine import Pin, PWM, ADC

# 時間関連のライブラリを読み込み
import time

# PWM制御を行うピンの設定
ir = PWM(Pin(17, Pin.OUT))

# アナログ-デジタル変換を行うピンの設定
adc = ADC(1)

# ステータス表示用LEDのピン設定
led = Pin(2, Pin.OUT, value=0)

# リモコン信号を何度も送信しないためのフラグ(0:未送信、1:送信済)
st = 0

# 起動時のセンサー反応対策(3秒待機)
time.sleep(3)
       
# 赤外線リモコンを制御するときに呼び出す関数
def IR():

    # PWM制御の動作周波数を設定
    # 一般的なリモコンで使用されている周波数 = 38KHz
    f = 38000
    ir.freq(f)

    # PWM制御の周期(波が上下に1回振動するのにかかる時間)
    # 周期 = 1/周波数(38kHz)= 26μs

    # PWMのデューティー比(HIGHとLOWの比率)
    # 一般的なリモコンのデューティー比 = HIGH:1/3、LOW:2/3
    # 16bitの最大値 = FFFF(16進数)= 65535(10進数)
    # 65535 * 0.3333 = 21845(10進数)= 5555(16進数)
    dty = 0x5555

    # 解析したデータが信号を一つ送るのに掛かっていた時間 = 300us
    # 300usの長さの信号になるようにPWM信号を繰り返す
    # 300us/26us = 11.5回
    # しかしtime.ticksで赤外線通信の稼働時間を計測した結果、
    # 理想のフレーム長(53ms~55ms)に足りない
    # よって稼働時間が53ms以上になるように「20」と調整した
    adj = 24

    # 上位8bitは共通コード(11100010)
    # 下位8bitは操作ボタン(01000000 = 電源ON/OFF
    data =[1,1,1,0,0,0,1,0,0,1,0,0,0,0,0,0]

    # 赤外線通信の稼働時間を計測開始
    start = time.ticks_us()

    # 16bitのコードを読み込む
    for bit in data:
           
        # コードの値が「1」のときの処理
        if(bit == 1):
            
            # デューティー比1/3がHIGHのPWM信号を送信(adj回分)
            for i in range(1, 1*adj):
                ir.duty_u16(dty)
                
            # LOWのPWM信号を送信(7×adj回分)
            for i in range(1, 7*adj):
                ir.duty_u16(0)
             
        # コードの値が「0」のときの処理
        else:
            
            # デューティー比1/3がHIGHのPWM信号を送信(adj回分)
            for i in range(1, 1*adj):
                ir.duty_u16(dty)
                
            # LOWのPWM信号を送信(7×adj回分)
            for i in range(1, 3*adj):
                    ir.duty_u16(0)
        
    # ストップビット(データの終端を示す信号)
    for l in range(1,1*adj):
        ir.duty_u16(dty)

    # トレーラー(通信の終わりを示す信号)
    for l in range(1,1*adj):
        for i in range(1,97):
            ir.duty_u16(0)
                  
    # 赤外線通信の稼働時間を出力(53000us以上になっていればOK)
    print(time.ticks_diff(time.ticks_us(), start))
    
# 永久ループ
while True:
    
    # 人感センサーの値を読み取り
    # read_u16() ・・・アナログ値を読込み[0-65535]の整数を返す関数
    # 16bit・2進数の最大値:1111111111111111 ⇒ 10進数の最大値:65535
    # 4.5/65535の意味:電圧の最大値4.5Vを、65535という数値にあてはめるための計算
    hsens = adc.read_u16()* (4.5 / 65535)
    
    # 人感センサーが反応したとき(センサーにかかる電圧が1.5Vより大きくなったとき)
    if(hsens > 1.5):
        
        # ステータス表示用LEDをON
        led.value(1)
        
        # まだリモコン信号を送信していない場合に実行
        if(st == 0):
            
            # 赤外線リモコンを制御(テレビの電源ON/OFF信号を発信)
            IR()
            
            # リモコン信号のフラグを「送信済」に変更
            st = 1
 
    else:
        
        # ステータス表示用LEDをOFF
        led.value(0)
        
        # リモコン信号のフラグを「未送信」に設定
        st = 0

技術解説

人感センサーが人の手に反応している様子

人感センサーは、人間が発する赤外線を検知するセンサーです。

「本当に人間にしか反応しないのか?」と思い、紙をペラペラ動かしてみましたが、たしかに反応しませんでした。

人感センサーの検知範囲に人間が入ると、電圧がHIGHとなります。

アナログ=デジタル変換でその電圧を読み取っています。

もしHIGHの場合は、赤外線通信によりリモコンから解析した電源ボタンの信号を送信。

テレビの電源がOFF(またはON)となります。

※今回のプログラムでは、三菱製テレビのリモコンから解析したデータを使用しています。他のメーカーのテレビで使用する場合は、赤外線フォーマットに合わせてコードの書き換えが必要です。

リモコン制御の詳しい解説については、過去記事をご覧ください↓

ラズパイPicoでテレビを操作(リモコンの赤外線通信を解析して送受信)

遅延時間の設定

人感センサーが人間を検知したあと、次の検知を開始するまでの時間を設定することができます。

センサーについている『タイマー遅延ボリューム(Time Delay Adjust)』を調整します。

設定可能な範囲は「5秒~200秒」です。

タイマー遅延ボリューム(Time Delay Adjust)の調整

また、ジャンパーの位置(Jumper Set)を変えることで、検知モードを変更することが可能です。

Jumper Set(リピートトリガーとシングルトリガーの違い)
  • リピートトリガー:人が検知される度にタイマーがリセットされます。例えば、遅延時間を10秒に設定していても、5秒の時点で動きが検知されると、タイマーが10秒に戻ります。
  • シングルトリガー:遅延時間を10秒と設置していれば、その10秒が経過し終わるまでタイマーはリセットされません。10秒の間は動きを検知しないのと同じ作用です。

検知範囲について

検知距離は『感度ボリューム(Sensitivity Adjust)』で調整することができます。

設定可能な範囲は「3m〜7m」です。

感度ボリューム(Sensitivity Adjust)の調整

検出角度は100°の放射状となっています(調整不可)

検出角度のイメージ

設置場所について

検出範囲が広いので、お部屋のレイアウトによっては、母親が戸棚を開けたり、テレビの横を横切ったりすると、誤検知してしまう場合があります。

天井から吊るすとか、テレビの上に設置するなど、角度を付けて検知範囲を狭めてあげると良いかもしれません。

また「子供がテレビを見る場所」と「テレビの受信部の位置」によって、ケースの穴あけ位置も変わるのでご注意ください。

センサーを取り付けるために穴をくり抜いたケース

トランジスタの抵抗値

ラズパイPicoのGPIOピンに流せる電流値は低いです(16mA)

もしGPIOピンに直接赤外線LEDを繋いだとすると、テレビの赤外線受信部に30cmくらいの距離まで近づかなければリモコン信号が届きません。

そこでトランジスタ(2SC1815)を使った増幅回路を用いて、赤外線LEDにもっと大きな電流を流し、長距離までリモコン信号が届くような回路を組み込んでいます。

今回は、赤外線LEDに約50mAの電流を流すことで、約1mまでリモコン信号が届くことが確認できました。

トランジスタ増幅回路

R1:赤外線LEDを破損させないための抵抗値

  • 電源電圧:4.5V
  • 赤外線LEDの順方向電圧:1.35V
  • 赤外線LEDに流したい電流:0.05A(50mA)

R1 = (4.5V – 1.35V) / 0.05A = 78.75Ω

※実際には手元に合った51Ωを使ってます。

赤外線LEDに50mA流すために必要なトランジスタのベース電流

  • 赤外線LEDに流したい電流:0.05A(50mA)
  • 2SC1815の電流増幅率:100倍

50mA  / 100 = 0.5mA

R2:ベースに0.5mA流すために必要な抵抗値

  • ベース電流:0.0005A(0.5mA)
  • ラズパイPicoのGPIO出力電圧:3.3V
  • 2SC1815のベース・エミッタ間電圧:約0.75V(※ベース電流が0.5mAのとき↓)
2SC1815のベース・エミッタ間電圧

R2 = (3.3v – 0.75v) / 0.0005A = 5100Ω = 5.1kΩ

※実際には手元に合った3.9kΩを使ってます。

この記事のURLをコピー

メールアドレスは公開されませんのでご安心ください。また、* が付いている欄は必須項目となります。

内容に問題なければ、下記の「コメントを送信する」ボタンを押してください。

関連情報

運営者プロフィール
コダマ

職業はIT系フリーランス。過去、電子配線業務の経験が10年ある為、はんだづけも得意です。宮崎県在住、30代・2児の父親。