RL-78の設定と初期化関数
UART設定と送受信割込み処理は、「RL-78のUART0操作例」を参照してください。ここでのルンバ通信にはUART0を利用するとします
以下で使うサンプルプログラムのリストは、ここからダウンロードできます
UART0のTxD:ユニット0(m=0)、チャンネル0(n=0)
UART0のRxD:ユニット0(m=0)、チャンネル1(n=1)
以下は全体に関わる定義や初期化関数で、受信バッファ _gRcvBuf と送信バッファ _gSndBuf はリングバッファとして動作します
・RL-78の受信は、1バイト受信毎に割込み関数_ComRmb_IntRcvが起動され、受信データを_gRcvBuf にセットします。割込み内から割込み外処理へデータを渡すバッファです
・RL-78からの送信は、_gSndBuf にデータをセットすれば割込み関数_ComRmb_IntSndで自動的に送信処理をします。割込み外から割込み内処理にデータを渡すバッファです
・_gRcvBuf と _gSndBuf のどちらのバッファに対しても「バッファ書き込み時に書込みインデックスが読込みインデックスに追いついた場合はバッファオーバー」のエラーとする必要があります
#define M_RING_INC(a,b) (((b)<=(a+1)) ? (a=0):(a+=1)) // マクロ定義
#define C_SIZE_COM_FRAME 22 // 送受信フレームの最大長
#define C_SIZE_COM_BUF 40 // 割込内送受信バッファサイズ
#define _C_CNT_RMB_RCV_MESSAGE 52 // 受信メッセージ数
#define _C_CNT_RMB_QUELY 27 // パケットクエリー数
#define _C_CMD_RMB_STREAM 19 // CmdStream(148)に対する応答
//*************************
// UART
// 割込外送受信フレーム
//*************************
typedef struct
{
uint16_t Count; // 送受信バイト数
uint8_t Data[ C_SIZE_COM_FRAME ]; // 送受信データ
} T_COM_FRAME;
//************************
// UART
// 割込内送受信バッファ
//************************
typedef struct
{
uint16_t WriteIdx; // 書込みインデックス
uint16_t ReadIdx; // 読込みインデックス
uint8_t Buf[ C_SIZE_COM_BUF ]; // バッファ
} T_COM_BUFFER;
//*************************
// UART
// 受信ステート
//*************************
typedef enum
{
enComState_RcvStandby = 0, // 待機中
enComState_RcvStx, // STX受信済
enComState_Rcv, // データ受信中
enComState_RmbHeader, // ヘッダー待ち
enComState_RmbCount, // データ数待ち
enComState_RmbPacketId, // パケットID待ち
enComState_RmbData, // データ受信中
enComState_RmbChecksum // チェックサム待ち
} COM_RCV_STATE;
//*************************
// UART
// 受信ステータス
//*************************
typedef enum
{
enComStatus_RcvNon = 0, // 受信データなし
enComStatus_RcvAck, // ACK受信
enComStatus_RcvNack, // NAK受信
enComStatus_RcvStx, // STX受信
enComStatus_RcvDat, // データ受信中
enComStatus_RcvEtx, // フレーム受信完了
enComStatus_RcvNotStx, // 先頭がSTXでない無効データ受信
enComStatus_RcvNotEtx, // 最後がETXでない無効データ受信
enComStatus_RcvErr, // エラー発生
enComStatus_RcvNotSupported, // 未対応プロトコル
enComStatus_RcvRmbCount, // データ数待ち
enComStatus_RcvRmbPacketId, // パケットID待ち
enComStatus_RcvRmbData, // データ受信中
enComStatus_RcvRmbChecksum, // チェックサム待ち
enComStatus_RcvRmbPacketEnd, // 全パケット受信完了
enComStatus_RcvRmbErr // エラー発生
} COM_RCV_STATUS;
//*************************
// RL通信エラー
//*************************
typedef enum
{
enComErr_Non = 0, // エラーなし
enComErr_RcvIndexOver, // 受信インデックス超え
enComErr_RcvChecksum, // 受信チェックサムエラー
enComErr_RcvNotStx, // 先頭がSTXでない無効データ受信
enComErr_RcvNotEtx, // 最後がETXでない無効データ受信
enComErr_RcvNotSupported, // 未対応プロトコル受信
enComErr_RcvOverrun, // 受信バッファオーバーラン
enComErr_SndIndexOver, // 送信インデックス超え
enComErr_SndAck, // ACK送信エラー
enComErr_SndStx, // STX送信エラー
enComErr_SndFrame, // データ送信エラー
enComErr_SndChecksum, // チェックサム送信エラー
enComErr_SndEtx // ETX送信エラー
} COM_ERROR;
//*************************
// 変数
//*************************
static COM_RCV_STATE _gRcvState = enComState_RmbHeader;// 割込外フレーム受信ステート
static T_COM_FRAME _gRcvFrame = { 0 }; // 割込外受信フレーム
static uint16_t _gPacketCount = 0; // 割込外受信パケット数
static volatile BOOL _gSending = FALSE; // 割込内送信中フラグ
static volatile T_COM_BUFFER _gRcvBuf = { 0 }; // 割込内受信バッファ
static volatile T_COM_BUFFER _gSndBuf = { 0 }; // 割込内送信バッファ
T_RMB_DATA gRmbData = { 0 }; // ルンバセンサデータ
volatile COM_ERROR gRmbComError = enComErr_Non;// 送受信エラー
//************************************************************************************************
// 機能概要:通信初期化、割込許可、管理変数の初期化
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
void ComRmb_Init( void )
{
_ComRmb_Stop(); // UART停止・割込み禁止
_gRcvState = enComState_RmbHeader; // 割込外フレーム受信ステート
_gRcvFrame.Count = 0; // 割込外受信フレーム
_gPacketCount = 0; // 割込外受信パケット数
_gSending = FALSE; // 割込内送信中フラグクリア
_gRcvBuf.WriteIdx = 0; // 割込内受信バッファ 書込みインデックスクリア
_gRcvBuf.ReadIdx = 0; // 割込内受信バッファ 読込みインデックスクリア
_gSndBuf.WriteIdx = 0; // 割込内送信バッファ 書込みインデックスクリア
_gSndBuf.ReadIdx = 0; // 割込内送信バッファ 読込みインデックスクリア
gRmbComError = enComErr_Non; // 送受信エラー
_ComRmb_Start(); // UART動作・割込み許可
}
//************************************************************************************************
// 機能概要:メインから呼ぶ ComRmb_RcvFrame 関数の初期化を行う。ルンバからのストリームデータの受信で
// :同期がとれないケースのエラーに対し受信処理を初期化して同期をとる
// :この対応は初期化後の受信開始時に起きる enComErr_RcvIndexOver エラーへの対応として追加
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
void ComRmb_InitRcvFrame( void )
{
_gRcvState = enComState_RmbHeader; // 割込外フレーム受信ステート
_gRcvFrame.Count = 0; // 割込外受信フレーム
}
送受信割込み関数
送受信割込み処理は、「RL-78のUART0操作例」を参照してください。関数名称の違いだけで同じ関数です
#pragma interrupt _ComRmb_IntRcv( vect = INTSR0 )
#pragma interrupt _ComRmb_IntSnd( vect = INTST0 )
#pragma interrupt _ComRmb_IntErr( vect = INTSRE0 )
//*************************
// ビット
//*************************
#define BIT0 (0x00000001U)
#define BIT1 (0x00000002U)
#define BIT2 (0x00000004U)
#define BIT3 (0x00000008U)
#define BIT4 (0x00000010U)
#define BIT5 (0x00000020U)
#define BIT6 (0x00000040U)
#define BIT7 (0x00000080U)
//************************************************************************************************
// 機能概要 :UART動作・割込み許可
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
static void _ComRmb_Start( void )
{
SO0 |= BIT0; // 出力Hiセット
SOE0 |= BIT0; // 出力許可
SS0 |= ( BIT1 | BIT0 ); // 送受信開始
STIF0 = 0U; // 送信割込み要求フラグクリア
SRIF0 = 0U; // 受信割込み要求フラグクリア
SREIF0 = 0U; // 受信エラー割込み要求フラグクリア
STMK0 = 0U; // 送信割込み許可
SRMK0 = 0U; // 受信割込み許可
SREMK0 = 0U; // 受信エラー割込み許可
}
//************************************************************************************************
// 機能概要 :UART停止・割込み禁止
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
static void _ComRmb_Stop( void )
{
STMK0 = 1U; // 送信割込みマスク
SRMK0 = 1U; // 受信割込みマスク
SREMK0 = 1U; // 受信エラー割込みマスク
ST0 |= ( BIT1 | BIT0 ); // 送受信停止
SOE0 &= ~(BIT0); // 出力禁止
STIF0 = 0U; // 送信割込み要求フラグクリア
SRIF0 = 0U; // 受信割込み要求フラグクリア
SREIF0 = 0U; // 受信エラー割込み要求フラグクリア
}
//************************************************************************************************
// 機能概要:エラー処理。既にエラーが発生している場合はスルー
// 引数 :Error エラーメッセージ
// 戻り値 :なし
// 備考 :
//************************************************************************************************
static void _ComRmb_Error( COM_ERROR Error )
{
if(( gRmbComError != enComErr_Non ) || ( Error == enComErr_Non ))
{
return;
}
gRmbComError = Error;
}
//************************************************************************************************
// 機能概要 :受信割込みハンドラ
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
static void __near _ComRmb_IntRcv( void )
{
volatile uint8_t rx_data = RXD0; // レジスタ読込み
_gRcvBuf.Buf[ _gRcvBuf.WriteIdx ] = rx_data; // データ格納
M_RING_INC( _gRcvBuf.WriteIdx, C_SIZE_COM_BUF ); // 書込インデックス更新
if( _gRcvBuf.WriteIdx == _gRcvBuf.ReadIdx ) // 書込が読込に追いついた
{
_ComRmb_Error( enComErr_RcvOverrun ); // 受信バッファオーバーラン
return;
}
}
//************************************************************************************************
// 機能概要 :送信割込みハンドラ
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
static void __near _ComRmb_IntSnd( void )
{
if( _gSndBuf.ReadIdx == _gSndBuf.WriteIdx ) // 読込みが書込みに追いついた場合
{
/* ---< 転送完了での割込み >--- */
if(( SMR00 & 0x0001U ) == 0U )
{
_gSending = FALSE; // 転送完了
}
/* ---< 転送前のバッファ空きでの割込み >--- */
else
{
SMR00 &= ~(0x0001U); // 転送完了割込みセット
}
}
else
{
SMR00 |= 0x0001U; // 転送前のバッファ空きでの割込み/
TXD0 = _gSndBuf.Buf[ _gSndBuf.ReadIdx ]; // レジスタ書込み
M_RING_INC(_gSndBuf.ReadIdx,C_SIZE_COM_BUF); // 読込みインデックス更新
}
}
//************************************************************************************************
// 機能概要:受信エラー割込
// 引数 :なし
// 戻り値 :なし
// 備考 :
//************************************************************************************************
static void __near _ComRmb_IntErr( void )
{
volatile uint8_t err;
volatile uint8_t rx = 0;
rx |= RXD0; // ダミーリード
err = (uint8_t)( SSR01 & 0x0007U ); // エラー取得(フレーミング、パリティ、オーバーラン)
SIR01 = (uint16_t)err; // 同エラークリア
}
送受信プロトコル
ルンバへのコマンド指示は垂れ流しでコマンド(Opcode)を送信し、ルンバのセンサ情報取得はストリーム形式での送受信を行います。「ルンバとIFでの留意点・・・その1」を参照願います
コマンド(Opcode)の垂れ流しで、不明なコードが戻ることがたまにありますが無視します。RL-78からストリームコマンドを送信した場合、ルンバから不明なコードが送信されることはないので、受信はヘッダ(19)を常に監視して受信開始すれば大丈夫です
コマンド(Opcode)送信
ルンバへのコマンド(Opcode)を送信(センサコマンド除く)する関数群です
・送信は_ComRmb_Send関数に送信データの配列へのポインタと送信データ数を渡して送信します
・_ComRmb_Send関数では、_ComRmb_SetByte関数で送信データを送信バッファ_gSndBufにセットします
・_ComRmb_Send関数内で送信データをセットしたら、_ComRmb_SendStart関数で送信割込みを起動します
以下のコマンド関数群の中でリセットコマンドはルンバに無視され、Fullモードコマンドは未定義コマンドにセットされてしまうので実際には使用していません。SafeモードコマンドがFUllモードにセットされるので、Safeモードコマンドを使用しました
ストップコマンドは無視されているようですが、念のためレベルで停止時とか初期化時に使ってはいます
・スタートコマンド送信(ComRmb_CmdStart)
・Safeモードコマンド送信(ComRmb_CmdSafe)
・センサコマンド送信(ComRmb_CmdSensor)
//************************************************************************************************
// 機能概要 :コマンド関数群
// 引数 :各関数参照
// 戻り値 :TRUE(成功)、FALSE(エラー)
// 備考 :
//************************************************************************************************
//*************************
// スタートコマンド
//*************************
BOOL ComRmb_CmdStart( void )
{
return _ComRmb_SendCmd( enOpCode_Start );
}
//*************************
// リセットコマンド・・・ルンバに無視され使えない
//*************************
BOOL ComRmb_CmdReset( void )
{
return _ComRmb_SendCmd( enOpCode_Reset );
}
//*************************
// ストップコマンド・・・多分ルンバに無視され使えないが、念のため使ってはいる
//*************************
BOOL ComRmb_CmdStop( void )
{
return _ComRmb_SendCmd( enOpCode_Stop );
}
//*************************
// Safeモードコマンド・・・Fullモードになる
//*************************
BOOL ComRmb_CmdSafe( void )
{
return _ComRmb_SendCmd( enOpCode_Safe );
}
//*************************
// Fullモードコマンド・・・未定義モードになる
//*************************
BOOL ComRmb_CmdFull( void )
{
return _ComRmb_SendCmd( enOpCode_Full );
}
//*************************
// Dockコマンド
//*************************
BOOL ComRmb_CmdDock( void )
{
return _ComRmb_SendCmd( enOpCode_Dock );
}
//*************************
// パワーコマンド(電源オフ)
//*************************
BOOL ComRmb_CmdPowerOff( void )
{
return _ComRmb_SendCmd( enOpCode_PowerOff );
}
//*************************
// アクチュエータコマンド
//*************************
// SpeedL_MMPS:左タイヤ速度[mm/s]
// SpeedR_MMPS:右タイヤ速度[mm/s]
BOOL ComRmb_CmdDrive( int16_t SpeedL_MMPS, int16_t SpeedR_MMPS )
{
uint8_t spdL[ 2 ]; // 送信バイト列 速度
uint8_t spdR[ 2 ]; // 送信バイト列 速度
uint8_t frame[ 5 ]; // 送信データ
Utility_GetUint16ToBigByte( SpeedL_MMPS, spdL ); // ビッグエンディアン配列取得
Utility_GetUint16ToBigByte( SpeedR_MMPS, spdR );
frame[ 0 ] = enOpCode_DriveDirect;
frame[ 1 ] = spdR[ 0 ];
frame[ 2 ] = spdR[ 1 ];
frame[ 3 ] = spdL[ 0 ];
frame[ 4 ] = spdL[ 1 ];
return _ComRmb_Send( frame, 5 ); // 送信
}
//************************************************************************************************
// 機能概要 :送信バッファへ1バイトセットして送信する
// 引数 :Data 送信データ
// 戻り値 :TRUE(成功)、FALSE(エラー)
// 備考 :
//************************************************************************************************
static BOOL _ComRmb_SendCmd( uint8_t Data )
{
uint8_t data[ 1 ] = { Data };
return _ComRmb_Send( data, 1 );
}
//************************************************************************************************
// 機能概要 :送信バッファへ指定バイトセットして送信する
// 引数 :Data 送信データ
// :Count データ数
// 戻り値 :TRUE(成功)、FALSE(エラー)
// 備考 :
//************************************************************************************************
static BOOL _ComRmb_Send( uint8_t* Data, uint16_t Count )
{
uint16_t index;
for( index = 0; index < Count; index++ ) // メッセージ・データセット
{
if( FALSE == _ComRmb_SetByte( Data[ index ] ))
{
return FALSE;
}
}
return _ComRmb_SendStart(); // 書込みインデックス更新と送信
}
//************************************************************************************************
// 機能概要 :送信バッファへ1バイトセットする
// 引数 :Data セットするデータ
// 戻り値 :TRUE(成功)、FALSE(エラー)
// 備考 :
//************************************************************************************************
static BOOL _ComRmb_SetByte( uint8_t Data )
{
STMK0 = 1U; // 送信割込みマスク
/* ---< 送信バッファへセット >--- */
_gSndBuf.Buf[ _gSndBuf.WriteIdx ] = Data; // データ格納
M_RING_INC( _gSndBuf.WriteIdx, C_SIZE_COM_BUF ); // 書込みインデックス更新
if( _gSndBuf.ReadIdx == _gSndBuf.WriteIdx ) // 読込みインデックスに追いついた
{
_ComRmb_Error( enComErr_SndIndexOver ); // 範囲超え
return FALSE;
}
STMK0 = 0U; // 送信割込み許可
return TRUE;
}
//************************************************************************************************
// 機能概要 :送信開始
// 引数 :なし
// 戻り値 :TRUE(成功)、FALSE(エラー)
// 備考 :送信割込動作中は自動で送信されるので起動の必要なし
//************************************************************************************************
static BOOL _ComRmb_SendStart( void )
{
STMK0 = 1U; // 送信割込みマスク
/* ---< 送信データなしの場合 >--- */
if( _gSending == FALSE )
{
_gSending = TRUE;
SMR00 |= 0x0001U; // 転送前のバッファ空きでの割込み
TXD0 = _gSndBuf.Buf[ _gSndBuf.ReadIdx ]; // データをセット
M_RING_INC( _gSndBuf.ReadIdx, C_SIZE_COM_BUF );// 読込みインデックス更新
}
/* ---< 送信データありの場合 >--- */
else
{
;/* Do Nothing 割り込み処理内で書き込みインデックスまで勝手に送信する */
}
STMK0 = 0U; // 送信割込み許可
return TRUE;
}
ストリームコマンドによるセンサ要求送信
ストリーム形式での送受信を行います。ストリームコマンド(148)とパケットID数、センサデータを要求するパケットIDを並べて送信します
「148、パケット数、パケットID・・・」
送信するパケットIDを _gQuely 配列で定義します。実際に送信されるデータは、
「148、_C_CNT_RMB_QUELY、_gQuely配列内容」
となります
//*************************
// パケットクエリテーブル
//*************************
static const char _gQuely[ _C_CNT_RMB_QUELY ] =
{
enPacket_EncoderLeft, // 左タイヤエンコーダ累積値
enPacket_EncoderRight, // 右タイヤエンコーダ累積値
enPacket_LightBumpLSig, // 左ライトバンパー信号強度
enPacket_LightBumpFLSig, // 左前ライトバンパー信号強度
enPacket_LightBumpCLSig, // 左センターライトバンパー信号強度
enPacket_LightBumpCRSig, // 右センターライトバンパー信号強度
enPacket_LightBumpFRSig, // 右前ライトバンパー信号強度
enPacket_LightBumpRSig, // 右ライトバンパー信号強度
enPacket_BumpsDrop, // 乗り上げ、脱輪
enPacket_CliffLeft, // 左崖有無
enPacket_CliffFLeft, // 左前崖有無
enPacket_CliffFRight, // 右前崖有無
enPacket_CliffRight, // 右崖有無
enPacket_CliffLeftSig, // 左崖センサ信号強度
enPacket_CliffFLeftSig, // 左前崖センサ信号強度
enPacket_CliffFRightSig, // 右前崖センサ信号強度
enPacket_CliffRightSig, // 右崖センサ信号強度
enPacket_BattChargingSrc, // 充電のリソース
enPacket_BattVoltage, // バッテリ電圧[mV]
enPacket_BattCurrent, // バッテリー電流[mA]
enPacket_BattTemperature, // バッテリー温度[℃]
enPacket_BattCharge, // 現在のバッテリー充電量[mAh]
enPacket_BattCapacity, // 現在のバッテリー充電容量[mAh]
enPacket_OiMode, // 現在のモード
enPacket_Buttons, // ボタンの押下状態
enPacket_IrLeft, // 左赤外線通信
enPacket_IrRight, // 右赤外線通信
};
//*************************
// センサコマンド
//*************************
// 15ms間隔で自動的にパケット応答がくるコマンド
// 予め決めた配列から指定したパケット要求を出す
BOOL ComRmb_CmdSensor( void )
{
uint8_t index;
uint8_t frame[ _C_CNT_RMB_QUELY + 2 ] = { 0 }; // コマンド+パケット要求数の2バイト加算
/* ---< コマンドセット >--- */
frame[ 0 ] = enOpCode_Stream;
/* ---< 指定パケット抽出 >--- */
_gPacketCount = 0;
for( index = 0; index < _C_CNT_RMB_QUELY; index++ )
{
frame[ _gPacketCount + 2 ] = _gQuely[index]; // 送信用フレームバッファへパケットIDセット
_gPacketCount++;
}
/* ---< パケット要求数セット >--- */
frame[ 1 ] = _gPacketCount;
/* ---< 指定パケットのクエリ送信 >--- */
return _ComRmb_Send( frame, _gPacketCount + 2 );
}
センサデータのストリーム受信
受信データを詳細に書くと次のようになります
[19][N-bytes][Packet ID 1][Packet 1 Data…][Packet ID 2][Packet 2 Data…]・・・[Packet ID N][Packet N data…][Checksum]
・[19] ストリーム応答のヘッダ
・[N-bytes] Packet ID、Packet Data・・・Packet ID、Packet Data・・・のパケットにかかるデータバイト数
・[Packet ID] パケットID
・[Packet Data] パケットIDのデータ(データサイズはパケットIDに従う)
・[Checksum] Checksum を含めて、全通信データを合計すると0となる値が Checksum として通知される
main 関数の while 文から ComRmb_RcvFrame 関数をコールし続けて、受信エラーの場合の対処を main 関数内で行います
void main( void )
{
ComRmb_InitCom();
while( 1 )
{
if( enComStatus_RcvRmbErr == ComRmb_RcvFrame())
{
// ここにエラー処理を入れる
}
}
}
ComRmb_RcvFrame 関数を分割して説明します。関数全体は分割説明の次に添付します
ComRmb_RcvFrame 関数がmain 関数からコールされた時点で受信データなしなら戻ります。バッファへの書込み位置 WriteIdx と読込み位置 ReadIdx が同じ位置をさしていれば、処理すべき受信データはありません
受信データは、1バイト送信される毎に割込み関数 _ComRmb_IntRcv が起動され、その1バイト受信データは _gRcvBuf の Buf[] 内に格納されます。ComRmb_IntRcv 関数で1バイト受信すると WriteIdx は +1されます。リングバッファなので、バッファの最後に達したら WriteIdx は0になります。少なくとも格納された時点で WriteIdx != ReadIdx の関係(受信データあり)になります
COM_RCV_STATUS ComRmb_RcvFrame( void )
{
static uint16_t dataCount; // 1パケットのデータ数
static uint16_t packetCount; // 受信パケット数
static uint8_t checkSum; // チェックサム
uint8_t rcvData; // 1バイト受信データ
const T_MES_TBL* table; // 送受信定義テーブル
/* ---< 受信データなし >--- */
if( _gRcvBuf.ReadIdx == _gRcvBuf.WriteIdx )
{
return enComStatus_RcvNon;
}
受信データを割込み内受信バッファ _gRcvBuf から読込みます。同時に読込みインデックスを更新します。1バイト読みだしたので ReadIdx は +1、バッファの最後に達したら ReadIdx は0になります
//*************************
// 受信データ読み込み
//*************************
if( _gRcvFrame.Count >= C_SIZE_COM_FRAME )
{
_ComRmb_Error( enComErr_RcvIndexOver ); // 範囲超え
return enComStatus_RcvErr;
}
rcvData = _gRcvBuf.Buf[ _gRcvBuf.ReadIdx ]; // データ取得
M_RING_INC( _gRcvBuf.ReadIdx, C_SIZE_COM_BUF ); // 読込インデックス更新
①ヘッダー待ち処理
・受信ステート _gRcvState は初期状態でヘッダー待ち enComState_RmbHeader です。受信データがヘッダ _C_CMD_RMB_STREAM(19) でなければエラーで戻し、ヘッダならチェックサムをセットして受信処理が開始されます
・次回ステートをパケット数待ちとし戻ります
//*************************
// 受信データ解析
//*************************
switch( _gRcvState )
{
case enComState_RmbHeader: // ヘッダー待ち
if( rcvData != _C_CMD_RMB_STREAM )
{
return enComStatus_RcvRmbErr;
}
packetCount = 0; // 受信(処理済)パケット数クリア
checkSum = (uint8_t)_C_CMD_RMB_STREAM; // チェックサムセット
_gRcvState = enComState_RmbCount; // データ数待ちへ
return enComStatus_RcvRmbCount;
②パケット数待ち処理
・受信データをチェックサムに加算します。パケット数は _gPacketCount とローカル変数 packetCount で管理し、この受信データは使っていません
・次回ステートをパケットID待ちとし戻ります
case enComState_RmbCount: // データ数待ち(ヘッダー,カウント,チェックサム除くデータ)
checkSum += (uint8_t)rcvData; // チェックサム更新
_gRcvState = enComState_RmbPacketId; // パケットID待ちへ
return enComStatus_RcvRmbPacketId;
③パケットID待ち処理
・受信テーブル_gRcvTableから受信したパケットIDにあたるテーブルを取得してます。後述の「受信データ長取得関数Utility_GetTable」参照
・割込外受信フレームをクリアし、以降の受信データをここに格納していきます
・割込外受信フレームにパケットIDを格納します
・受信データをチェックサムに加算します
・次に受信するデータ長をテーブルから取得します
・次回ステートをデータ受信中とし戻ります
case enComState_RmbPacketId: // パケットID待ち
table = Utility_GetTable( rcvData, _gRcvTable, _C_CNT_RMB_PACKET_ID ); // 受信コマンドに対応したテーブル取得
if( table == NULL )
{
return enComStatus_RcvRmbErr;
}
_gRcvFrame.Count = 0; // 割込外受信フレーム
_gRcvFrame.Data[ _gRcvFrame.Count++ ] = rcvData;// パケットID
checkSum += (uint8_t)rcvData; // チェックサム更新
dataCount = table->RcvMessageLen - 1; // 1パケットのデータ数(ヘッダー受信済なので-1)
_gRcvState = enComState_RmbData; // データ受信中
return enComStatus_RcvRmbData;
④データ受信処理
・割込外受信フレームに受信データを格納します
・受信データをチェックサムに加算します
・受信データ長を減算します
・受信データが無ければ以降を処理し、受信データがあれば戻ります
・受信したパケットデータを後述の「受信データ解析関数_ComRmb_AnalizePacket」で解析し、ルンバデータgRmbDataにセットします
・受信パケット数を加算します
・受信予定パケット数_gPacketCountを全て受信したら、次回ステートをチェックサム待ちとし戻ります
・まだ受信するパケットがあれば、次回ステートをパケットID待ちとし戻ります
case enComState_RmbData: // データ受信中
_gRcvFrame.Data[_gRcvFrame.Count++]=rcvData;// データ
checkSum += (uint8_t)rcvData; // チェックサム更新
dataCount--;
if( dataCount == 0 ) // 1パケット受信完了
{
/* ---< 1パケットの解析とデータセット >--- */
if( !_ComRmb_AnalizePacket( _gRcvFrame.Data[ 0 ], (uint8_t*)( _gRcvFrame.Data + 1 )))
{
return enComStatus_RcvRmbErr;
}
packetCount++; // 受信(処理済)パケット数
if( packetCount >= _gPacketCount ) // 全パケット受信済の場合、チェックサム待ちへ
{
_gRcvState=enComState_RmbChecksum; // チェックサム待ちへ
return enComStatus_RcvRmbChecksum;
}
else
{
_gRcvState=enComState_RmbPacketId; // パケットID待ちへ
return enComStatus_RcvRmbPacketId;
}
}
return enComStatus_RcvRmbData;
⑤チェックサム待ち処理
・受信データをチェックサムに加算します
・チェックサムが0でなければエラーとして戻ります
・チェックサムが正常なら、処理完了で次回の受信に備え変数を初期化し戻ります
case enComState_RmbChecksum: // チェックサム待ち
checkSum += (uint8_t)rcvData; // チェックサム更新
if( checkSum != 0 ) // checkSum + チェックサム = 0 が正解
{
return enComStatus_RcvRmbErr;
}
/* ---< ストリーム受信完了 >--- */
packetCount = 0; // 受信(処理済)パケット数クリア
_gRcvState = enComState_RmbHeader; // ヘッダー受信待ちへ
return enComStatus_RcvRmbPacketEnd; // 全パケット受信完了
ComRmb_RcvFrame関数
//************************************************************************************************
// 機能概要:割込内の受信バッファから受信データを取り出しパケット解析する
// :複数パケットを連続受信するので、受信予定のパケット数は _gPacketCount に格納されており
// :全パケット受信・解析完了で enComStatus_RcvRmbPacketEnd を戻す
// 引数 :なし
// 戻り値 :受信状態 全パケット受信・解析完了で enComStatus_RcvRmbPacketEnd
// 備考 :
//************************************************************************************************
COM_RCV_STATUS ComRmb_RcvFrame( void )
{
static uint16_t dataCount; // 1パケットのデータ数
static uint16_t packetCount; // 受信パケット数
static uint8_t checkSum; // チェックサム
uint8_t rcvData; // 1バイト受信データ
const T_MES_TBL* table; // 送受信定義テーブル
/* ---< 受信データなし >--- */
if( _gRcvBuf.ReadIdx == _gRcvBuf.WriteIdx )
{
return enComStatus_RcvNon;
}
//*************************
// 受信データ読み込み
//*************************
if( _gRcvFrame.Count >= C_SIZE_COM_FRAME )
{
_ComRmb_Error( enComErr_RcvIndexOver ); // 範囲超え
return enComStatus_RcvErr;
}
rcvData = _gRcvBuf.Buf[ _gRcvBuf.ReadIdx ]; // データ取得
M_RING_INC( _gRcvBuf.ReadIdx, C_SIZE_COM_BUF ); // 読込インデックス更新
//*************************
// 受信データ解析
//*************************
switch( _gRcvState )
{
case enComState_RmbHeader: // ヘッダー待ち
if( rcvData != _C_CMD_RMB_STREAM )
{
return enComStatus_RcvRmbErr;
}
packetCount = 0; // 受信(処理済)パケット数クリア
checkSum = (uint8_t)_C_CMD_RMB_STREAM; // チェックサムセット
_gRcvState = enComState_RmbCount; // データ数待ちへ
return enComStatus_RcvRmbCount;
case enComState_RmbCount: // データ数待ち(ヘッダー,カウント,チェックサム除くデータ)
checkSum += (uint8_t)rcvData; // チェックサム更新
_gRcvState = enComState_RmbPacketId; // パケットID待ちへ
return enComStatus_RcvRmbPacketId;
case enComState_RmbPacketId: // パケットID待ち
table = Utility_GetTable( rcvData, _gRcvTable, _C_CNT_RMB_PACKET_ID ); // 受信コマンドに対応したテーブル取得
if( table == NULL )
{
return enComStatus_RcvRmbErr;
}
_gRcvFrame.Count = 0; // 割込外受信フレーム
_gRcvFrame.Data[_gRcvFrame.Count++]=rcvData;// パケットID
checkSum += (uint8_t)rcvData; // チェックサム更新
dataCount = table->RcvMessageLen - 1; // 1パケットのデータ数(ヘッダー受信済なので-1)
_gRcvState = enComState_RmbData; // データ受信中
return enComStatus_RcvRmbData;
case enComState_RmbData: // データ受信中
_gRcvFrame.Data[_gRcvFrame.Count++]=rcvData;// データ
checkSum += (uint8_t)rcvData; // チェックサム更新
dataCount--;
if( dataCount == 0 ) // 1パケット受信完了
{
/* ---< 1パケットの解析とデータセット >--- */
if( !_ComRmb_AnalizePacket( _gRcvFrame.Data[ 0 ], (uint8_t*)( _gRcvFrame.Data + 1 )))
{
return enComStatus_RcvRmbErr;
}
packetCount++; // 受信(処理済)パケット数
if( packetCount >= _gPacketCount ) // 全パケット受信済の場合、チェックサム待ちへ
{
_gRcvState=enComState_RmbChecksum; // チェックサム待ちへ
return enComStatus_RcvRmbChecksum;
}
else
{
_gRcvState=enComState_RmbPacketId; // パケットID待ちへ
return enComStatus_RcvRmbPacketId;
}
}
return enComStatus_RcvRmbData;
case enComState_RmbChecksum: // チェックサム待ち
checkSum += (uint8_t)rcvData; // チェックサム更新
if( checkSum != 0 ) // checkSum + チェックサム = 0 が正解
{
return enComStatus_RcvRmbErr;
}
/* ---< ストリーム受信完了 >--- */
packetCount = 0; // 受信(処理済)パケット数クリア
_gRcvState = enComState_RmbHeader; // ヘッダー受信待ちへ
return enComStatus_RcvRmbPacketEnd; // 全パケット受信完了
default:
return enComStatus_RcvRmbErr;
}
}
OpcodeとPacketID定義
RL-78から送信するコマンド(Opcode)を以下に示します。ここでのコメントは、iRobot® Create® 2 Open Interfaceから抜粋したものですが、実際にはコメント通りの動作をしないものもあります。「692で使用できなかったコマンド」参照
//*************************
// RL-78送信コマンド
// Opcode(オペレーションコード)
//*************************
typedef enum
{
/* 基本コマンドメッセージ */
enOpCode_Start = 128, // スタートコマンド
enOpCode_Reset = 7, // リセットコマンド
enOpCode_Stop = 173, // ストップコマンド
enOpCode_Baud = 129, // ボーレートコマンド
enOpCode_Safe = 131, // Safeモードコマンド
enOpCode_Full = 132, // Fullモードコマンド
/* クリーニングコマンドメッセージ */
enOpCode_Clean = 135, // クリーンコマンド
enOpCode_Max = 136, // マックスコマンド
enOpCode_Spot = 134, // スポットコマンド
enOpCode_Dock = 143, // ドックコマンド
enOpCode_PowerOff = 133, // パワーコマンド
enOpCode_Schedule = 167, // スケジュールコマンド
enOpCode_Clock = 168, // 時刻セットコマンド
/* アクチュエータコマンドメッセージ */
enOpCode_Drive = 137, // ドライブコマンド
enOpCode_DriveDirect = 145, // ドライブダイレクトコマンド
enOpCode_DrivePWM = 146, // ドライブPWMコマンド
enOpCode_Mot = 138, // モータコマンド
enOpCode_MotPWM = 144, // PWMモータコマンド
enOpCode_Led = 139, // LEDコマンド
enOpCode_LedScheduling = 162, // LEDスケジューリングLEDコマンド
enOpCode_LedDigit = 163, // LEDデジットコマンド
enOpCode_LedButton = 165, // LEDボタンコマンド
enOpCode_LedAscii = 164, // LEDアスキーコマンド
enOpCode_Song = 140, // ソングコマンド
enOpCode_Play = 141, // プレイコマンド
/* インプットコマンドメッセージ */
enOpCode_Sensor = 142, // センサーコマンド
enOpCode_Quely = 149, // クエリーリストコマンド
enOpCode_Stream = 148, // ストリームコマント
enOpCode_PauseResume = 150, // Pause/Resumeストリームコマンド
} RMB_OP_CODE;
//*************************
// RL-78センサ要求
// PacketID(パケットID)
//*************************
typedef enum
{
enPacket_BumpsDrop = 7, // Bumps and Wheel Drops
enPacket_Wall = 8, // Wall
enPacket_CliffLeft = 9, // Cliff Left
enPacket_CliffFLeft = 10, // Cliff Front Left
enPacket_CliffFRight = 11, // Cliff Front Right
enPacket_CliffRight = 12, // Cliff Right
enPacket_VirtualWall = 13, // Virtual Wall
enPacket_WheelOverCur = 14, // Wheel Overcurrents
enPacket_DirtDetect = 15, // Dirt Detect
enPacket_UnusedByte = 16, // Unused Byte
enPacket_InfraredOmni = 17, // Infrared Character Omni
enPacket_InfraredLeft = 52, // Infrared Character Left
enPacket_InfraredRight = 53, // Infrared Character Right
enPacket_Buttons = 18, // Buttons
enPacket_Distance = 19, // Distance
enPacket_Angle = 20, // Angle
enPacket_BattCharging = 21, // Charging State
enPacket_BattVoltage = 22, // Battery Voltage
enPacket_BattCurrent = 23, // Battery Current
enPacket_BattTemperature = 24, // Battery Temperature
enPacket_BattCharge = 25, // Battery Charge
enPacket_BattCapacity = 26, // Battery Capacity
enPacket_WallSig = 27, // Wall Signal
enPacket_CliffLeftSig = 28, // Cliff Left Signal
enPacket_CliffFLeftSig = 29, // Cliff Front Left Signal
enPacket_CliffFRightSig = 30, // Cliff Front Right Signal
enPacket_CliffRightSig = 31, // Cliff Right Signal
enPacket_BattChargingSrc = 34, // Charging Sources Available
enPacket_OiMode = 35, // OI Mode
enPacket_SongNumber = 36, // Song Number
enPacket_SongPlaying = 37, // Song Playing
enPacket_StreamPcks = 38, // Number of Stream Packets
enPacket_ReqVelocity = 39, // Requested Velocity
enPacket_ReqRadius = 40, // Requested Radius
enPacket_ReqRVelocity = 41, // Requested Right Velocity
enPacket_ReqLVelocity = 42, // Requested Left Velocity
enPacket_EncoderLeft = 43, // Left Encoder Counts
enPacket_EncoderRight = 44, // Right Encoder Counts
enPacket_LightBumper = 45, // Light Bumper
enPacket_LightBumpLSig = 46, // Light Bump Left Signal
enPacket_LightBumpFLSig = 47, // Light Bump Front Left Signal
enPacket_LightBumpCLSig = 48, // Light Bump Center Left Signal
enPacket_LightBumpCRSig = 49, // Light Bump Center Right Signal
enPacket_LightBumpFRSig = 50, // Light Bump Front Right Signal
enPacket_LightBumpRSig = 51, // Light Bump Right Signal
enPacket_IrLeft = 52, // Infrared Character Left
enPacket_IrRight = 53, // Infrared Character Right
enPacket_MotCurLeft = 54, // Left Motor Current
enPacket_MotCurRight = 55, // Right Motor Current
enPacket_MotCurMain = 56, // Main Brush Motor Current
enPacket_MotCurSide = 57, // Side Brush Motor Current
enPacket_Stasis = 58 // Stasis
} RMB_PACKET_ID;
ルンバのセンサ型定義
大きく「走行制御項目」「走行安全項目」「電気的安全項目」「その他項目」の分類で型定義(T_RMB_DATA)しています。その中の詳細の項目は、iRobot® Create® 2 Open Interface に従います
//*************************
// ルンバのセンサ型
//*************************
typedef enum
{
enRmbOff = 0, // オフモード
enRmbPassive, // パッシブモード
enRmbSafe, // セーフモード
enRmbFull // フルモード
} RMBMODE;
typedef union BumpsDrop
{
uint8_t Data;
struct
{
uint8_t BumpR : 1; // 右バンパー衝突
uint8_t BumpL : 1; // 左バンパー衝突
uint8_t DropR : 1; // 右脱輪
uint8_t DropL : 1; // 左脱輪
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
} BIT;
} BIT_BUMPDROP;
typedef union WheelOverCur // 過電流 1:過電流あり 0:なし
{
uint8_t Data;
struct
{
uint8_t SideB : 1; // サイドブラシ
uint8_t b1 : 1;
uint8_t MainB : 1; // メインブラシ
uint8_t WheelR : 1; // 右タイヤ
uint8_t WheelL : 1; // 左タイヤ
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
} BIT;
} BIT_WHEELOVERCUR;
typedef union Buttons // ボタンの押下状態 1:押下あり 0:なし
{
uint8_t Data;
struct
{
uint8_t Clean : 1; // Clean
uint8_t Spot : 1; // Spot
uint8_t Dock : 1; // Dock
uint8_t Minitue : 1; // Minitue
uint8_t Hour : 1; // Hour
uint8_t Day : 1; // Day
uint8_t Schedule : 1; // Schedule
uint8_t Clock : 1; // Clock
} BIT;
} BIT_BUTTONS;
typedef union ChargingSrc // 充電のリソース 1:ソースあり & 充電中 0:以外
{
uint8_t Data;
struct
{
uint8_t Inner : 1; // 内部充電器充電
uint8_t Home : 1; // ドック充電器充電
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
} BIT;
} BIT_CHARGESRC;
typedef union LightBump // ライトバンパー検出
{
uint8_t Data;
struct
{
uint8_t LightBumpL : 1; // 左ライトバンパー
uint8_t LightBumpFL : 1; // 左前ライトバンパー
uint8_t LightBumpCL : 1; // 左センターライトバンパー
uint8_t LightBumpCR : 1; // 右センターライトバンパー
uint8_t LightBumpFR : 1; // 右前ライトバンパー
uint8_t LightBumpR : 1; // 右ライトバンパー
uint8_t b6 : 1;
uint8_t b7 : 1;
} BIT;
} BIT_LIGHTBUMP;
typedef struct
{
int16_t EncoderLeft; // 左タイヤエンコーダ累積値
int16_t EncoderRight; // 右タイヤエンコーダ累積値
int16_t LightBumpLSig; // 左ライトバンパー信号強度
int16_t LightBumpFLSig; // 左前ライトバンパー信号強度
int16_t LightBumpCLSig; // 左センターライトバンパー信号強度
int16_t LightBumpCRSig; // 右センターライトバンパー信号強度
int16_t LightBumpFRSig; // 右前ライトバンパー信号強度
int16_t LightBumpRSig; // 右ライトバンパー信号強度
BIT_LIGHTBUMP LightBumper; // ライトバンパー検出
} T_MOVE_CNTL;
typedef struct
{
int16_t CliffLeftSig; // 左崖センサ信号強度
int16_t CliffFLeftSig; // 左前崖センサ信号強度
int16_t CliffFRightSig; // 右前崖センサ信号強度
int16_t CliffRightSig; // 右崖センサ信号強度
BOOL CliffLeft; // 左崖有無
BOOL CliffFLeft; // 左前崖有無
BOOL CliffFRight; // 右前崖有無
BOOL CliffRight; // 右崖有無
BIT_BUMPDROP BumpDrop; // 乗り上げ、脱輪
} T_MOVE_SAFTY;
typedef struct
{
int16_t BattVoltage; // バッテリ電圧[mV]
int16_t BattCurrent; // バッテリー電流[mA]
int16_t BattTemperature; // バッテリー温度[℃]
int16_t BattCharge; // 現在のバッテリー充電量[mAh]
int16_t BattCapacity; // 現在のバッテリー充電容量[mAh]
uint8_t BattCharging; // 充電状態
BIT_CHARGESRC BattChargingSrc; // 充電のリソース
BIT_WHEELOVERCUR WheelOverCur; // 過電流
} T_ELEC_SAFTY;
typedef struct
{
RMBMODE OiMode; // 現在のモード
BIT_BUTTONS Buttons; // ボタンの押下状態
uint8_t IrLeft; // 左赤外線通信
uint8_t IrRight; // 右赤外線通信
} T_RMB_OTHERS;
typedef struct
{
T_MOVE_CNTL MoveCntl; // 走行制御項目のセンサ情報
T_MOVE_SAFTY MoveSafty; // 走行安全項目のセンサ情報
T_ELEC_SAFTY ElecSafty; // 電気的安全項目のセンサ情報
T_RMB_OTHERS Others; // その他項目のセンサ情報
} T_RMB_DATA;
受信データ長取得関数
//************************************************************************************************
// 機能概要 :受信定義テーブルから検索メッセージのテーブルを探して戻す
// 引数 :Message 検索メッセージ
// :Table 受信定義テーブル
// :TableLength 受信定義テーブル長
// 戻り値 :検索した受信定義テーブル
// 備考 :
//************************************************************************************************
const T_MES_TBL* Utility_GetTable( uint8_t Message, const T_MES_TBL* Table, uint16_t TableLength )
{
int index;
/* ---< 検索メッセージのテーブル取得し戻す >--- */
for( index = 0; index < TableLength; index++ )
{
if( Table[ index ].Message == Message )
{
return &( Table[ index ] );
}
}
return NULL;
}
//*************************
// UART
// シリアル受信長
//*************************
typedef struct
{
uint8_t Message; // 送受信メッセージ
int16_t RcvMessageLen; // 受信メッセージ長
} T_MES_TBL;
static const T_MES_TBL _gRcvTable[ _C_CNT_RMB_PACKET_ID ] =
{
// パケットID メッセージ長(パケットID長 + データ長)
{ enPacket_BumpsDrop, ( 1 + 1 ) }, // Bumps and Wheel Drops
{ enPacket_Wall, ( 1 + 1 ) }, // Wall(非推奨)
{ enPacket_CliffLeft, ( 1 + 1 ) }, // Cliff Left
{ enPacket_CliffFLeft, ( 1 + 1 ) }, // Cliff Front Left
{ enPacket_CliffFRight, ( 1 + 1 ) }, // Cliff Front Right
{ enPacket_CliffRight, ( 1 + 1 ) }, // Cliff Right
{ enPacket_VirtualWall, ( 1 + 1 ) }, // Virtual Wall
{ enPacket_WheelOverCur, ( 1 + 1 ) }, // Wheel Overcurrents
{ enPacket_DirtDetect, ( 1 + 1 ) }, // Dirt Detect
{ enPacket_UnusedByte, ( 1 + 1 ) }, // Unused Byte
{ enPacket_InfraredOmni, ( 1 + 1 ) }, // Infrared Character Omni
{ enPacket_InfraredLeft, ( 1 + 1 ) }, // Infrared Character Left
{ enPacket_InfraredRight, ( 1 + 1 ) }, // Infrared Character Right
{ enPacket_Buttons, ( 1 + 1 ) }, // Buttons
{ enPacket_Distance, ( 1 + 2 ) }, // Distance(要バージョン確認)
{ enPacket_Angle, ( 1 + 2 ) }, // Angle(要バージョン確認)
{ enPacket_BattCharging, ( 1 + 1 ) }, // Charging State
{ enPacket_BattVoltage, ( 1 + 2 ) }, // Battery Voltage
{ enPacket_BattCurrent, ( 1 + 2 ) }, // Battery Current
{ enPacket_BattTemperature, ( 1 + 1 ) }, // Battery Temperature
{ enPacket_BattCharge, ( 1 + 2 ) }, // Battery Charge
{ enPacket_BattCapacity, ( 1 + 2 ) }, // Battery Capacity
{ enPacket_WallSig, ( 1 + 2 ) }, // Wall Signal(非推奨)
{ enPacket_CliffLeftSig, ( 1 + 2 ) }, // Cliff Left Signal
{ enPacket_CliffFLeftSig, ( 1 + 2 ) }, // Cliff Front Left Signal
{ enPacket_CliffFRightSig, ( 1 + 2 ) }, // Cliff Front Right Signal
{ enPacket_CliffRightSig, ( 1 + 2 ) }, // Cliff Right Signal
{ enPacket_BattChargingSrc, ( 1 + 1 ) }, // Charging Sources Available
{ enPacket_IrLeft, ( 1 + 1 ) }, // Infrared Character Left
{ enPacket_IrRight, ( 1 + 1 ) }, // Infrared Character Right
{ enPacket_OiMode, ( 1 + 1 ) }, // OI Mode
{ enPacket_SongNumber, ( 1 + 1 ) }, // Song Number
{ enPacket_SongPlaying, ( 1 + 1 ) }, // Song Playing
{ enPacket_StreamPcks, ( 1 + 1 ) }, // Number of Stream Packets
{ enPacket_ReqVelocity, ( 1 + 2 ) }, // Requested Velocity
{ enPacket_ReqRadius, ( 1 + 2 ) }, // Requested Radius
{ enPacket_ReqRVelocity, ( 1 + 2 ) }, // Requested Right Velocity
{ enPacket_ReqLVelocity, ( 1 + 2 ) }, // Requested Left Velocity
{ enPacket_EncoderLeft, ( 1 + 2 ) }, // Left Encoder Counts
{ enPacket_EncoderRight, ( 1 + 2 ) }, // Right Encoder Counts
{ enPacket_LightBumper, ( 1 + 1 ) }, // Light Bumper
{ enPacket_LightBumpLSig, ( 1 + 2 ) }, // Light Bump Left Signal
{ enPacket_LightBumpFLSig, ( 1 + 2 ) }, // Light Bump Front Left Signal
{ enPacket_LightBumpCLSig, ( 1 + 2 ) }, // Light Bump Center Left Signal
{ enPacket_LightBumpCRSig, ( 1 + 2 ) }, // Light Bump Center Right Signal
{ enPacket_LightBumpFRSig, ( 1 + 2 ) }, // Light Bump Front Right Signal
{ enPacket_LightBumpRSig, ( 1 + 2 ) }, // Light Bump Right Signal
{ enPacket_MotCurLeft, ( 1 + 2 ) }, // Left Motor Current
{ enPacket_MotCurRight, ( 1 + 2 ) }, // Right Motor Current
{ enPacket_MotCurMain, ( 1 + 2 ) }, // Main Brush Motor Current
{ enPacket_MotCurSide, ( 1 + 2 ) }, // Side Brush Motor Current
{ enPacket_Stasis, ( 1 + 1 ) } // Stasis
};
受信データ解析関数
static BOOL _ComRmb_AnalizePacket( uint8_t PacketId, uint8_t* Data )
{
switch( PacketId )
{
case enPacket_BumpsDrop: // 乗り上げ、脱輪
gRmbData.MoveSafty.BumpDrop.Data = Data[ 0 ];
break;
case enPacket_Wall: // 非対応
return FALSE;
case enPacket_CliffLeft: // 左崖有無
gRmbData.MoveSafty.CliffLeft = Data[ 0 ] == 0 ? FALSE : TRUE;
break;
case enPacket_CliffFLeft: // 左前崖有無
gRmbData.MoveSafty.CliffFLeft = Data[ 0 ] == 0 ? FALSE : TRUE;
break;
case enPacket_CliffFRight: // 右前崖有無
gRmbData.MoveSafty.CliffFRight = Data[ 0 ] == 0 ? FALSE : TRUE;
break;
case enPacket_CliffRight: // 右崖有無
gRmbData.MoveSafty.CliffRight = Data[ 0 ] == 0 ? FALSE : TRUE;
break;
case enPacket_WheelOverCur: // 過電流
gRmbData.ElecSafty.WheelOverCur.Data = Data[ 0 ];
break;
case enPacket_UnusedByte: // ダミーデータ 要求されたパケットが0、1、または6の場合、汚れ検出バイトの後に1つの未使用バイトが送信される
break;
case enPacket_Buttons: // ボタンの押下状態
gRmbData.Others.Buttons.Data = Data[ 0 ];
break;
case enPacket_BattCharging: // 充電状態
gRmbData.ElecSafty.BattCharging = Data[ 0 ];
break;
case enPacket_BattVoltage: // バッテリ電圧
gRmbData.ElecSafty.BattVoltage = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_BattCurrent: // バッテリー電流
gRmbData.ElecSafty.BattCurrent = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_BattTemperature: // バッテリー温度
gRmbData.ElecSafty.BattTemperature = (int16_t)Data[ 0 ];
break;
case enPacket_BattCharge: // 現在のバッテリー充電量
gRmbData.ElecSafty.BattCharge = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_BattCapacity: // 現在の推定バッテリー充電容量
gRmbData.ElecSafty.BattCapacity = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_WallSig: // 非対応
return FALSE;
case enPacket_CliffLeftSig: // 左崖センサ信号強度
gRmbData.MoveSafty.CliffLeftSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_CliffFLeftSig: // 左前崖センサ信号強度
gRmbData.MoveSafty.CliffFLeftSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_CliffFRightSig: // 右前崖センサ信号強度
gRmbData.MoveSafty.CliffFRightSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_CliffRightSig: // 右崖センサ信号強度
gRmbData.MoveSafty.CliffRightSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_BattChargingSrc: // 充電のリソース
gRmbData.ElecSafty.BattChargingSrc.Data = Data[ 0 ];
break;
case enPacket_OiMode: // 現在のモード
gRmbData.Others.OiMode = (RMBMODE)Data[ 0 ];
break;
case enPacket_EncoderLeft: // 左タイヤエンコーダ累積値
gRmbData.MoveCntl.EncoderLeft = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_EncoderRight: // 右タイヤエンコーダ累積値
gRmbData.MoveCntl.EncoderRight = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_LightBumper: // ライトバンパー検出
gRmbData.MoveCntl.LightBumper.Data = Data[ 0 ];
break;
case enPacket_LightBumpLSig: // 左ライトバンパー信号強度
gRmbData.MoveCntl.LightBumpLSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_LightBumpFLSig: // 左前ライトバンパー信号強度
gRmbData.MoveCntl.LightBumpFLSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_LightBumpCLSig: // 左センターライトバンパー信号強度
gRmbData.MoveCntl.LightBumpCLSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_LightBumpCRSig: // 右センターライトバンパー信号強度
gRmbData.MoveCntl.LightBumpCRSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_LightBumpFRSig: // 右前ライトバンパー信号強度
gRmbData.MoveCntl.LightBumpFRSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_LightBumpRSig: // 右ライトバンパー信号強度
gRmbData.MoveCntl.LightBumpRSig = (int16_t)Utility_GetBigByteToUint16( Data );
break;
case enPacket_Stasis: // 非対応
return FALSE;
case enPacket_IrLeft: // 左赤外線通信
gRmbData.Others.IrLeft = Data[ 0 ];
break;
case enPacket_IrRight: // 右赤外線通信
gRmbData.Others.IrRight = Data[ 0 ];
break;
default:
return FALSE;
}
return TRUE;
}
その他の関数
//************************************************************************************************
// 機能概要 :16ビット符号なし整数からビッグエンディアンバイト列取得
// 引数 :Data16 16ビット符号なし整数
// :Data ビッグエンディアンバイト配列
// 戻り値 :なし
// 備考 :
//************************************************************************************************
void Utility_GetUint16ToBigByte( uint16_t Data16, uint8_t* Data )
{
UINT16_UNION dat;
dat.Uint16Data = Data16;
Data[ 0 ] = dat.Data[ 1 ];
Data[ 1 ] = dat.Data[ 0 ];
}
//************************************************************************************************
// 機能概要 :ビッグエンディアンバイト列から16ビット符号なし整数取得
// 引数 :Data ビッグエンディアンバイト配列
// 戻り値 :16ビット符号なし整数
// 備考 :
//************************************************************************************************
uint16_t Utility_GetBigByteToUint16( uint8_t* Data )
{
UINT16_UNION dat;
dat.Data[ 1 ] = Data[ 0 ];
dat.Data[ 0 ] = Data[ 1 ];
return dat.Uint16Data;
}