■ 課題8のCソース・ファイルとHEXファイルはこちらです【LZH】
■ 赤外線リモコンのこと
PIC赤外線受信ボードの課題を8までこなしました。ずいぶんとPICプログラミングに慣れてきたと思います。LEDの点滅やタクト・スイッチの使用方法はマスタできたでしょうか?。
さて、今扱っているのはPIC"赤外線受信"ボードです。赤外線受光素子を装備した立派な受信機です。が、まだ赤外線を受信したことがありません。続けて赤外線送信機ボードを製作すればよいのですが、確実に動作するハードウェアがないと動作しなかった場合に何が原因なのかを解明することができません。
そこで考えたのが、「身の回りにある動作確認ができている赤外線送信機を利用して赤外線の受信を試みる」ことです。赤外線送信機というとピンとこないかもしれませんが、"赤外線リモコン"のことです。
赤外線リモコンであれば、部屋の中にいくつか見つけることができます。TV・ビデオ・エアコン・扇風機・照明器具・トイレ?、最近はリモコン装備の電化製品がほんとうに多いですね。
多数のリモコンがある中で、たまたま100円ショップで見つけた赤外線リモコンが使えそうです。このリモコンの送信フォーマットを解析して、送信機の役割をさせることにしました。
■ 200円リモコン
パナソニックと三菱のTVやビデオに対応していると書かれているリモコンを200円で購入しました(100円ショップですが、200円以上の商品もけっこうあった)。家で愛用している10年選手のパナソニック製TVに向けて説明書通りの操作をすると、電源ON,OFFと音量調整ができました。
オシロスコープで波形を確認すると、4種類の送信フォーマットが確認できます。設定ボタンを押しながらチャネル・キーを押すと、送信フォーマットが切り替わります。パナソニックのテレビを操作できる状態にしておいて、再度オシロスコープで波形を確認し、各ボタンを押すとどのように波形が変化するかを観察しました。
赤外線リモコンに採用されているフォーマットには、大きく分けて2種類あります。NECフォーマットとSONYフォーマットです。
NECフォーマットは”H”の後の”L”の長さで0,1を判定します。SONYフォーマットは”H”の長さで0,1を判定します(共に受信状態とする)。
200円リモコンはNECフォーマットを採用しています。同じフォーマットであれば基本部分は共通ですが、データ送信部分は各社独自となっています。パナソニック製であれば、基本はNECフォーマットであっても独自部分が多いので、パナソニック・フォーマットと呼んで差し支えないと思います。
■プログラミング
今回は、オシロスコープで観測した波形からそれぞれのボタンを押したときに、LEDが点滅するようにプログラムを行いました。
// ダイソーリモコン(or パナソニック)用受信プログラム
// PIC赤外線受信ボードでダイソーリモコンのデータを受信し、
// LEDを点滅する
// 転送フォーマットはパナソニック・フォーマットとする
// 0621k27rx_daiso.c
/*
ビット・パターン [0]:Start,[1 to 5]:NON,[6 to 8]:data,[9 to 10]:予備
*/
#include<16f84a.h>
#fuses HS,NOWDT,NOPROTECT
// ウオッチドック・タイマなし、パワーアップ・タイマ使用
// プロテクトなし、MCLRなし
#use delay(CLOCK=20000000) //20MHz
#byte RA=5
#byte RB=6
#bit IRSIG=RA.2
#bit TACTSW=RA.3
#bit DOWN_LED=RB.0
#bit UP_LED=RB.2
#bit RIGHT_LED=RB.1
#bit LEFT_LED=RB.3
// CPU wait:4MHz=45,20MHz=49
#define CL_WAIT 49
#define ON 1
#define OFF 0
#define HI 1
#define LOW 0
void led_flash(int flash,d_time)
{
int i;
for(i=0;i
RB=0x0f;
delay_ms(d_time);
RB=0x00;
delay_ms(d_time);
}
}
// メイン・ルーチン
void main(){
int ird[11],i,gcount,p_count;
set_tris_a(0x0c);
set_tris_b(0x00);
led_flash(2,500);
RB=0x00;
while(1){
gcount=0;
while(gcount < 100){
if(IRSIG==HI){
delay_us(100);
gcount++;
}
else{
gcount=0;
}
}
While(IRSIG==HI){// パルス ”L”になるまで待機
}
// リモコン・データ受信開始
while(IRSIG==LOW){// リーダ部読み飛ばし
}
while(IRSIG==HI){
}
for(i=1;i<=10;i++){// データ受信スタート
p_count=0;
while(IRSIG==LOW){
}
while(IRSIG==HI){
delay_us(CL_WAIT);// 1ループ50μs
p_count=p_count+1;
if(p_count > 30){ //50*30=1500μS:1.5ms >= '1'
ird[i]=1;
}
else{
ird[i]=0;
}
}
}
// LED制御
if(ird[6]==0 && ird[7]==0 && ird[8]==0){// 全点滅
RB=0x0f;
}
if(ird[6]==0 && ird[7]==1 && ird[8]==0){// UP点滅
UP_LED=ON;
}
if(ird[6]==1 && ird[7]==1 && ird[8]==0){// DOWN点滅
DOWN_LED=ON;
}
if(ird[6]==0 && ird[7]==0 && ird[8]==1){// LEFT点滅
LEFT_LED=ON;
}
if(ird[6]==1 && ird[7]==0 && ird[8]==1){// RIGHT点滅
RIGHT_LED=ON;
}
delay_ms(100);
RB=0x00;
}
}
■ ギャップ検出ルーチン
赤外線受光素子からの出力ですが、
信号を受信したとき:”L”
無信号のとき:”H”
になっています。
信号受信を開始すると”L”・”H”が入り乱れるので、”H"が長く続く(10ms以上)と無信号であるとして、”H”の間待機します。この長い”H”をギャップと呼んでいます。ギャップを見つけるルーチンがギャップ検出ルーチンです。
while(1){// ギャップ検出ルーチン
gcount=0;
while(gcount < 100){
if(IRSIG==HI){
delay_us(100);
gcount++;
}
else{
gcount=0;
}
}
While(IRSIG==HI){// パルス”L”になるまで待機
}
■ データ受信ルーチン
ギャップの間は”H”になっています。”L”になった瞬間よりデータ受信を開始します。
最初の長い”L”と”H”の区間はリーダ部といってデータ受信前の識別信号なので、読み飛ばします。
リモコンよりの信号は全部で40ビットほど送られてきますが、ダイソーリモコンで使っているのは先頭の6、7、8ビットだけです。そこで、10ビットまで読み込み、必要なビットだけを使うことにしました。そのための配列を、
int ird[11],i,gcount,p_count;
// [0]:Start,[1 to 5]:NON,[6 to 8]:data,[9 to 10]:予備
としてird[0]~[10]まで用意しています。
このフォーマットでは”L”の後、
1.5ms以上のHi:「1」
それ以外:「0」
としています。以上に従って、作成したデータ受信部分は次のようになりました。
// リモコン・データ受信開始
while(IRSIG==LOW){// リーダ部読み飛ばし
}
while(IRSIG==HI){
}
for(i=1;i<=10;i++){// データ受信スタート
p_count=0;
while(IRSIG==LOW){
}
while(IRSIG==HI){
delay_us(CL_WAIT);// 1ループ50μs
p_count=p_count+1;
if(p_count > 30){ // 50*30=1500μs:1.5ms >= '1'
ird[i]=1;
}
else{
ird[i]=0;
}
}
}
■ LED点灯制御ルーチン
これでird[6],ird[7],ird[8]に受信データが1,0で入っています。この3ビットの組み合わせは、ird[6,7,8]の順番で次のようになります。
チャネル+:010
チャネル-:110
音量+:001
音量-:101
電源:000
赤外線リモコンとLED点滅の関係を、次のように決めました。
チャネル+:010 ・・・ UP_LED点滅
チャネル-:110 ・・・ DOWN_LED点滅
音量+:001 ・・・ LEFT_LED点滅
音量-101 ・・・ RIGHT_LED点滅
電源:000 ・・・ 全LED点滅
以上の仕様で作成したのがLED点滅ルーチンです。
if(ird[6]==0 && ird[7]==0 && ird[8]==0){//全点滅
RB=0x0f;
}
if(ird[6]==0 && ird[7]==1 && ird[8]==0){//UP点滅
UP_LED=ON;
}
if(ird[6]==1 && ird[7]==1 && ird[8]==0){//DOWN点滅
DOWN_LED=ON;
}
if(ird[6]==0 && ird[7]==0 && ird[8]==1){//LEFT点滅
LEFT_LED=ON;
}
if(ird[6]==1 && ird[7]==0 && ird[8]==1){//RIGHT点滅
RIGHT_LED=ON;
}
delay_ms(100);
RB=0x00;
■ 操作方法
パナソニック製のTVがある場合は、設定ボタンを押しながらチャネル・キー(-)を押して、パナソニック・フォーマットに設定されたことを確認してください。対応製品がない場合は、PIC赤外線受信ボードに向けて同様の操作を行い、LEDが全点滅するように設定してください。ダイソーリモコンによるPIC赤外線受信ボードの操作方法は次のようになります。
チャネル+:UP_LED点滅
チャネル-:DOWN_LED点滅
音量+:LEFT_LED点滅
音量-:RIGHT_LED点滅
電源:全LED点滅
リモコンのボタンを押してPIC赤外線受信ボードの対応するLEDが点滅すれば成功です。
■ その他のリモコンでの操作
(1) パナソニックの古いTV用リモコンでPIC赤外線受信ボードを操作したところ、ダイソーリモコンと同じ結果になりました。送信フォーマットは同じと思われます。
パナソニック製テレビ用リモコン
ダイソーリモコンと同じように操作できました。
(2)CCPハニービー送信機をPIC赤外線受信ボードに向けて操作したところ、全LEDの点滅動作が確認できました。ハニビ送信機でもPIC赤外線受信ボードの動作確認は可能です。
(3)エアロソアラの送信機よりスロットルを動かすとUP_LEDが点滅します。左右キーを動かしても同じ動きとなります。
エアロソアラ用コントローラ
(4) 同じパナソニック製でもMDラジカセ付属のリモコンでは何も反応しませんでした。
(5) データ送信部分の先頭10ビットで0を送信しているリモコンはLEDが全点滅します。これは電源ON,OFF信号と同じ扱いになるので、動作確認が可能です。
今回はパナソニックの赤外線フォーマットでプログラミングしましたが、ほかのメーカのリモコンでもなんらかの反応はあると思います。家中のリモコンのチェックを兼ねて、楽しみながらお試しください。
長野県飯田工業高校 竹内浩一

PICマイコンでつくるインドア・プレーン
みんなで作ろうインドア・プレーン