米粒AVRでリモコン受信処理

公開日: 電子工作 | ,

米粒AVT(tiny10) リモコンレシーバー 

米粒AVR(Tiny10)で赤外線リモコンを受信して処理をするサンプルを作ってみました。 このサンプルでは、受信したリモコンの信号を解析し、3つのLEDを点けたり消したり出来ます。
対応するリモコンのデータのフォーマットは、データ長4バイトのNECフォーマットのみです。 SONY製リモコンやSHARP製のリモコンを使う場合には工夫が必要です。

赤外線リモコンを使って何かをコントロールしたい時に使えると思います。

部品リスト

部品 数量 記号 備考
ATTiny10 1 IC1 米粒AVR
赤外線センサー 1 IR1 赤外線リモコン受信モジュール
抵抗 – 1K 3 R1~3  
LED 3 LED1~3  
コンデンサ – 0.1u 2 C1, C2 積層セラミックコンデンサ
       

 

米粒AVR(Tiny10)

tiny10
この回路のメインキャスト
超小型AVRマイコン ATtiny10 米粒AVR (10個入り)

 

赤外線リモコン受信モジュール

赤外線リモコン受信モジュール OSRB38C9AA
同等のセンサーはたくさん売られていますが、利用したのは OSRB38C9AAと言うモジュール。
秋月電子で2個で100円で売られています。
赤外線リモコン受信モジュールOSRB38C9AA(2個入)
2.7Vから動作するので乾電池2本で駆動できる。
シールド付きで@50円

 

回路図

Tiny10 リモコン受信 回路図
 

※注意※ tiny10のPB3ピンは、流せる電力が小さいので、この回路図通りに作るとLED3だけ暗くなります。ブレッドボードの写真には明るさを合せるためにトランジスタを使っています。
2sc1815

 

Tiny10用ソース

#define F_CPU 8000000UL        // 2MHz以上で動作<br />
<br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <avr/sleep.h><br />
#include <util/delay.h><br />
<br />
#define LED1            PB0<br />
#define LED2            PB1<br />
#define LED3            PB3<br />
#define SENSOR1            PB2<br />
<br />
#define THRESHOLD_HEADER_HIGH_MIN        162        // 9000 * 0.9 / 50<br />
#define THRESHOLD_HEADER_HIGH_MAX        198        // 9000 * 1.1 / 50<br />
#define THRESHOLD_HEADER_LOW_MIN        81        // 4500 * 0.9 / 50<br />
#define THRESHOLD_HEADER_LOW_MAX        99        // 4500 * 1.1 / 50<br />
#define THRESHOLD_HEADER_REP_LOW_MIN    40        // 2250 * 0.9 / 50<br />
#define THRESHOLD_HEADER_REP_LOW_MAX    49        // 2250 * 1.1 / 50<br />
#define THRESHOLD_STOP_LOW_MIN            72        // 40000 * 0.9 / 50<br />
<br />
#define DATA_BYTE_COUNT        4<br />
#define DATA_BIT_COUNT        (DATA_BYTE_COUNT*8)<br />
<br />
uint8_t ch_data[][DATA_BYTE_COUNT]=<br />
{<br />
    {0x01,0x00,0x00,0x01},    // ch0<br />
    {0x01,0x00,0x00,0x02},    // ch1<br />
    {0x01,0x00,0x00,0x03},    // ch2<br />
};<br />
<br />
typedef enum<br />
{<br />
    MODE_CHECK_HEADER = 0,<br />
    MODE_ANALYZE,<br />
    MODE_RECEIVED,<br />
    MODE_REPEAT,<br />
    MODE_REPEAT_RECEIVED,<br />
    MODE_OVERFLOW = 0x10,<br />
} modeStatus;<br />
<br />
ISR(INT0_vect)<br />
{<br />
}<br />
<br />
int main(void)<br />
{<br />
    CCP = 0xD8;<br />
    CLKMSR = 0x00;<br />
    CCP = 0xD8;<br />
    #if F_CPU == 8000000UL<br />
    CLKPSR = 0x00;<br />
    #elif F_CPU == 4000000UL<br />
    CLKPSR = 0x01;<br />
    #elif F_CPU == 2000000UL<br />
    CLKPSR = 0x02;<br />
    #elif F_CPU == 1000000UL<br />
    CLKPSR = 0x03;<br />
    #endif<br />
    <br />
    DDRB |= _BV(LED1) | _BV(LED2) | _BV(LED3);<br />
    PUEB |= _BV(SENSOR1);<br />
    <br />
    PRR = _BV(PRADC) | _BV(PRTIM0);            // AD変換停止+timer0停止<br />
    EICRA = 0b00000000;                        // INT0割り込み条件(INT0ピンLowLevel)<br />
    <br />
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // パワーダウンモードに設定<br />
    sei();                                    // 全体の割り込み許可<br />
    <br />
    uint8_t data[DATA_BYTE_COUNT];<br />
    uint8_t mode;<br />
    uint8_t timeHigh,timeLow;<br />
    uint8_t fBit;<br />
    uint8_t byteCount;<br />
    uint8_t bitCount=0;<br />
<br />
    while(1)<br />
    {<br />
        EIMSK = _BV(INT0);<br />
        sleep_mode();<br />
        EIMSK &= ~_BV(INT0);<br />
        <br />
        mode=MODE_CHECK_HEADER;<br />
        <br />
        while(1)<br />
        {<br />
            timeHigh=0;<br />
            timeLow=0;<br />
        <br />
            while(!(PINB&_BV(SENSOR1)))<br />
            {<br />
                timeHigh++;<br />
                if(timeHigh==0)<br />
                {<br />
                    timeHigh=0xFF;<br />
                    while(!(PINB&_BV(SENSOR1)));<br />
                    break;<br />
                }<br />
                _delay_us(50);<br />
            }<br />
            while((PINB&_BV(SENSOR1)))<br />
            {<br />
                timeLow++;<br />
                if(timeLow==0)<br />
                {<br />
                    timeLow=0xFF;<br />
                    timeHigh=0xFF;<br />
                    break;<br />
                }                <br />
                _delay_us(50);<br />
            }<br />
<br />
            if(mode==MODE_CHECK_HEADER)<br />
            {<br />
                if(timeHigh>=THRESHOLD_HEADER_HIGH_MIN && timeHigh<=THRESHOLD_HEADER_HIGH_MAX)<br />
                {<br />
                    if(timeLow>=THRESHOLD_HEADER_LOW_MIN && timeLow<=THRESHOLD_HEADER_LOW_MAX)<br />
                    {<br />
                        mode=MODE_ANALYZE;<br />
                        fBit=0x80;<br />
                        byteCount=0;<br />
                        bitCount=0;<br />
                        data[0]=0;<br />
                        data[1]=0;<br />
                        data[2]=0;<br />
                        data[3]=0;<br />
                    }<br />
                    else if(timeLow>=THRESHOLD_HEADER_REP_LOW_MIN && timeLow<=THRESHOLD_HEADER_REP_LOW_MAX)<br />
                    {<br />
                        mode=MODE_REPEAT;<br />
                    }<br />
                }                <br />
            }<br />
            else if(mode==MODE_ANALYZE)<br />
            {<br />
                if(timeLow>=THRESHOLD_STOP_LOW_MIN)<br />
                {<br />
                    mode=MODE_RECEIVED;<br />
                }<br />
                else if(timeLow>=(timeHigh+timeHigh))<br />
                {<br />
                    data[byteCount]|=fBit;<br />
                }    <br />
                fBit>>=1;<br />
                if(fBit==0)<br />
                {<br />
                    byteCount++;<br />
                    fBit=0x80;<br />
                    if(byteCount>=DATA_BYTE_COUNT)<br />
                    {<br />
                        mode=MODE_OVERFLOW;<br />
                    }<br />
                }        <br />
                bitCount++;<br />
            }<br />
            else if(mode==MODE_REPEAT)<br />
            {<br />
                if(timeLow>=THRESHOLD_STOP_LOW_MIN)<br />
                {<br />
                    mode=MODE_REPEAT_RECEIVED;<br />
                }<br />
                else<br />
                {<br />
                    mode=MODE_OVERFLOW;<br />
                }<br />
            }                            <br />
            else if(mode==MODE_OVERFLOW)<br />
            {<br />
                if(timeLow>=THRESHOLD_STOP_LOW_MIN)<br />
                {<br />
                    mode=MODE_RECEIVED;<br />
                }<br />
            }<br />
            <br />
            if(mode==MODE_RECEIVED)<br />
            {<br />
                if(bitCount==DATA_BIT_COUNT)<br />
                {<br />
                    uint8_t ch,i;<br />
                    for(ch=0;ch<3;ch++)<br />
                    {<br />
                        for(i=0;i<DATA_BYTE_COUNT;i++)<br />
                        {<br />
                            if(ch_data[ch][i]!=data[i])<br />
                            {<br />
                                break;<br />
                            }<br />
                        }<br />
                        if(i==DATA_BYTE_COUNT)<br />
                        {<br />
                            if(ch==0)<br />
                            {<br />
                                PORTB^=_BV(LED1);<br />
                            }<br />
                            else if(ch==1)<br />
                            {<br />
                                PORTB^=_BV(LED2);<br />
                            }<br />
                            else if(ch==2)<br />
                            {<br />
                                PORTB^=_BV(LED3);<br />
                            }<br />
                            break;<br />
                        }<br />
                    }<br />
                }<br />
                break;<br />
            }<br />
            else if(mode==MODE_REPEAT_RECEIVED)<br />
            {<br />
                if(bitCount!=0)<br />
                {<br />
                }<br />
                break;<br />
            }<br />
            else if(mode==MODE_CHECK_HEADER)<br />
            {<br />
                bitCount=0;<br />
                break;<br />
            }<br />
        }<br />
        while(!(PINB&_BV(SENSOR1)));<br />
    }<br />
}<br />

このプログラムでは、PB3ピンを利用しているので、FUSEの設定でRSTDISBLにチェックを入れる必要があります。

動作周波数

このプログラムは1MHz以下では動作しません。必ず2MHz以上を指定してください。

 

リモコンのコードの指定

リモコンのコードの指定は、24行目のch_dataへ、1chにつき4バイトのコードを指定します。
送信用のリモコンも別で自作するので、ここでは実在しない(と思われる)コードを指定しています。
家電のリモコンコードが分かれば、ここに指定すると家電リモコンでもコントロールが可能です。

uint8_t ch_data[][DATA_BYTE_COUNT]=<br />
{<br />
    {0x01,0x00,0x00,0x01},    // ch0<br />
    {0x01,0x00,0x00,0x02},    // ch1<br />
    {0x01,0x00,0x00,0x03},    // ch2<br />
};<br />

 

リモコンのコード別の動作

受信したリモコンを判別して、それぞれの処理を行っているのは190行~201行です。

                            if(ch==0)<br />
                            {<br />
                                PORTB^=_BV(LED1);<br />
                            }<br />
                            else if(ch==1)<br />
                            {<br />
                                PORTB^=_BV(LED2);<br />
                            }<br />
                            else if(ch==2)<br />
                            {<br />
                                PORTB^=_BV(LED3);<br />
                            }<br />

 

 

関連記事

no image

Wimeji Client for Arduino

前回紹介したWimeji Client for WindowsXPをArduinoでやってみました。

記事を読む

no image

米粒AVRのEAGLEライブラリ

EAGLEを使って米粒AVR(ATtiny10)の回路図を書こうと思ったら何か様子がおかしい。

記事を読む

no image

Android + Arduino でリモコン2 (softmodem接続)

以前、LAN接続のリモコン Android + Arduino でリモコン と言うものを作ったのです

記事を読む

no image

Softmodem Terminal 公開しました。

需要がどれほど有るのか疑問に思いつつ、以前のエントリ(AndroidでSoftModemを試してみた

記事を読む

no image

Arduino + USBホストシールド で ADK を試す(その2)

前回「Arduino + USBホストシールド で ADK を試す(その1)」では、Androidで

記事を読む

Raspberry Piを買った

先日、Raspberry Pi(ラズベリーパイ)を買いました。 Raspberry Piは噂で

記事を読む

soundIR 送信機

赤外線リモコン送信機(イヤホンジャック接続)の回路

前回は受信機で、今回は送信機を作ってみました。 受信機と違って、送信機の作成は少し面倒です。

記事を読む

no image

AndroidでSoftModemを試してみた

今回、ここで言うSoftModemとは、携帯電話のオーディオ端子(イヤホン・マイク端子)を利用し

記事を読む

Raspberry Piのリビジョン

リビジョンの種類 現在、Rapsberry Piにはリビジョン1とリビジョン2と呼ばれる2つの

記事を読む

Androidから米粒AVRへデータを送る

米粒AVRでSoftModem的なこと その2

前回は「米粒AVRからAndroidへデータを送る」ことを試しました。 今回はその逆の「And

記事を読む

Arduinoで温湿度計 #2

今回は、前回作った温湿度計にRTCモジュールとSDカードアダプタを

Arduinoで温湿度計

秋月電子の温湿度モジュールを使って、温湿度計を作ってみました。 以前

ArduinoでSDカード

電子工作で大量のデータを保存する方法を調べていると、 Arduin

秋月のリアルタイムクロック(RTC)モジュール

今回は秋月電子のI2C接続のリアルタイムクロック(RTC)モジュールを

秋月の小型キャラクタLCD

今回秋月電子で売られている小型のキャラクター液晶2種を買ったので、

PAGE TOP ↑