Arduinoマイコンから近藤科学RCB-4HVのユーザー変数を書き換える

近藤科学ロボットコントロールボードRCB-4HVのユーザー変数を、外部のArduinoマイコンから書き換える方法を、ひとまず走り書きではあるが投稿。

近藤科学のライブラリを利用するとcomポートに繋いだArduinoマイコンから、
* RCB-4HVのI/Oポートにアクセス
* ロボットのモーション発動

等の機能を簡単に利用できるが、ユーザー変数に簡単にアクセスする関数は現在提供されていない。なので、RCB-4HVコマンドリファレンスにあるところの、MOVコマンドを生成しRCB-4に送信する必要がある

### Arduinoスケッチ例
なにげにDFRobotの画像認識モジュールHuskyLensとRCB-4の連携の簡単な例にもなっている。

~~~ cpp


const long BAUDRATE =115200;
const int TIMEOUT = 100;

Rcb4HardSerialClass rcb4(&Serial,BAUDRATE,TIMEOUT);//RCB4HardSerialClassの定義
int destAddr = 1126;       //rcb4ユーザー変数3のRAMアドレス 0x466
byte destData[] = {0,0,0,0};  //rcb4のRAMに送るデータを入れる配列
int destDataSize = 4;     //rcb4のRAMに送るデータのバイト数
byte send_rcb[11];
byte receive_rcb[4];

const int16_t objRed = 1;  //  HUSKYLENSに学習させた色のID
const int16_t objGreen = 2;  //  HUSKYLENSに学習させた色のID

int blockwidth=0;
int blockheight=0;
int x=160;
int y=120;
int16_t xDev;
String cstmtxt;

const int ledPin =  13;     //13番(PB5)には実装済みLEDがある
int buttonState = 0;

byte loopCounter =0 ;

void setup()
{
// put your setup code here, to run once:
  pinMode(ledPin, OUTPUT);      
  Wire.begin(); //I2c  

  rcb4.configData.word = 0xFFFF;  //configdata初期化
  rcb4.open();
  
 //RCB4 configdata取得と、Huskylensとの通信ができるまでループ
  while ( (!huskylens.begin(Wire)) || (rcb4.open()==false))
    {      
        digitalWrite(ledPin, HIGH);  
        delay(100);
        digitalWrite(ledPin, LOW); 
        delay(100);
        //Serial.println(("Begin failed!"));
    }

  while ( !huskylens.clearCustomText() ) { }
}


void receiveHuskylens()
{
//huskylensから認識結果受信する関数
  if ( !huskylens.request() ) { }
  else if( !huskylens.isLearned() ) { }
  else if( !huskylens.available() ) { blockwidth=0, blockheight=0, x=0, y=0; }
  else
  {
      HUSKYLENSResult result = huskylens.read();
      //digitalWrite(ledPin, HIGH);
      if (result.command == COMMAND_RETURN_BLOCK)
      {
        if(result.ID == objRed)
        {
          x = result.xCenter;
          y = result.yCenter;
          blockwidth=result.width;
          blockheight=result.height;
          //赤色認識したときユーザー変数に送り付けるデータ
          destData[2]= 0xFF; //下側8bit
          destData[3]= 0x00; //上側8bit
        }
        if(result.ID == objGreen)
        {
          x = result.xCenter;
          y = result.yCenter;
          blockwidth=result.width;
          blockheight=result.height;
        //緑色認識したときユーザー変数に送り付けるデータ
          destData[2]= 0x00; //下側8bit
          destData[3]= 0x7F; //上側8bit
        } 
      }
  }

  cstmtxt = String(x,DEC);
  cstmtxt = String("x: " + cstmtxt);
  if( !huskylens.customText(cstmtxt,220,20) ) { }
  cstmtxt = String(y,DEC);
  cstmtxt = String("y: " + cstmtxt);
  if( !huskylens.customText(cstmtxt,220,40) ) { }
  
}

void loop() 
{
// put your main code here, to run repeatedly:
 digitalWrite(ledPin, LOW); 

 buttonState = digitalRead(buttonPin);
 while( rcb4.configData.word == 0xFFFF);  //RCB4 configdataが読めてない場合ループ

 receiveHuskylens();
   while(blockwidth != 0) //認識したときblock辺長が取得されているのでループ入り
    { 
    digitalWrite(ledPin, HIGH);     
        
        //対象物の見かけの座標x,y スクリーン中点座標160,120との差からミキシング量算出
        xDev = x - 160;

        destData[0]= xDev & 0xFF; //RCB4送信用に下側8bit抽出
        destData[1]= xDev >>8;    //上側8bit抽出
        
        //rcb4ユーザー変数へミキシング量送信
        rcb4.moveComToRamCmd(send_rcb,destAddr,destData,destDataSize);//RCB4コマンドを生成し、第一引数の配列に格納する関数
        rcb4.synchronize(send_rcb, send_rcb[0], receive_rcb, 4);  //第一引数にRCB4コマンドを格納した配列を指定し、RCB4と送受信を行う。
    
        delay(105); //ウェイト関数[msec]適当な時間待機
        
    receiveHuskylens();    
    }


destData[0]=0,destData[1]=0,destData[2]=0,destData[3]=0; ;  //rcb4ユーザー変数へ0送信
rcb4.moveComToRamCmd(send_rcb,destAddr,destData,destDataSize);
rcb4.synchronize(send_rcb, send_rcb[0], receive_rcb, 4);

}

~~~

* destAddr 
 アクセスしたいユーザー変数(ここではユーザー変数3)のRAMアドレス
 値はRCB-4プログラミングマニュアルを参照
* destData[], destDataSize 
 RAMに送るデータを入れる配列とそのサイズ
 RCB-4プログラミングマニュアル記載の通り、ユーザー変数の大きさは2byte。
 なので、この例のように4byteのデータを送り付けると隣のアドレス、つまりアドレス0x468~0x469のユーザー変数4も一気に書き換えられる。
* send_rcb[11],  receive_rcb[4]
 それぞれ、生成されたMOVコマンドが格納される配列と、RCB-4からの返信が格納される配列。
 なぜ要素数がこの値なのかについてはRCB-4HVコマンドリファレンスのMOVコマンドの項を参照。

これらを引数としてmoveComToRamCmd()を実行すると、RCB-4のMOVコマンドが生成されsend_rcbに格納される。
コマンドが格納された配列、返信を受ける配列、それらの要素数を引数としてsynchronize()を実行するとRCB-4との送受信が実行される。

RCB4Library for Arduinoのドキュメントも参照のこと。



まだアプデ予定