JUGEMテーマ:電子工作


赤外線リモコン(ESP32のRMT制御)
 
手持ちパーツで黒くて丸いやつ。

 
これってハードオフに
ケーブル探しに行ったときに3.5のオーディオプラグがくっついていて、
必要なのはオーディオプラグだけだったんで切り離して
こっちの丸くて黒いやつはそのまま取っておいたんだけど。
この度、もしやこれは、赤外線リモコンの受信部分じゃねーの?
と思い、いろいろ試した結果、
予想通り動きましたのでこれとESP32で赤外線リモコンの実験してみようかなと思います。


 
 
■赤外線リモコンの規格
 
赤外線は人の目に見えない光です。
目に見えるのは800nm~400nmの範囲になります。


 
引用
 https://www.toho-u.ac.jp/sci/biomol/glossary/chem/visible_light.html

リモコンで使っているのが940nmとの事なので、
周波数が低い方に少しずれたところの光を使っています。

 
ちなみに、https://keisan.casio.jp/exec/system/1240368538によると、
940nmの波長は周波数で言うと318.9THzとの事です。
携帯の5Gでやっと、30GHzですからね、人類はまだまだそこまで及ばないですね。
上記の赤外線を33KHz~40Khzの搬送波使って点滅させることで太陽光などの自然な光からの誤動作を防ぎつつ通信を行う。
ってもののようです。

 
参考ページ。
 http://elm-chan.org/docs/ir_format.html
上の参考ページによると
NECフォーマット、家製協フォーマット、SONYフォーマットに分かれており、
搬送波にONとOFFの信号が乗っかってくる。

そのONとOFFの信号を解析すると、メーカーコードとかデータが入ってくるんだぜ。
という事になっている。

 
となっているんですが、データの中身はそんなに興味はなくて、
市販のリモコンからデータを取り込んでおいて、
同じデータを送信できるとオリジナルリモコンとして、
マイコンと連動したり、ネットを経由して家電を制御できるよなーって思っております。

 
■回路
 

 
■データ受信
 フォトトランジスターで出来るのかなーと思っていたんですが、
 それだと搬送波の処理からやらきゃならないんですが、
 上の黒くて丸いやつとか、秋月のOSRB38C9AAでやると、搬送波の処理は
 すでに終わっている状態でONとOFFが取り出せるので、
 これの時間を記録していきます。
 一定時間記録したら、pythonの配列の形式で画面表示します。

 
■データ送信
 PWMでも出来そうなものですが、ESP32にはより正確な
 RMT制御ってのが有るそうでして、
 これを使うと、より簡単にリモコン信号を作ることができます。
 赤外線LEDは秋月のOSI5FU5111C-40を使います。
 中心波長は940nmです。

 

■プログラム使い方解説

 

受信プログラム実行例
 ex...
 IRread Version 0.1
 [8976, 4488, 561, 561, 561, 561, 561, 561, 561, 1683, 561, 1683, 561, 1683, 561, 561, 561, 1683, 561, 561, 561,  561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 1683, 561, 561, 561, 1683, 561, 1683, 561,  1683, 561, 561, 561, 561, 561, 1683, 561, 561, 561, 1683, 561, 561, 561, 561, 561, 561, 561, 1683, 561, 1683,  561, 561, 561, 44880, 8976, 2244, 561]
------ここまで-----


IRread Version 0.1と出たらリモコンデータの入力待ちになるので、
お目当てのリモコンボタンを一回押します。
その下に表示されているカッコと数字とカンマをコピーして
送信プログラムの「↓①↓↓↓↓」の所の配列を書き換えてください。
それで、実行するとリモコンと同じ信号で赤外線
LEDが光るので家電の制御が出来るようになります。

 

■送信プログラム
#

#  ESP32 micro python system
#
# 接続
#  IR----------ESP32
#   +          23(トランジスターを間に入れて赤外線LEDを制御)
#
# 仕様
#  
#  赤外線リモコンの38KHzの搬送波に乗せて
#  パルス送信 Kenwood ミニコンポの電源ON/OFF
#  esp32のRMT機能を使用する
#

import machine
from machine import Pin
import time
import esp32

#
#↓①↓↓↓↓
signal_list=[8928, 4464, 558, 558, 558, 558, 558, 558, 558, 1674, 558, 1674, 558, 1674, 558, 558, 558, 1674, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 1674, 558, 558, 558, 1674, 558, 1674, 558, 1674, 558, 558, 558, 558, 558, 1674, 558, 558, 558, 1674, 558, 558, 558, 558, 558, 558, 558, 1674, 558, 1674, 558, 558, 558, 44640, 8928, 2232, 558]

time.sleep(3.5)
print("start")

print("IRsend Version 0.4")

#ピンの準備
tx_pin = Pin(23, Pin.OUT)

#RMTの準備
ch = 0
freq=38000
rmt = esp32.RMT(ch, pin=tx_pin, clock_div=80, tx_carrier=(freq, 30, 1), idle_level=False)

#送信
rmt.write_pulses(signal_list, 1)
rmt.wait_done(timeout=2000)        #終わるまで待つ
print("end")


■受信プログラム
#

#  ESP32 micro python system
#
# 接続
#  PL-IRM0101----------ESP32
#   VOUT             15
#
# 仕様
#  
#  赤外線リモコンの37.9KHzの搬送波から
#  パルス受信
#


import machine
from machine import Pin
import time

print("IRread Version 0.1")

pin = machine.Pin(15,Pin.IN)

rec_time = []

first = 1
HiLo = 1
while True :
  if first == 1 :
    if pin.value()==0 :
      first = 0
      HiLo=0
      timeStamp = time.ticks_us()
      #print("point 100")
  else :
    if HiLo == 0 :
      if pin.value()==1 :
        #print("point 200")
        HiLo = 1
        newTimeStamp = time.ticks_us()
        sa = newTimeStamp - timeStamp
        rec_time.append(sa)
        timeStamp = newTimeStamp
    if HiLo == 1 :
      if pin.value()==0 :
        #print("point 300")
        HiLo = 0
        newTimeStamp = time.ticks_us()
        sa = newTimeStamp - timeStamp
        rec_time.append(sa)
        timeStamp = newTimeStamp
    
    #1秒経過でループ脱出
    newTimeStamp = time.ticks_us()
    sa = newTimeStamp - timeStamp
    if sa > 1000000 :
      #print("point 400")
      break

#
#誤差を修正して表示
#  先頭32の最小をmin_intervalとして
#  並びでmin_intervalの1.4倍よりも小さいものがあったらその二つの平均を求めて
#  basic_timeにして、rec_timeの中身をbasic_timeの倍数にして取り出す
#
first = []
#
for i in range(min(len(rec_time), 32)):
    first.append(rec_time[i])
#
min_interval = min(first)
#
for i in range(32):
    if first[i] < min_interval*1.4 and first[i+1] < min_interval*1.4:
        basic_time = (first[i]+first[i+1]) // 2
        break
#time_list = [round(rec_time[i]/basic_time)*basic_time for i in range(len(rec_time))]
for i in range(len(rec_time)) :
  rec_time[i] = round(rec_time[i]/basic_time)*basic_time

#表示
out_str="["
for i in range(len(rec_time)) :
  out_str=out_str+str(rec_time[i])
  if i<len(rec_time)-1 :
    out_str=out_str+", "
out_str=out_str+"]"
print(out_str)