米粒AVRでSoftModem的なこと その2
公開日:
電子工作 | Android, SoftModem, イヤホンジャック, 米粒AVR(tiny10)
前回は「米粒AVRからAndroidへデータを送る」ことを試しました。
今回はその逆の「Androidから米粒AVRへデータを送る」方法です。
前回と同じく、リモコンのプロトコルを使います。
Androidのイヤホンジャックに接続するリモコン送信機と米粒AVRで行うリモコン受信処理をくっつけるとAndroidから米粒AVRへデータを送ることができる計算です。
前回の回路で、米粒AVRからAndroidへ送ったデータを、そのまま今回の回路に送り直すことで、LEDのOn/Offを制御してみます。
回路
回路は、リモコン送信機の回路の、LED1を通常のLEDに変えて、LED2(PB3)を足した物となっています。
このLED1・LED2の点灯/消灯を、Androidでコントロールします。
Tiny10用ソース
リモコン受信処理のものを少しだけ修正して使っています。
前のリモコン受信処理ではint0割り込みを使っていたのですが、このソースではコンパレータを使うように修正しています。
コンパレータを使うとピンがどうしても2本必要になるので、本当はピンが1本ですむint0で処理したかったのですが、色々と試行錯誤するも結果うまく出来ず、コンパレータに逃げた次第ですw
#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 PB2<br /> #define LED2 PB3<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(ANA_COMP_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); // 出力設定<br /> <br /> ACSR = 0b00001011; // コンパレータ許可・割り込み許可<br /> DIDR0 = 0b00000011; // AIN0 AIN1 デジタル入力禁止<br /> PRR = _BV(PRADC) | _BV(PRTIM0); // AD変換停止+timer0停止<br /> <br /> set_sleep_mode(SLEEP_MODE_IDLE); // アイドルモードに設定<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 /> ACSR |= _BV(ACIE);<br /> sleep_mode();<br /> ACSR &= ~_BV(ACIE);<br /> <br /> mode=MODE_CHECK_HEADER;<br /> <br /> while(1)<br /> {<br /> timeHigh=0;<br /> timeLow=0;<br /> <br /> while(ACSR&_BV(ACO))<br /> {<br /> timeHigh++;<br /> if(timeHigh==0)<br /> {<br /> timeHigh=0xFF;<br /> while(ACSR&_BV(ACO));<br /> break;<br /> }<br /> _delay_us(50);<br /> }<br /> while(!(ACSR&_BV(ACO)))<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 /> 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(ACSR&_BV(ACO));<br /> }<br /> }<br />
米粒AVRのデータ受信のテスト
Androidから送る音声データは こちらのSoundIR Analyzerというリモコンデータの解析アプリを使って作ります。
まず、前回の「米粒AVRからAndroidへデータを送る」の回路を使って、スイッチ1を押した時のデータをアプリで受信して、メニューから保存を選び、「リモコン操作用ファイル」として保存しておきます。
あと、スイッチ2を押した時のデータも同様にして保存しておきます。
(この方法で作ったサウンドデータ )
次に、Androidと今回の回路を接続し、作成したサウンドデータを再生します。
再生前に予めAndroidの「音の設定」で「タッチ操作音」を消しておいて下さい。
タッチ操作音を消しておかなければ、再生しようと画面をタッチした時に別の音が混ざって正しくデータ転送できません。
スイッチ1のデータを再生すると、LED1が点灯/消灯します。同様にスイッチ2のデータを再生すれば、LED2が操作できます。
今回のプログラムでは、LEDのトグルに4バイト(32ビット)のデータの一致をチェックしています。
まだ少ししか試していませんが、割とエラーも少なく送受信できているんじゃないかと思います。
と言っても完璧では無いので、チェックサム等を付けてデータの整合性チェックは欠かせません。
関連記事
-
-
AndroidにPS2キーボードを繋いでみた
@yishiiさんの素のAndroid端末を外部のキーにより操作する実験と言う記事を参考に、Ardu
-
-
Raspberry Piを買った
先日、Raspberry Pi(ラズベリーパイ)を買いました。 Raspberry Piは噂で
-
-
パソコンで温度計 #4
前回までに作ったPC温度計のログデータを、計測と同時に撮影した映像にオーバーレイ表示(スーパーイ
-
-
ArduinoでSDカード
電子工作で大量のデータを保存する方法を調べていると、 Arduinoでも比較的簡単にSDカードを
-
-
米粒AVRでリモコン送信機
米粒AVR(tiny10)を使った赤外線リモコン送信機を作ってみました。 これで送信できるのは
-
-
そうだ、Raspberry Pi用にピンヘッダーのオス・メス変換アダプタを作ろう
Raspberry PiのI/O端子は、ピンヘッダーとなっていて、電極が出っ張ってる
-
-
Raspberry Piのスクリーンショット
ブログで使う用に、Raspberry Piのスクリーンショットを撮りたいと思った時、
-
-
SoundIRModemライブラリのサンプル
SoundIRModemライブラリは、米粒AVR(Tiny10)とAndroid端末をイ
-
-
androidで気圧・高度計(LPS331AP使用)
Androidと大気圧センサー(LPS331AP)をイヤフォンジャックで繋いで気圧と高度、ついで
-
-
Arduinoで温湿度計 #2
今回は、前回作った温湿度計にRTCモジュールとSDカードアダプタを取り付けて温湿度データロガーを
- PREV
- 米粒AVRでSoftModem的なこと
- NEXT
- SoundIRModemライブラリのサンプル