フォト
2025年4月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
無料ブログはココログ

« IchigoJamとArduinoでI2Cバス通信を試してみる | トップページ | IchigoJamでアナログ入力を使った6ボタン入力 »

2015年5月 3日 (日)

IchigoJamとArduinoでI2Cバス通信を試してみる (2)

前回の続きです。

ちょっと実用的な実装をやってみました。
Arduinoに赤外線リモコン受信機能を実装して、IchigoJamからI2C経由で
参照できるようにしました。

ちなみに、IchigoJamのファームウェアのバージョンは1.0.0B6です。

Dscn3786

配線は、前回の回路に赤外線リモコン受信モジュールを追加したのみです。

01
秋月電子で販売されているPL-IRM2161-XD1 という製品を利用しました。

Arduino用のプログラムは以前作成したものを流用してます。
赤外線リモコンのフォーマットはいくつかありますが、今回はNECフォーマットのみ
の対応です。

赤外線リモコンは、その辺に転がってた中華製ポータブルプレイヤーに付属していた
ものを利用しました。カスタムコードは00FD、各ボタンに割り付けられているコードは
下記の通りです。

Dscn3787

IchigoJamでは、上記リモコンの"2"、"8"でキャラクタを上、下、"4"、"6"で左右に
移動させます。

IchigoJamのプログラム

10 'I2C IR remote
20 CLS:CLV:POKE #700,0,0
30 X=16:Y=12
40 R=I2CR(#10,#700,2,#800,4)
45 LC 0,0:?HEX$([0],4);" ";HEX$([1],4)
50 IF [0]=0 GOTO 100
60 IF [1]=#28 X=X-1:GOTO 100
70 IF [1]=#68 X=X+1:GOTO 100
80 IF [1]=#88 Y=Y-1:GOTO 100
90 IF [1]=#98 Y=Y+1
100 LC X,Y:? "O"
110 GOTO 40

40行のI2CR命令でArduinoからデータを取得しています。
取得したデータはアドレス#800から4バイト格納されます。
この#800から始まる領域は、IchigoJamの配列変数に利用されるています。
配列変数 [0] が#800~#801、[1]が#802~#803用です。
ちょっと、分かりにくですが直接配列変数に取得データをセットしています。

[0]は、既に取得しているデータかをArduinoから受け取っています。
[1]は、リモコンの押したボタンコードを受け取っています。

Arduinoのプログラム

#include <Wire.h>

// for I/O Port
#define IR    4
#if !defined(PORTD) 
 #define IR_DDR    DDRB
 #define IR_PORT   PORTB
 #define IR_PININ  PINB
#else
 #define IR_DDR    DDRD
 #define IR_PORT   PORTD
 #define IR_PININ  PIND
#endif

#define IRbitRead()    (IR_PININ&_BV(IR))
#define RC_RDH_TS      8000    // リーダコードOFF間隔  9ms判定用
#define RC_RDL_TS      4000    // リーダコードON間隔   4.5ms判定用
#define RC_BITLOW_TS   1200    // ビットデータON間隔   1.69ms判定用  
#define RC_TMOVER      8000    // タイムオバー

uint16_t ir_customCode = 0;   // カスタムコード
uint8_t ir_data = 0;          // コマンドデータ
uint8_t lfgnewData = 0;       // 新規IRデータフラグ

//
// 赤外線リモコンコード取得
// 4バイトのデータを返す
// CCCCDDdd
//    CCCC カスタムコード
//    DD   データコード
//    dd   データコードのビット反転(データチェック用)
// ただし、
//    リピートコードの場合  0
//    エラーの場合          0xFFFFFFFF
//  を返す.
//
uint32_t Read_IR() {
  uint8_t  repeat = 0;  // リピートコード検出フラグ
  uint32_t  dt    = 0;  // 赤外線リモコン読み取りデータ
  unsigned long t ;     // 信号長計測用

  // リード部の取得
  // 受信データはH/L反転で読まれる
  while(1) {
    while(IRbitRead());  // OFF検出受信待ち   
    t = micros();        // OFF検出時刻取得
    while(!IRbitRead()); // ON受信検出待ち 
    t = micros() -t;     // OFF->ONの時間間隔取得
    if (t > RC_RDH_TS) { // 9ms以上ならリーダコードとみなす
        t = micros();      // ON検出時刻取得
        while(IRbitRead());// OFF検出待ち
        t = micros() -t;   // ON->OFF時間間隔取得
        break;
    }
  }
  
  // データ部取得
  if (t < RC_RDL_TS) {
    // 0N->OFF がリピートコードの場合、データ取得はスキップ
    repeat = 1;          
  } else {
    // 0N->OFF がリダーコードの場合、データを取得
     for (uint8_t i = 0; i <32; i++) {  //32ビット分取得ループ
        // ビット開始待ち
        while(!IRbitRead());  // ON待ち
        t = micros();
        while(IRbitRead());  // OFF待ち
        t = micros() -t;
        if (t>RC_TMOVER)
          return 0xFFFFFFFF;  // エラー
        dt<<=1;
        dt |= (t>RC_BITLOW_TS) ? 1:0;     
    }
  }
  // ストップビットの待ち
  while(IRbitRead());  // OFF待ち  
  if (repeat)
    return 0;
  return dt;
}

void receiveEvent(int howMany) {
  byte d;
  //Serial.println(howMany);
  if(Wire.available()) {
      d = Wire.read()  ;
  }
}
  
// I2CマスタからのIR受信データ取得要求の処理
// 送信データ
//  属性: 0x00:新規データなし 、0x01:新規データあり
//  カスタムコード:2バイト
//  コマンドデータ:1バイト
void requestEvent() {
    byte d[4];
    d[0] = lfgnewData;
    d[1] = 0;
    d[2] = ir_data;
    d[3] = 0;
    Wire.write(d,4);
    //Serial.println("req"); 
    lfgnewData = 0;   // 新規IRデータフラグ
}

void setup() {
  IR_DDR &= ~_BV(IR);  // IRピンのみ入力設定する
  Serial.begin(115200);
  Wire.begin(0x10) ;                    // I2Cの初期化、自アドレスを8とする
  Wire.onRequest(requestEvent) ;     // 割込み関数の登録
  Wire.onReceive(receiveEvent) ; 
}

void loop() {
  uint32_t rc =  Read_IR();  // IR受信
  if (rc) {
    if (rc != 0xFFFFFFFF) {
      ir_customCode = (uint16_t)(rc>>16);
      ir_data = (uint8_t)(rc>>8&0xff);
      lfgnewData = 1;
      //Serial.print("custom="); Serial.print(ir_customCode,HEX);
      //Serial.print(" data=");  Serial.println(ir_data,HEX);
    }
  } else {
    //lfgnewData = 1;
    //serOut("Repeat\n\r");
  }
}

setup()でI2Cのスレーブの設定を行い、IchigoJamからの要求に対処するための
コールバック関数を登録しています。これは前回と同じです。

loop()ではRead_IR()で赤外線リモコン受信処理を行っています。
データを受信するまで復帰しない関数です。受信するとそのデータを変数に格納します。
非同期でのIchigoJamからのデータ要求でこの変数の値を渡しています。

IchigoJamで動かすと、赤外線リモコン操作でキャラクタが移動します。
ボタンを押すたびに移動します。押し続けても連続移動しません。
もし、押し続けてる間移動したい場合は、
Arduinoのプログラムのコメントアウトしている//lfgnewData = 1; の// をとってください。

20150503121026

なんか、これはいい感じに使えそうです。
LPC810で実装してモジュール化してもいいかも。

« IchigoJamとArduinoでI2Cバス通信を試してみる | トップページ | IchigoJamでアナログ入力を使った6ボタン入力 »

arduino」カテゴリの記事

IchigoJam」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: IchigoJamとArduinoでI2Cバス通信を試してみる (2):

« IchigoJamとArduinoでI2Cバス通信を試してみる | トップページ | IchigoJamでアナログ入力を使った6ボタン入力 »