2015-07-06

EVShield筆記(3):測試 EV3 以 I2C 連線控制 EVShield

EVShield 是作為Arduino連接 Mindstorms NXT/EV3 馬達與感應器擴展板
EVShield具備的功能中,除了 Servo pins 之外,都是透過 I2C 方式進行控制,包含:三個按鍵、兩個 RGB LED、四個 Motor ports 以及 四個 Sensor ports
而對於同樣具有 I2C 通訊
介面的 EV3主機 Sensor ports,應該也可以取代 Arduino 直接連接及運用 EVShield 的功能,以下即是對於這個需求所進行的測試記錄。


【EV3 接線方式】:
如下圖,將 EVShield 背面正下方的 4 pins I2C 接腳轉接成 RJ12 cable 之後
連接 EV3 的 Sensor Port。

【EV3 使用軟體】:
EV3 程式使用 RobotC 4.32 版。
至於 EV3 軟體,目前已知 Mindsensors 與 DI 的 EV3-I2C Programming Blocks,在功能方面並不適用。
 

EVShield I2C 架構

如下圖,EVShield 由兩個 I2C Slave 裝置所組成,分別為 Bank A ( 位址:0x34 ) 與 Bank B 0x36 ),其中 LED 與 按鍵 的控制功能都建立在 Bank A,詳細的 I2C 暫存器資訊需參考 "EVShield Advanced Development Guide文件



測試記錄  

1. RGB LED 顏色顯現

EVShield共有兩組 LED,分別位於面板的正上方 (  Front LED ) 與左下方( Rear LED ),暫存器資訊如下表:
只需將顏色值分別寫入對應的暫存器中,即可以改變 LED 顯現的顏色,以下為 RobotC 範例程式:

///////////////////////////////////////////////////////////
// @EVSH_ledSetRGB: Set Front/Rear LED RGB color value
// Front LED(0xDE) 
// Rear  LED(0xD7)
///////////////////////////////////////////////////////////
void EVSH_ledSetRGB(ubyte ledRegAddr,
      ubyte r, ubyte g, ubyte b, int delayMSec)
{
 ubyte I2C_Request[6];
 short errCnt=0;
 while(nI2CStatus[EVSHIELD] == i2cStatusPending) {  
  wait1Msec(10);
 }

 memset(I2C_Request, 6, 0);
 I2C_Request[0] = 5;
 I2C_Request[1] = EVSH_BANK_A;
 I2C_Request[2] = ledRegAddr;
 I2C_Request[3] = r;
 I2C_Request[4] = g;
 I2C_Request[5] = b;
 sendI2CMsg(EVSHIELD, &I2C_Request[0], 0);
 wait1Msec(delayMSec);
}


2. 按鍵狀態

EVShield透過 0xDA 這個暫存器位址讀取最新按鍵值
RobotC 範例程式如下:

///////////////////////////////////////////////////////////
// @EVSH_getKeyPressValue()
// Return: 1-Left, 2-Go, 4-Right
///////////////////////////////////////////////////////////
ubyte EVSH_getKeyPressValue()
{
 ubyte I2C_Request[3], I2C_Reply[1];
 short errCnt=0;
 while(nI2CStatus[EVSHIELD] == i2cStatusPending) {  
  wait1Msec(10);
 }

 memset(I2C_Request, 3, 1);
 I2C_Request[0] = 2;
 I2C_Request[1] = EVSH_BANK_A;
 I2C_Request[2] = EVSH_KEY_PRESS;
 sendI2CMsg(EVSHIELD, &I2C_Request[0], 1);
 wait1Msec(20);

 memset(I2C_Reply, 1, 0);
 while(nI2CStatus[EVSHIELD] == i2cStatusPending) wait1Msec(1);
 readI2CReply(EVSHIELD, &I2C_Reply[0], 1);
 return I2C_Reply[0];
}

3. Motor Ports控制

以EV3 透過 EVShield Motor ports 連接馬達的實務用途在於擴充 EV3 可控制的馬達數量,尤其若同時擁有 EV3 與 NXT sets,即可以單一 EV3 主機控制超過 4 顆馬達,不過此時,EVShield 即需要外接電源才能供應 Motor ports 的電力需求。

而EVShield 對於每個 Motor Port 提供三種馬達控制模式,包含:編碼值控制、Speed 控制 與 運轉時間控制等,分別有對應的暫存器,下表是 Motor 1 Port 的暫存器設定資訊:
此外,對於馬達的運轉狀態,可透過讀取下表中的暫存器值取得:
以下是控制馬達依據 設定速度 旋轉至 指定編碼值(角度) 的範例程式

//////////////////////////////////////////////////////////
// @EVSH_runMotorEncoderControl()
// encoderRegAddr: M1-0x42, M2-0x4A
//////////////////////////////////////////////////////////
void EVSH_runMotorEncoderControl(ubyte bankI2CAddr, ubyte encoderRegAddr,
                                 long encoder, short motorSpeed, bool setBraked, bool setRelPos)
{
 ubyte I2C_Request[11];
 short errCnt=0;
 while(nI2CStatus[EVSHIELD] == i2cStatusPending) {
  wait1Msec(10);
 }

 memset(I2C_Request, 11, 0);
 I2C_Request[0] = 10;
 I2C_Request[1] = bankI2CAddr;
 I2C_Request[2] = encoderRegAddr;
 I2C_Request[3] =(encoder & 0x000000FF);       // Encoder LSB
 I2C_Request[4] =(encoder & 0x0000FF00) >> 8;  // Encoder Byte2
 I2C_Request[5] =(encoder & 0x00FF0000) >> 16; // Encoder Byte3
 I2C_Request[6] =(encoder & 0xFF000000) >> 24; // Encoder MSB
 I2C_Request[7] = motorSpeed;          // Speed
 I2C_Request[8] = 0;                   // Time
 I2C_Request[9] = 0;                   // Command B
 I2C_Request[10]= 0x89;                // Command A 0b1000 1001
 if(setBraked) I2C_Request[10] = I2C_Request[10] | CMD_STOP_WITH_BRAKE;
 if(setRelPos) I2C_Request[10] = I2C_Request[10] | CMD_ENCODER_RELATIVE;
 sendI2CMsg(EVSHIELD, &I2C_Request[0], 0);
 wait1Msec(50);
 
 if(setBraked)
   while(!(EVSH_getMotorStatus(EVSH_BANK_B, EVSH_M2_STATUS) == 0x10)) delay(10); // Motor stop in brake mode
 else
   while(!(EVSH_getMotorStatus(EVSH_BANK_B, EVSH_M2_STATUS) == 0x00)) delay(10); // Motor stop in float mode

 eraseDisplay();
}

 4. Sensor Ports

EVShield 對於 Sensor Ports 的控制相當複雜,主要原因在於每個感應器的介面、功能與特性各異,因此,各個感應器皆需要實作專屬的 API,這可以參考 Mindsensors 為 EVShield 所提供的 Arduino 程式庫就可以瞭解(下載: EVShield-master ) 

因此,經以 RobotC 實作幾種類型的感應器測試,發現雖可行但比較耗費的程式開發成本,實在不太切合實際,倒不如直接連接 EV3 的 Sensor port 或 以 EVShield+Arduino 再透過 EV3 以 I2C 控制還比較實用。 

沒有留言:

張貼留言