赤外線送受信プログラム

HOME COMPUTER

誰かのお役に立てれば幸いです


何年か前から高専ロボコンも操縦方式の無線化が義務づけられました。
しかしながら電波無線での遠隔操作はなぜか禁止なので
使える方式は赤外線、可視光線、音波系となっています。
しかし可視光線、は強力なスポットライトを使われる会場では絶対無理。
音波は超音波を使うチームがごく少数ありますが安定度から言って避けるべきだと思います。
つまりほとんどは赤外線のみの状態です。

赤外線通信は基本的にはビット転送によるデジタル通信です。
変調周波数は38kHzが多数、混信を嫌い455kHzを使う場合もあります。

受信はICパッケージ化された赤外線受信モジュールを使うのが簡単です。

符号化はPPM(Pulse Position Modulation)と呼ばれるものが一般的です。
信号間の無信号時間によってビットを表現します。長いとH、短いとLです。
受信アルゴリズムは最初のリーダー部でのみ同期を取り、一定時間でサンプリング
するというのも考えられますがプログラムの遅延を考慮しないとすぐにエラーで受信できなくなります。
従ってアルゴリズムはビットごとに無信号状態の時間を測定するという物です。
そのようにすれば信号のエッジごとに同期を取れますので安心です。
(最初にTTLでの符号化を試みましたが全く同期が取れずほとんど使い物になりませんでした。
特に受信の仕方が難しくてあきらめました。アルゴリズムは簡単ですが多くのビットを送ろうとした場合は
絶対にお勧めしません。)

使ったマイコンはルネサスの3048Fです。(秋月のやつ)
開発環境はベストテクノロジのGCC Developer Lite です。
ヘッダーファイルもこれに入ってますのでこれでコンパイルすれば
即使えます。


送信プログラム(soshin.c)
ポート5のビット0に赤外線LEDが付いていてポート2のビット0~5がスイッチです。
スイッチはLでONなのでPCRでプルアップしています。
信号は全部で6ビット送っています。
チェックサムや反転コードなどでエラー回避すべきですが今回は簡略化のため行いませんでした。
//***************************************************************
//PPM赤外線リモコン送信プログラム Ver2.2
//2004年0730日
//
//4I YAS
//4C Outrider314
//***************************************************************

#include <3048.h>

#define LED P5.DR.BIT.B0 //出力ポート

#define RF P2.DR.BIT.B0
#define RB P2.DR.BIT.B1
#define LF P2.DR.BIT.B2
#define LB P2.DR.BIT.B3

#define UP P2.DR.BIT.B4 //リフト昇降用ボタン
#define DOWN P2.DR.BIT.B5

#define on 1
#define off 0

void wave(unsigned int time,int sw)
{



ITU1.GRA = time; // 1/2@変数timeμSを設定

ITU1.TSR.BIT.IMFA=0;
ITU.TSTR.BIT.STR0 = 1; // タイマスタート
ITU.TSTR.BIT.STR1 = 1; // タイマスタート

while(!ITU1.TSR.BIT.IMFA){
if(sw==on){
while(!ITU0.TSR.BIT.IMFA);
P5.DR.BIT.B0=~P5.DR.BIT.B0;
ITU0.TSR.BIT.IMFA=0;
}
}

LED=1;
}


int main(void)
{
P2.DDR = 0; //ポート2入力
P2.PCR.BYTE = 0xff; //プルアップMOS ON

P5.DDR = 0xff; //ポート5出力

ITU0.TCR.BIT.CCLR = 1;
ITU0.TCR.BIT.TPSC = 3; //プリスケーラ1/8設定
ITU0.GRA = 25; // 1/2@13μSを設定

ITU1.TCR.BIT.CCLR = 1;
ITU1.TCR.BIT.TPSC = 3; //プリスケーラ1/8設定

LED=1;
while(1)
{
if(RF==0|RB==0|LF==0|LB==0|UP==0|DOWN==0){

wave(17999,on);//リーダー
wave(8999,off);

wave(1099,on);
if(RF==0)wave(3379,off); else wave(1099,off);
wave(1099,on);
if(RB==0)wave(3379,off); else wave(1099,off);
wave(1099,on);
if(LF==0)wave(3379,off); else wave(1099,off);
wave(1099,on);
if(LB==0)wave(3379,off); else wave(1099,off);
wave(1099,on);
if(UP==0)wave(3379,off); else wave(1099,off);
wave(1099,on);
if(DOWN==0)wave(3379,off); else wave(1099,off);
wave(1099,on);

wave(39999,off);//80ms
wave(39999,off);
wave(39999,off);
wave(39999,off);
}
}
}


受信プログラム(jusin_v3.c)
//***************************************************************
//PPM赤外線リモコンMプログラム Ver1.4
//2004年0730日
//4C Outrider314
//4I YAS
//熊研プログラムを改修
//6bitを送信3フモーターの正転、逆転切り替え
//***************************************************************

#include <3048.h>

/* IN:P5 BIT0 ir_in */
/* OUT:P2 -> FET */

/* i/o */
#define IR P5.DR.BIT.B0
#define IMFA0 ITU0.TSR.BIT.IMFA
#define out P2.DR.BYTE

/* constant for ir_rcv */
#define Ir_On 0
#define Ir_Off 1
#define Signal_Length 6 //Mbit数w定
#define Time_Leader_On 180 /* time unit:0.05ms (no use) */
#define Time_Leader_Off 90 /* (no use) */
#define Time_Delimiter 11 /* (no use) */
#define Time_On 52 /* (no use) */
#define Time_Off 16 /* (no use) */
#define Time_Leader 40
#define TimeOut_Leader 2000
#define TimeOut 100
#define Time_Threshold 30

#define ERROR 0x00

void ioinit( void );
void IR_rcv( void );
void datout( void );
unsigned int irwait( unsigned char, unsigned int );

unsigned char rdat; /* must be global value */

/***** main *****/
int main( void )
{
int i, count,no_rcv;

ioinit();

rdat = 0; /* clear */

/* main loop */
while( 1 )
{
/* IR check */
count = 0;
if( IR == Ir_On )
{ /* IR in? */
while( IR == Ir_On )
{
if( IMFA0 )
{
IMFA0 = 0;
count++;
}
if( count >= 2 ) break;
}
if( count >= 2 )
{ /* >=0.1ms */
IR_rcv(); /* recieve */
}
}
datout(); //P2へデータ出力

//一定時間信号が来なければ停止
if(IMFA0){
IMFA0=0;
no_rcv++;
}
if(no_rcv > 1000){ //0.5s以上無信号なら停止信号代入
no_rcv=0;
out=0x00;
}
}
}

/***** IR recieve function *****/
void IR_rcv( void )
{
unsigned int i, count;

/* sense leader */
while( 1 ){ /* wait leader */
if( IR == Ir_On ){
count = irwait( Ir_On, TimeOut_Leader );
if( count >= Time_Leader ) break; /* >=Time_Leader then leader */
if( count > TimeOut_Leader ){ /* time out */
rdat = ERROR; return; }
}
if( IR == Ir_Off ){ /* no signal? */
count = irwait( Ir_Off, TimeOut_Leader );
if( count > TimeOut_Leader ){ /* time out */
rdat = ERROR; return; }
} }
count = irwait( Ir_Off, TimeOut_Leader ); /* wait delimiter */
if( count > TimeOut_Leader ){ /* time out */
rdat = ERROR; return; }

/* recieve data */
rdat = 0;
for( i=0; i<Signal_Length; i++ ){
count = irwait( Ir_On, TimeOut ); /* delimiter skip */
if( count > TimeOut ){ /* time out */
rdat = ERROR; return; }
count = irwait( Ir_Off, TimeOut ); /* width count */
if( count > TimeOut ){ /* time out */
rdat = ERROR; return; }
if( count > Time_Threshold ) rdat = (rdat <<1) + 1; /* >Time_Threshold then 1 */
else rdat = rdat <<1; /* small then 0 */
}
}

/* wait for IR -----*/
unsigned int irwait( unsigned char on_off, unsigned int timeout )
{
unsigned int count;

count = 0;
while( IR == on_off ){
if( IMFA0 ){
IMFA0 = 0;
count++;
}
if( count > timeout ) return( count ); /* time out */
}
return( count );
}


/* i/o initialize -----*/
void ioinit( void )
{
P2.DDR = 0xff; /* output */
P5.DDR = 0x00; /* input */

ITU0.TCR.BYTE = 0x22; /* on GRA, 1/4 */
ITU0.GRA = 200; /* 20kHz */
ITU.TMDR.BYTE = 0;
ITU.TSTR.BYTE = 0x01; /* ch0 start */
}

/* output to P2 */
void datout( void )
{
switch (rdat)
{
case 1 : {out = 0x20;break;}
case 2 : {out = 0x10;break;}

case 3 : {out = 0x00;break;} //エラー椏ョ作

case 4 : {out = 0x08;break;}
case 5 : {out = 0x28;break;}
case 6 : {out = 0x18;break;}

case 8 : {out = 0x04;break;}
case 9 : {out = 0x24;break;}
case 10: {out = 0x14;break;}

case 12: {out = 0x00;break;} //エラー椏ョ作
case 15: {out = 0x00;break;} //エラー椏ョ作

case 16: {out = 0x02;break;}
case 17: {out = 0x22;break;}
case 18: {out = 0x12;break;}

case 20: {out = 0x0a;break;}
case 21: {out = 0x2a;break;}
case 22: {out = 0x1a;break;}

case 24: {out = 0x06;break;}
case 25: {out = 0x26;break;}
case 26: {out = 0x16;break;}

case 32: {out = 0x01;break;}
case 33: {out = 0x21;break;}
case 34: {out = 0x11;break;}

case 36: {out = 0x09;break;}
case 37: {out = 0x29;break;}
case 38: {out = 0x19;break;}

case 40: {out = 0x05;break;}
case 41: {out = 0x25;break;}
case 42: {out = 0x15;break;}

case 48: {out = 0x00;break;} //エラー椏ョ作
case 51: {out = 0x00;break;} //エラー椏ョ作
case 60: {out = 0x00;break;} //エラー椏ョ作
case 63: {out = 0x00;break;} //エラー椏ョ作

defaule: {out = 0x00;}
}

}



ダウンロード
ソフトがなくても使えるように一応、機械語(モトローラ形式)も入れました。

--------注意--------
そのまま二次配布はやめてください。
動作は保証しません。(動作確認はしてますが)
プログラムに関して作者は一切の責任を負いません。

ダウンロード
Ir_ctrl.lzh
lzh形式 4,372 バイト
プログラムに関して意見などいただけたら幸いです。


Copyright (C) 2002 YAS All Rights Reserved

inserted by FC2 system