米粒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

Android+Arduinoでリモコン3 その1(AndroidAccessory接続)

何度か、Android+リモコンのネタを書いたことがあるのですが、今回はAndroid Access

記事を読む

no image

AndroidにPS2キーボードを繋いでみた

@yishiiさんの素のAndroid端末を外部のキーにより操作する実験と言う記事を参考に、Ardu

記事を読む

no image

気になる物

HT-03Aで使えるのかどうかは知らないけど、Bluetooth-シリアルモジュール(BT-MOD1

記事を読む

soundIR 送信機

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

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

記事を読む

no image

AVRISPmk2

米粒AVR(ATtiny10)のプログラム書き込み用にAVRISPmk2を購入しました。 先人

記事を読む

Arduinoで温湿度計

Arduinoで温湿度計

秋月電子の温湿度モジュールを使って、温湿度計を作ってみました。 以前「パソコンで温度計」と言うもの

記事を読む

thermometer

パソコンで温度計 #2

今回は温度表示とログ取りアプリを作ったので公開。 前回にArduino+STTS751で作った

記事を読む

no image

AndroidでSoftModemを試してみた

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

記事を読む

no image

Android Open Accessory開発時のWiFiデバッグ

Android Open Accessory開発時のデバッグは、ADBをWiFiで接続しろと、USB

記事を読む

no image

米粒AVRのEAGLEライブラリ

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

記事を読む

Arduinoで温湿度データロガー
Arduinoで温湿度計 #2

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

Arduinoで温湿度計
Arduinoで温湿度計

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

SDカード・マイクロSDカード
ArduinoでSDカード

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

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

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

秋月電子 キャラクタLCD
秋月の小型キャラクタLCD

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

PAGE TOP ↑