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

 

 

関連記事

米粒AVRでI2C通信

米粒AVRでI2C通信(マスター)

米粒AVRことATtiny10は3つまたは4つのI/Oピンしか使えないのですが、I2Cなら2つの

記事を読む

no image

Android+Arduinoでリモコン3のおまけ

Androidとは関係ないのですが、前回の記事  Android+Arduinoでリモコ

記事を読む

Raspbianの起動

Raspbianの起動画面をキャプチャしてみた。 SDカードにイメージを書き込んだままのデフォ

記事を読む

no image

S2 Resistor Color Code 公開しました。

このアプリは、抵抗のカラーコードから抵抗値を素早く見る為のAndroidアプリです。 4本帯と、5

記事を読む

no image

USBホストケーブルとUSBケーブルの違い

USBホストケーブル(OTGケーブル)と普通のUSBケーブルの違いは、USBホストケーブルとして振る

記事を読む

no image

米粒AVRでアナログ入力を試してみた

米粒AVR(ATtiny10)に搭載されている8ビット4チャンネルのアナログ入力を試してみました

記事を読む

S2 SoundIR analyzer

赤外線リモコン受信機(イヤホンジャック接続)のアプリ

 前回の赤外線リモコン受信機(イヤホンジャック接続)の回路 を使う為のAndroidア

記事を読む

no image

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

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

記事を読む

パソコンで温度計 #3

今回は、I2C接続の温度センサー STTS751をケーブルを使ってArduinoに接続できるよう

記事を読む

no image

Softmodem Terminal 公開しました。

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

記事を読む

Arduinoで温湿度計 #2

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

Arduinoで温湿度計

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

ArduinoでSDカード

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

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

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

秋月の小型キャラクタLCD

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

PAGE TOP ↑