ROBO-ONEにおいて各社のアクチュエータで異なる通信方式をDXLIBをベースとしたAPIレベルで標準化する試みが行われました。その成果物として、KRS LibraryはKONDO ICS3.0/3.5の通信プロトコルをサポートした製品をWindows等のOSから操作するためのライブラリとしてとりまとめました。
本APIを介する事でシリアル通信である事をほとんど意識すること無くアプリケーションの作りこみに専念できます。
なお、PCとDual USBアダプターHS・シリアルUSBアダプターHS・BTE061D・BTE061E・BTE068・BTE068B・BTE082のいずれかがUSBケーブルで接続され、PC上にWindowsのデバイスとして仮想COMポートが増設された状態で使用するものとします。
以下のリンクよりライブラリ及びサンプルプログラムをアーカイブしたファイルがダウンロードできます。
アーカイブファイルには以下のファイルが同梱されます。必要に応じて解凍してください。なおファイル名のサフィックスが_x32は32ビット、_x64は64ビットのWindowsアプリ用です。
| KRSLIB1.1 | krslib_x32.dll | ライブラリ本体 | |
| krslib_x64.dll | |||
| libkrslib_x32.a | GCC用ライブラリ(定義のみ) | ||
| libkrslib_x64.a | |||
| krslib_x32.llb | MSVC用ライブラリ(定義のみ) | ||
| krslib_x64.lib | |||
| krslib.c | ライブラリソース | ||
| krslib.h | ライブラリヘッダ | ||
| krsmemmap.h | 仮想メモリマップ定義ヘッダ | ||
| makelib.bat | ライブラリ再構築用バッチ コンパイルにはGCC Developer Liteとlib.exeが必要 | ||
| 83.bat | |||
| SampleCode | test1.c | C言語のサンプル | |
| test2.c | |||
| test3.c | |||
| test.vi | LabVIEWのサンプルとAPIのラッパvi | ||
| KRS_OpenPort.vi | |||
| KRS_ClosePort.vi | |||
| KRS_SetBaudrate.vi | |||
| KRS_WriteByte.vi | |||
| KRS_ReadByte.vi | |||
| KRS_WriteWord.vi | |||
| KRS_ReadWord.vi | |||
| KRS_WriteBlock.vi | |||
| KRS_ReadBlock.vi | |||
| ErrorCheck.vi | |||
ICS3.0/3.5では位置やスピードといった情報毎にパケットが異なる構造を持っており、アドレスという概念を持っていません。そこでKRSLIBではそれらの情報に対して仮想的にアドレスを持たせてアクセスする手法を採用しています。
以下に仮想メモリマップを示します。なおEEPROMデータやIDの操作は仮想メモリマップ処理から除外しているためサポートしません。
| Address | Name | Size | I/O | Range | Default |
| 0 | ID | uint8 | I | 0~31 | - |
| 1 | 位置決め制御のON/OFF | uint8 | I/O | 0:OFF/1~255:ON | 0 |
| 2 | 指令位置 | uint16 | I/O | 3000~12000 | - |
| 3 | |||||
| 4 | 指令速度 | uint8 | I/O | 1~127 | - |
| 5 | 指令ストレッチ | uint8 | I/O | 1~127 | - |
| 6 | 現在位置 | uint16 | I | - | - |
| 7 | |||||
| 8 | 現在電流 | int8 | I | - | - |
| 9 | 現在温度[degC] | int8 | I | - | - |
ライブラリの内部情報を初期化すると同時に指定されたCOMポートをオープンし、KRS_SetBaudrateを使用して通信速度を設定した後、ユニークなTDeviceIDを返す。以後はこのTDeviceIDを使用して各APIを使用する。
複数のCOMポートを使用する場合は、使用するポート毎にKRS_OpenPortを行いTDeviceIDを取得しなくてはならない。
なお、Linuxにおけるボーレートの指定に関しては、KRS_SetBaudrateの解説に注意の事。
TDeviceID KRS_OpenPort (char *name, uint32_t baud);
KRS_OpenPortで開いたCOMポートを閉じる。
KRS_ClosePortが実行された以後は指定されたTDeviceIDでの通信が行えなくなる。
bool KRS_ClosePort (TDeviceID dvid);
パケット中のコマンド部の応答をライブラリ内で削除するか否かを決定する。
デフォルトはtrue。
void KRS_SetEchoCancel (bool becho);
ホストからの送信データがホスト自ら受信されてしまうKONDO製USB I/Fを使用する場合はtrue、ホストからの送信データがホストに受信されないI/Fの場合はfalse。
TDeviceID dev;
KRS_SetEchoCancel (false); // DXHUB等を使用する場合
// オープン
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
... (中略)
// クローズ
KRS_ClosePort (dev);
}既にオープンされているTDeviceIDの通信速度の変更を行う。
実行すると強制的に受信バッファがクリアされる。
なお、Linux環境におけるボーレートの設定は、POSIX.1でサポートする値(50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000)であればtcsetattrを使用して処理するが、これらの値に当てはまらない場合はioctrlを使用する。その際I/Fがこれらのボーレートに対応していなかったり、ioctrlをサポートしない場合、本APIは失敗する。
bool KRS_SetBaudrate (TDeviceID dvid, long baud);
指定されたTDeviceIDのポートが開かれており、使用可能であるかを確認する。
USB接続等によりインターフェース自体が取り外し可能な場合に、実際に使用可能であるかを判断するために使用するが、状況によっては正確に判断できない場合もある。
bool KRS_Active (TDeviceID dvid);
I/FやOSの都合で生じるであろうタイムラグを予め設定する。
内部で算出している受信タイムアウト時間とタイムアウトオフセット時間を加算した時間を超えた場合に、タイムアウトエラーとして処理する。
デフォルトは20。
void KRS_SetTimeOutOffset (TDeviceID dvid, uint32_t offsettime);
対象IDからの応答を確認する。
bool KRS_Ping (TDeviceID dvid, uint8_t id, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31)。
エラーコード。
正常な応答が得られた場合はtrue、それ以外はfalseを返す。
TDeviceID dev;
TErrorCode err;
// オープン
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1にPINGを発行
if (KRS_Ping (dev, 1, &err))
printf ("Found [%08X]\n", err);
else
printf ("Not found [%08X]\n", err);
// クローズ
KRS_ClosePort (dev);
}対象IDのコントロールテーブルから1バイトのデータを読み出す。
bool KRS_ReadByteData(TDeviceID dvid, uint8_t id, uint8_t adr, uint8_t *rdata, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31)。
コントロールテーブルのアドレス。
読み出した値の保存先。
エラーコード。
正常な応答が得られた場合はtrue、それ以外はfalseを返す。
TDeviceID dev;
TErrorCode err;
int8_t dat;
// オープン
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1の温度を取得
if (KRS_ReadByteData (dev, 1, 9, &dat, &err)) {
printf ("TEMP=%d\n", dat);
}
KRS_ClosePort (dev);
}対象IDのコントロールテーブルへ1バイトのデータを書き込む。
bool KRS_WriteByteData(TDeviceID dvid, uint8_t id, uint8_t adr, uint8_t dat, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31, 254)。
コントロールテーブルのアドレス。
書き込む値。
エラーコード。
正常な応答が得られた場合はtrue、それ以外はfalseを返す。
BROADCASTING ID(254)を指定した場合は応答待ちを行わない。
TDeviceID dev;
TErrorCode err;
// オープン
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1の位置決め制御をONする
KRS_WriteByteData (dev, 1, 1, 1, &err);
KRS_ClosePort (dev);
}対象IDのコントロールテーブルから1ワード(2バイト)のデータを読み出す。
bool KRS_ReadWordData(TDeviceID dvid, uint8_t id, uint8_t adr, uint16_t *rdata, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31)。
コントロールテーブルのアドレス。
読み出した値の保存先。
エラーコード。
正常な応答が得られた場合はtrue、それ以外はfalseを返す。
TDeviceID dev;
TErrorCode err;
uint16_t dat;
// オープン
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1から現在位置を取得
if (KRS_ReadWordData (dev, 1, 6, &dat, &err)) {
printf ("PRESENT POS=%d\n", dat);
}
KRS_ClosePort (dev);
}対象IDのコントロールテーブルへ1ワード(2バイト)のデータを書き込む。
bool KRS_WriteWordData(TDeviceID dvid, uint8_t id, uint8_t adr, uint16_t dat, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31, 254)。
コントロールテーブルのアドレス。
書き込む値。
エラーコード。
正常な応答が得られた場合はtrue、それ以外はfalseを返す。
BROADCASTING ID(254)を指定した場合は応答待ちを行わない。
TDeviceID dev;
TErrorCode err;
// オープン
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1へ位置(7500)を指令
KRS_WriteWordData (dev, 1, 2, 7500, &err);
KRS_ClosePort (dev);
}対象IDのコントロールテーブルから指定サイズのデータを読み出す。
bool KRS_ReadBlockData (TDeviceID dvid, uint8_t id, uint8_t adr, uint8_t *rdata, uint32_t len, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31)。
コントロールテーブルのアドレス。
読み出したデータの保存先。
読み出すデータのサイズ。
エラーコード。
正常な応答が得られた場合はtrue、それ以外はfalseを返す。
TDeviceID dev;
TErrorCode err;
uint8_t dat[11];
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1から全データ(アドレス0から11バイト)を取得
if (KRS_ReadBlockData (dev, 1, 0, comp, 11, &err) {
printf (
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
dat[0], dat[1], dat[2], dat[3], dat[4],
dat[5], dat[6], dat[7], dat[8], dat[9],
dat[10]
);
}
KRS_ClosePort (dev);
}対象IDのコントロールテーブルへ指定サイズのデータを書き込む。
bool KRS_WriteBlockData(TDeviceID dvid, uint8_t id, uint8_t adr, uint8_t *dat, uint32_t len, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31, 254)。
コントロールテーブルのアドレス。
書き込むデータの保存先。
書き込むデータのサイズ。
エラーコード。
正常な応答が得られた場合はtrue、それ以外はfalseを返す。
BROADCASTING ID(254)を指定した場合は応答待ちを行わない。
#define POS 4000
#define SPEED 50
TDeviceID dev;
TErrorCode err;
uint8_t param[3];
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1へ位置と速度を指令
param[0] = POS & 0xff;
param[1] = (POS >> 8) & 0xff;
param[2] = SPEED;
KRS_WriteBlockData (dev, 1, 2, param, 3, &err);
KRS_ClosePort (dev);
}複数IDへブロック書き込みを行う。
なおDXLIBの互換性を保つために受け口として用意されたまでで、内部的にはSyncしないので注意。
書き込まれるデータの構成は使用例を参考の事。
bool KRS_WriteSyncData (TDeviceID dvid, uint8_t *dat, uint32_t size, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
書き込むパラメータの保存先。
パラメータのサイズ。
エラーコード。
インターフェースより送信が行われた場合はtrue、それ以外はfalseを返す。
#define POS1 (4000)
#define POS2 (8000)
TDeviceID dev;
TErrorCode err;
uint8_t param[8] = {
2; // 開始アドレス
2; // 1軸あたりのデータバイトサイズ
1; // 1軸目id
(POS1 & 0xFF); // data0
((POS1 >> 8) & 0xFF); // data1
2; // 2軸目id
(POS2 & 0xFF); // data0
((POS2 >> 8) & 0xFF); // data1
};
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// ID=1と2へ位置を指令
KRS_WriteSyncData (dev, param, 8, &err);
KRS_ClosePort (dev);
}任意のコマンドパケットを送信する。
bool KRS_TxPacket (TDeviceID dvid, uint8_t id, TCommand cmd, uint8_t *param, uint32_t len, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
対象とするID (0~31, 254)。
使用するコマンド。
送信するパラメータの保存先。
送信するパラメータのサイズ。
エラーコード。
インターフェースより送信が行われた場合はtrue、それ以外はfalseを返す。
TDeviceID dev;
uint8_t tx[3] = {0, 0, 0};
uint8_t rx[1];
int len;
const uint8_t reqid = 31;
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// IDの読み出し
// IDコマンド($E0|$1F,$00,$00,$00,$00)を送信する
if (KRS_TxPacket (hdev, reqid, CMD_ID, tx, 3, NULL)) {
// 1byteの応答を受信
if (KRS_RxPacket (hdev, rx, 1, &len, 100, NULL)) {
if ((rx[0] >> 5) == CMD_ID) {
printf ("Detect ID=%d\n", rx[0] & 0x1f);
}
}
}
KRS_ClosePort (dev);
}応答パケットを受信する。
基本的にKRS_TxPacketとペアで使用する。応答が得られない状況で使用するとタイムアウトするまで返らない。
なお、本APIはKRS_SetTimeOutOffsetで設定されたオフセット値は使用せず、引数で指定された受信タイムアウトのみが適用される。
bool KRS_RxPacket (TDeviceID dvid, uint8_t *rdata, uint32_t rdatasize, uint32_t *rlen, uint32_t timeout, TErrorCode *err);
KRS_OpenPortで開いた際のTDeviceID。
受信バッファ。
応答パケットを受信するのに十分なサイズを確保しておく必要がある。
rdataのサイズ。
実際に受信された応答パケットのサイズ。
受信タイムアウト[ms]。
エラーコード。
受信成功時はtrue、それ以外はfalseを返す。
#define NEWID 10
TDeviceID dev;
int len;
const uint8_t tx[3] = {1, 1, 1};
uint8_t rx[1];
dev = KRS_OpenPort ("\\\\.\\COM10", 115200);
if (dev) {
// IDの書き込み
// IDコマンド($E0|NEWID,$01,$01,$01)を送信する
if (KRS_TxPacket (hdev, NEWID, CMD_ID, (uint8_t *)tx, 3, NULL)) {
// 1byteの応答を受信
if (KRS_RxPacket (hdev, rx, 1, &len, 100, NULL)) {
if (rx[0] == ((CMD_ID << 5) | NEWID)) printf ("SUCCESS!\n");
}
}
Sleep (5); // IDコマンド直後は後処理のためにスリープが必要
KRS_ClosePort (dev);
}| bit | macro name | |
| 15 | ERR_INVALID_DEVID | 使用できないTDeviceID |
| 14 | ERR_INVALID_ID | 指定できないID |
| 13 | ERR_DIFF_ID | 異なるIDからの応答 |
| 12 | ERR_ILLEGAL_SIZE | 異常なデータサイズ |
| 11 | ERR_INVALID_PARAM | 異常なパラメータ |
| 10 | ERR_COMM | シリアルポートエラー |
| 9 | ERR_CHECKSUM | 異常なチェックサム |
| 8 | ERR_TIMEOUT | 受信タイムアウト |
| 7 | ||
| 6 | ||
| 5 | ||
| 4 | ||
| 3 | ERR_KRS_RANGE | パラメータの設定範囲を超えた |
| 2 | ||
| 1 | ||
| 0 |