arduino を TJ3B のスレーブとして使う(その5)

次にスレーブ側arduinoからデータを返す Wire.onRequest の対応を考える。


マスター側TJ3Bのプログラムでは、スレーブ側から何か値を取得するようにしておく。


スレーブ側arduinoのプログラムは先日のプログラムを若干直しし、経過時間(ミリ秒)を返すプログラムにしてテストする。

//---------------------------------------------------------------------------
//I2C test request
//master:tj3b, slave:arduino
//---------------------------------------------------------------------------
#include <Wire.h>

//TJ3B設定
#define SUB_ADRS	0x30
#define I2C_BUFSIZE	10

typedef union {
  long bbbb;
  struct {
    byte b1;
    byte b2;
    byte b3;
    byte b4;
  };
}
U_LNG;

boolean is_received = false;
byte i2c_recv_buf[I2C_BUFSIZE]; //I2C受信バッファ
byte i2c_send_buf[I2C_BUFSIZE]; //I2C応答バッファ

void setup()
{
  //Slave addressスレーブアドレス変換
  int adrs = SUB_ADRS >> 1;
  Wire.begin(adrs);
  //マスターからの書き込み要求(R/W=0)を受けた時の割込み関数を登録
  Wire.onReceive(receiveEvent);
  //マスターからの読み出し要求(R/W=1)を受けた時の割込み関数を登録
  Wire.onRequest(requestEvent);
  Serial.begin(9600);
}

/**
  マスターからの読み出し要求(R/W=1)を受けた時の割込み関数
*/
void requestEvent()
{
  U_LNG w;
  w.bbbb = millis();

  i2c_send_buf[0] = w.b1;
  i2c_send_buf[1] = w.b2;
  i2c_send_buf[2] = w.b3;
  i2c_send_buf[3] = w.b4;
  Wire.write(i2c_send_buf, 4);
  Serial.println("request");
}

/**
   マスターからの書き込み要求(R/W=0)を受けた時の割込み関数
   @param int bytesReceived データ長(byte)
*/
void receiveEvent(int bytesReceived)
{
  for (int i = 0; i < I2C_BUFSIZE; i++) {
    if (i < bytesReceived) {
      i2c_recv_buf[i] = Wire.read();
    } else {
      i2c_recv_buf[i] = 0;
    }
  }
  is_received = true;
  Serial.println("receive");
}

void loop()
{
  U_LNG v;
  if (is_received) {
    for (int i = 0; i < I2C_BUFSIZE; i++) {
      Serial.print(i2c_recv_buf[i]);
      if (i < I2C_BUFSIZE - 1 ) {
        Serial.print(",");
      } else {
        Serial.println("");
      }
    }
    is_received = false;
  }
}


スレーブ側arduinoとマスター側TJ3Bのシリアルモニタを開き、TJ3Bでプログラムをスタートさせる。

問題なければ、次の表示が1秒毎に追記される。

  • スレーブ側arduino のシリアルモニタには、TJ3B からの要求内容を表示
  • マスター側TJ3Bのシリアルモニタには、arduinoで計測した経過時間(ミリ秒)を表示