├── ICS_library └── ICS_library.ino ├── LICENSE └── README.md /ICS_library/ICS_library.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * ICS_library.ino 3 | * 4 | * Arduino_STM32 with Kondo ICS servo library. 5 | * 6 | * MIT License 7 | * 8 | * version 0.50 9 | * 10 | * 2019/9/5 11 | * 12 | * devemin 13 | * https://github.com/devemin 14 | * https://twitter.com/devemin 15 | * 16 | * 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | 23 | //定数 24 | static const int ID_MIN = 0; 25 | static const int ID_MAX = 31; 26 | static const int ID_NUM = 32; 27 | 28 | static const int EEPROM_NOTCHANGE = -4096; 29 | 30 | static const int RETCODE_OK = 1; 31 | static const int RETCODE_ERROR_ICSREAD = -1001; //読み取りエラー、おそらくタイムアウト 32 | static const int RETCODE_ERROR_ICSWRITE = -1002; //返信コマンド内容エラー 33 | static const int RETCODE_ERROR_IDWRONG = -1003; 34 | static const int RETCODE_ERROR_OPTIONWRONG = -1004; 35 | static const int RETCODE_ERROR_RETURNDATAWRONG = -1005; 36 | static const int RETCODE_ERROR_EEPROMDATAWRONG = -1006; 37 | 38 | 39 | static const int SERIAL1_BAUDRATE = 115200; 40 | //プリメイドAI通常は115200。TeraTerm等でBluetooth RN42に接続でき、コマンド「$$$」→「D Enter確認」→「SU,92 Enter」→「D Enter確認」→電源入れ直し で921600bpsの高速設定になります。 41 | static const int SERIAL2_BAUDRATE = 1250000; 42 | static const int SERIAL3_BAUDRATE = 1250000; 43 | 44 | //デバッグ用 45 | //プリメイドAIでは、Serial1がBluetooth RN42チップにつながっています。 46 | //PCとペアリングしTeratermで接続すれば、Serial1.print() (debugPrint())で文字列が送信でき表示されるはずです。 47 | HardwareSerial *debugSer = &Serial1; 48 | void debugPrint(String str) { 49 | debugSer->print(str); //Serial1.print()によるデバッグ表示を無効にしたい場合はここをコメントアウトする 50 | } 51 | 52 | //IcsCommunicationクラスで用いるEEPROMデータ用構造体 53 | struct EEPROMdata { 54 | int stretch = EEPROM_NOTCHANGE; 55 | int speed = EEPROM_NOTCHANGE; 56 | int punch = EEPROM_NOTCHANGE; 57 | int deadband = EEPROM_NOTCHANGE; 58 | int dumping = EEPROM_NOTCHANGE; 59 | int safetimer = EEPROM_NOTCHANGE; 60 | 61 | int flag_slave = EEPROM_NOTCHANGE; 62 | int flag_rotation = EEPROM_NOTCHANGE; 63 | int flag_pwminh = EEPROM_NOTCHANGE; 64 | int flag_free = EEPROM_NOTCHANGE; //ここを変更しても書き込まない(ICSマネージャによると、読み出し参照のみとのこと) 65 | int flag_reverse = EEPROM_NOTCHANGE; 66 | 67 | int poslimithigh = EEPROM_NOTCHANGE; 68 | int poslimitlow = EEPROM_NOTCHANGE; 69 | int commspeed = EEPROM_NOTCHANGE; 70 | int temperaturelimit = EEPROM_NOTCHANGE; 71 | int currentlimit = EEPROM_NOTCHANGE; 72 | int response = EEPROM_NOTCHANGE; 73 | int offset = EEPROM_NOTCHANGE; 74 | int ID = EEPROM_NOTCHANGE; 75 | int charstretch1 = EEPROM_NOTCHANGE; 76 | int charstretch2 = EEPROM_NOTCHANGE; 77 | int charstretch3 = EEPROM_NOTCHANGE; 78 | 79 | }; 80 | 81 | 82 | class IcsCommunication 83 | { 84 | //パブリック変数 85 | public: 86 | 87 | //プライベート変数 88 | private: 89 | 90 | static const int POS_MIN = 3500; 91 | static const int POS_MAX = 11500; 92 | 93 | static const int TIMEOUT_NORMAL = 5; 94 | static const int TIMEOUT_LONG = 600; //ここのLONGタイムアウト値は、EEPROM書き込みエラーに関連してます。 95 | //エラーが出る場合、型番によってはもう少し長くする必要があるかもしれません。 96 | 97 | static const int SC_CODE_EEPROM = 0x00; 98 | static const int SC_CODE_STRETCH = 0x01; 99 | static const int SC_CODE_SPEED = 0x02; 100 | static const int SC_CODE_CURRENT = 0x03; 101 | static const int SC_CODE_TEMPERATURE = 0x04; 102 | 103 | 104 | //デバッグ用 105 | unsigned long time1, time2, time3, time4; 106 | 107 | HardwareSerial *refSer ; 108 | struct usart_reg_map *regmap ; 109 | struct usart_dev *u_dev; 110 | uint32 baudrate = 115200; 111 | uint16 timeout; 112 | bool initHigh; 113 | 114 | int retcode; 115 | int retval; 116 | 117 | //パブリック関数 118 | public: 119 | IcsCommunication(HardwareSerial &ser); 120 | 121 | //初期化 122 | bool begin(uint32 brate=115200, uint16 timeoutnum=TIMEOUT_NORMAL, bool initFlag=true ); 123 | void change_baudrate(uint32 brate); 124 | void change_timeout(uint16 timeoutnum); 125 | 126 | //サーボ移動関係 127 | int set_position(uint8 servolocalID, int val); //サーボ動作する     位置が戻り値として来る 128 | int set_position_weak(uint8 servolocalID); //サーボ脱力する     位置が戻り値として来る 129 | int set_position_weakandkeep(uint8 servolocalID); //サーボ脱力後即動作する 位置が戻り値として来る 130 | 131 | //パラメータ関数系 電源切ると設定消える 132 | int get_stretch(uint8 servolocalID); 133 | int get_speed(uint8 servolocalID); 134 | int get_current(uint8 servolocalID); 135 | int get_temperature(uint8 servolocalID); 136 | 137 | int set_stretch(uint8 servolocalID, int val); 138 | int set_speed(uint8 servolocalID, int val); 139 | int set_currentlimit(uint8 servolocalID, int val); 140 | int set_temperaturelimit(uint8 servolocalID, int val); 141 | 142 | 143 | //EEPROM系 電源切っても設定消えない 144 | int get_EEPROM(uint8 servolocalID, EEPROMdata *r_edata); 145 | int set_EEPROM(uint8 servolocalID, EEPROMdata *w_edata); 146 | 147 | void show_EEPROMbuffer(byte *checkbuf); 148 | void show_EEPROMdata(EEPROMdata *edata); 149 | 150 | //標準のIDコマンド ホストとサーボ1対1で使用する必要あり 151 | int get_ID(); 152 | int set_ID(uint8 servolocalID); 153 | 154 | bool IsServoAlive(uint8 servolocalID); 155 | 156 | //プライベート関数 157 | private: 158 | int transceive(byte *txbuf, byte *rxbuf, uint8 txsize, uint8 rxsize); 159 | int read_Param(uint8 servolocalID, byte sccode); 160 | int write_Param(uint8 servolocalID, byte sccode, int val); 161 | int read_EEPROMraw(uint8 servolocalID, byte *rxbuf); 162 | int check_EEPROMdata(EEPROMdata *edata); 163 | byte combine_2byte(byte a, byte b); 164 | }; 165 | 166 | 167 | //コンストラクタ 168 | IcsCommunication::IcsCommunication(HardwareSerial &ser) { 169 | 170 | refSer = &ser; 171 | } 172 | 173 | 174 | //初期化関数 175 | //引数: ボーレート(115200, 625000, 1250000)、タイムアウト値、500msecウェイト有無 176 | //initHighで、500msecウェイトを最初に実行するかどうか決めます。 177 | //(サーボ通信をシリアルのみとする手続き。EEPROMフラグに書き込み済なら不要) 178 | //STM32 x Arduino は、接続方法によってSerialの対応番号が変わります。 179 | //参考情報はこちら: https://qiita.com/nanbuwks/items/5a01b924b192d5d36b31 180 | //ST Linkで書き込み想定。 もしUSBシリアル接続で書き込んでいる場合には、Serial表記番号がずれます。メンドー 181 | //どうしてもUSBシリアル接続の場合の方は、対応番号(Serial1,Serial2,Serial3の対応)を適当に書き替えてください。 182 | bool IcsCommunication::begin(uint32 brate, uint16 timeoutnum, bool initFlag ) { 183 | baudrate = brate; 184 | timeout = timeoutnum; 185 | initHigh = initFlag; 186 | 187 | uint8_t IcsPin; 188 | 189 | if (refSer == &Serial1) { 190 | IcsPin = PA9; 191 | regmap = USART1_BASE; 192 | u_dev = USART1; 193 | } else if (refSer == &Serial2) { 194 | IcsPin = PA2; 195 | regmap = USART2_BASE; 196 | u_dev = USART2; 197 | } else if (refSer == &Serial3) { 198 | IcsPin = PB10; 199 | regmap = USART3_BASE; 200 | u_dev = USART3; 201 | } else { 202 | return false; 203 | } 204 | 205 | if (initHigh) { 206 | //ICSサーボ設定 信号線を起動時500msec Highにすることで、シリアル通信になる(誤ってPWMにならないよう) 207 | //さらに心配なら、別途 EEPROMのPWMINHフラグを1にする事。 208 | digitalWrite(IcsPin, HIGH); 209 | delay(550); //長めに550msec. 210 | digitalWrite(IcsPin, LOW); 211 | } 212 | 213 | //ICSサーボ通信設定 (8bit, EVEN) 214 | refSer->begin(baudrate,SERIAL_8E1); 215 | refSer->setTimeout(timeout); 216 | 217 | //1-wire USART 用オープンドレイン設定 設定すると動かなかった、不要? 218 | //pinMode(IcsPin, OUTPUT_OPEN_DRAIN); 219 | 220 | //HDSELビットをオンにし、1-wire USARTを有効にする 221 | regmap->CR3 = regmap->CR3 | 0b00000000000000000000000000001000; 222 | 223 | return true; 224 | } 225 | 226 | //ボーレート変更関数 いつでも変更可能 227 | //ICSでは115200, 625000, 1250000 のみ対応 228 | void IcsCommunication::change_baudrate(uint32 brate) { 229 | 230 | usart_set_baud_rate(u_dev, USART_USE_PCLK, brate); 231 | } 232 | 233 | 234 | //タイムアウト値変更関数 235 | void IcsCommunication::change_timeout(uint16 timeoutnum) { 236 | 237 | timeout = timeoutnum; 238 | refSer->setTimeout(timeout); 239 | } 240 | 241 | 242 | //基本的なサーボとのデータ送受信関数 すべてのベース 243 | //引数: 送信バッファ、受信バッファ、送信サイズ、受信サイズ 244 | int IcsCommunication::transceive(byte *txbuf, byte *rxbuf, uint8 txsize, uint8 rxsize) { 245 | 246 | int retLen; 247 | byte tmpbyte = txbuf[0]; //デバッグ用 248 | 249 | //TXビット オン / RXビット オフ 250 | regmap->CR1 = (regmap->CR1 & 0b111111111111111111111111111110011) | 0b000000000000000000000000000001000; 251 | 252 | refSer->flush(); 253 | time1 = micros(); //デバッグ用 254 | retLen = refSer->write(txbuf,txsize); 255 | time2 = micros(); //デバッグ用 256 | refSer->flush(); 257 | 258 | //送信終わったのでtxbuf をゼロに(安全のため) 259 | for (int a=0; aCR1 = (regmap->CR1 & 0b111111111111111111111111111110011) | 0b000000000000000000000000000000100; 270 | 271 | //受信前なのでrxbuf をゼロに 272 | for (int a=0; aavailable() > 0) //受信バッファの空読み 282 | { 283 | refSer->read(); 284 | } 285 | time3 = micros(); //デバッグ用 286 | retLen = refSer->readBytes(rxbuf,rxsize); 287 | time4 = micros(); //デバッグ用 288 | 289 | if (retLen != rxsize) 290 | { 291 | //error 292 | //debugPrint("RETCODE_ERROR_ICSWRITE: retLen: " + String(retLen) + ", rxsize: " + String(rxsize) + "\r\n"); 293 | return RETCODE_ERROR_ICSWRITE; 294 | } 295 | 296 | //デバッグ用 297 | //debugPrint("transcieve: CMD " + String(tmpbyte,HEX) + ", " + String(time1) + ", " + String(time2) + ", " + String(time3) + ", " + String(time4) + ", " + "\r\n"); 298 | 299 | return RETCODE_OK; 300 | } 301 | 302 | 303 | 304 | 305 | //////////////////////////////////////////////////////////////////////////////////// 306 | //////////////////////////////////////////////////////////////////////////////////// 307 | //サーボ制御系 308 | 309 | //補足:サーボポジションの戻り値は、3500-11500範囲より少しだけ超える値が返ることもある(3481, 11541とか) 310 | 311 | //サーボ位置移動 312 | //引数:サーボID、ポジション値(3500-11500) 313 | //戻り値に現在位置が入ります。 314 | int IcsCommunication::set_position(uint8 servolocalID, int val) { 315 | int txsize = 3; //この関数固有の、送信データバイト数 316 | int rxsize = 3; //この関数固有の、受信データバイト数 317 | byte txbuf[3]; 318 | byte rxbuf[3]; 319 | 320 | for (int a=0; a ID_MAX)) { 329 | return RETCODE_ERROR_OPTIONWRONG; 330 | } 331 | if ((val < POS_MIN) || (val > POS_MAX)) { 332 | return RETCODE_ERROR_OPTIONWRONG; 333 | } 334 | 335 | //送信データ作成 336 | txbuf[0] = 0x80 | servolocalID; 337 | txbuf[1] = val >> 7; 338 | txbuf[2] = val & 0b0000000001111111; 339 | 340 | //ICS送信 341 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 342 | 343 | //受信データ確認 344 | if (retcode == RETCODE_OK) { 345 | if ((rxbuf[0] & 0b01111111) == servolocalID) { 346 | retval = (rxbuf[1] << 7) + (rxbuf[2]); 347 | return retval; 348 | } else { 349 | return RETCODE_ERROR_IDWRONG; 350 | } 351 | } else { 352 | //error 353 | return retcode; 354 | } 355 | } 356 | 357 | 358 | 359 | //サーボ脱力 360 | //戻り値に現在位置が入ります。 361 | int IcsCommunication::set_position_weak(uint8 servolocalID) { 362 | int txsize = 3; //この関数固有の、送信データバイト数 363 | int rxsize = 3; //この関数固有の、受信データバイト数 364 | byte txbuf[3]; 365 | byte rxbuf[3]; 366 | 367 | for (int a=0; a ID_MAX)) { 376 | return RETCODE_ERROR_OPTIONWRONG; 377 | } 378 | 379 | //送信データ作成 380 | txbuf[0] = 0x80 | servolocalID; 381 | txbuf[1] = 0; 382 | txbuf[2] = 0; 383 | 384 | //ICS送信 385 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 386 | 387 | //受信データ確認 388 | if (retcode == RETCODE_OK) { 389 | if ((rxbuf[0] & 0b01111111) == servolocalID) { 390 | retval = (rxbuf[1] << 7) + (rxbuf[2]); 391 | return retval; 392 | } else { 393 | return RETCODE_ERROR_IDWRONG; 394 | } 395 | } else { 396 | //error 397 | return retcode; 398 | } 399 | } 400 | 401 | 402 | //脱力後、即時動作(現在位置確認用) 403 | //戻り値に現在位置が入ります。 404 | int IcsCommunication::set_position_weakandkeep(uint8 servolocalID) { 405 | int txsize = 3; //この関数固有の、送信データバイト数 406 | int rxsize = 3; //この関数固有の、受信データバイト数 407 | byte txbuf[3]; 408 | byte rxbuf[3]; 409 | 410 | for (int a=0; a ID_MAX)) { 419 | return RETCODE_ERROR_OPTIONWRONG; 420 | } 421 | 422 | //1回目の送信データ作成 423 | txbuf[0] = 0x80 | servolocalID; 424 | txbuf[1] = 0; 425 | txbuf[2] = 0; 426 | 427 | //ICS送信 428 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 429 | 430 | //受信データ確認 431 | if (retcode == RETCODE_OK) { 432 | if ((rxbuf[0] & 0b01111111) == servolocalID) { 433 | retval = (rxbuf[1] << 7) + (rxbuf[2]); 434 | 435 | //2回目の送信データ作成 436 | txbuf[0] = 0x80 | servolocalID; 437 | txbuf[1] = retval >> 7; 438 | txbuf[2] = retval & 0b0000000001111111; 439 | 440 | //2回目のICS送信 441 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 442 | 443 | //2回目の受信データ確認 444 | if (retcode == RETCODE_OK) { 445 | if ((rxbuf[0] & 0b01111111) == servolocalID) { 446 | retval = (rxbuf[1] << 7) + (rxbuf[2]); 447 | return retval; 448 | } else { 449 | return RETCODE_ERROR_IDWRONG; 450 | } 451 | } else { 452 | //error 453 | return retcode; 454 | } 455 | 456 | } else { 457 | return RETCODE_ERROR_IDWRONG; 458 | } 459 | } else { 460 | //error 461 | return retcode; 462 | } 463 | } 464 | 465 | 466 | 467 | //EEPROM以外のパラメータ読み取りコマンド 468 | //引数:サーボID、ポジション値(3500-11500) 469 | //sccode は、SC_CODE_STRETCH, SC_CODE_SPEED, SC_CODE_CURRENT, SC_CODE_TEMPERATURE 470 | //のどれかが入ります。 471 | //SC_CODE_EEPROM はエラーとなります。EEPROM用の関数get_EEPROMを使ってください。 472 | //戻り値に指定パラメータ値、またはエラーコード(負の値)が入ります。 473 | int IcsCommunication::read_Param(uint8 servolocalID, byte sccode) { 474 | int txsize = 2; 475 | int rxsize = 3; 476 | byte txbuf[2]; 477 | byte rxbuf[3]; 478 | 479 | for (int a=0; a ID_MAX)) { 492 | return RETCODE_ERROR_OPTIONWRONG; 493 | } 494 | 495 | //送信データ作成 496 | txbuf[0] = 0xA0 | servolocalID; 497 | txbuf[1] = sccode; 498 | 499 | //ICS送信 500 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 501 | 502 | //受信データ確認 503 | if (retcode == RETCODE_OK) { 504 | if ( (rxbuf[0] == (0x20 | servolocalID)) && (rxbuf[1] == sccode) ) { 505 | //バッファチェック ID, SC 506 | return rxbuf[2]; 507 | } else { 508 | return RETCODE_ERROR_RETURNDATAWRONG; 509 | } 510 | } else { 511 | //error 512 | return retcode; 513 | } 514 | } 515 | 516 | 517 | //EEPROM以外のパラメータ書き込みコマンド 518 | //戻り値にRETCODE_OK(1の値)、またはエラーコード(負の値)が入ります。 519 | //sccode は、 520 | //SC_CODE_STRETCH, SC_CODE_SPEED, SC_CODE_CURRENT, SC_CODE_TEMPERATURE 521 | //のどれかが入ります。 522 | //SC_CODE_EEPROM はエラーとなります。EEPROM用の関数set_EEPROMを使ってください。 523 | int IcsCommunication::write_Param(uint8 servolocalID, byte sccode, int val) { 524 | int txsize = 3; 525 | int rxsize = 3; 526 | byte txbuf[3]; 527 | byte rxbuf[3]; 528 | 529 | for (int a=0; a ID_MAX)) { 542 | return RETCODE_ERROR_OPTIONWRONG; 543 | } 544 | 545 | //送信データ作成 546 | txbuf[0] = 0xC0 | servolocalID; 547 | txbuf[1] = sccode; 548 | txbuf[2] = val; 549 | 550 | //ICS送信 551 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 552 | 553 | //受信データ確認 554 | if (retcode == RETCODE_OK) { 555 | if ( (rxbuf[0] == (0x40 | servolocalID)) && (rxbuf[1] == sccode) ) { 556 | //バッファチェック ID, SC 557 | return RETCODE_OK; 558 | } else { 559 | return RETCODE_ERROR_RETURNDATAWRONG; 560 | } 561 | } else { 562 | //error 563 | return retcode; 564 | } 565 | } 566 | 567 | 568 | 569 | 570 | //////////////////////////////////////////////////////////////////////////////////// 571 | //////////////////////////////////////////////////////////////////////////////////// 572 | //パラメータ読み込み系 573 | 574 | //全て、戻り値にパラメータ値、またはエラーコード(負の値)が入ります。 575 | 576 | int IcsCommunication::get_stretch(uint8 servolocalID){ 577 | byte sccode = SC_CODE_STRETCH; 578 | retval = read_Param(servolocalID, sccode); 579 | return retval; 580 | } 581 | 582 | int IcsCommunication::get_speed(uint8 servolocalID){ 583 | byte sccode = SC_CODE_SPEED; 584 | retval = read_Param(servolocalID, sccode); 585 | return retval; 586 | } 587 | 588 | int IcsCommunication::get_current(uint8 servolocalID){ 589 | byte sccode = SC_CODE_CURRENT; 590 | retval = read_Param(servolocalID, sccode); 591 | return retval; 592 | } 593 | 594 | int IcsCommunication::get_temperature(uint8 servolocalID){ 595 | byte sccode = SC_CODE_TEMPERATURE; 596 | retval = read_Param(servolocalID, sccode); 597 | return retval; 598 | } 599 | 600 | 601 | 602 | 603 | 604 | //////////////////////////////////////////////////////////////////////////////////// 605 | //////////////////////////////////////////////////////////////////////////////////// 606 | //パラメータ書き込み系 607 | 608 | //全て、戻り値にRETCODE_OK(1の値)、またはエラーコード(負の値)が入ります。 609 | 610 | int IcsCommunication::set_stretch(uint8 servolocalID, int val){ 611 | byte sccode = SC_CODE_STRETCH; 612 | if ((val < 1) || (val > 127) ) { 613 | return RETCODE_ERROR_OPTIONWRONG; 614 | } 615 | retcode = write_Param(servolocalID, sccode, val); 616 | return retcode; 617 | } 618 | 619 | int IcsCommunication::set_speed(uint8 servolocalID, int val){ 620 | byte sccode = SC_CODE_SPEED; 621 | if ((val < 1) || (val > 127) ) { 622 | return RETCODE_ERROR_OPTIONWRONG; 623 | } 624 | retcode = write_Param(servolocalID, sccode, val); 625 | return retcode; 626 | } 627 | 628 | int IcsCommunication::set_currentlimit(uint8 servolocalID, int val){ 629 | byte sccode = SC_CODE_CURRENT; 630 | if ((val < 1) || (val > 63) ) { 631 | return RETCODE_ERROR_OPTIONWRONG; 632 | } 633 | retcode = write_Param(servolocalID, sccode, val); 634 | return retcode; 635 | } 636 | 637 | int IcsCommunication::set_temperaturelimit(uint8 servolocalID, int val){ 638 | byte sccode = SC_CODE_TEMPERATURE; 639 | if ((val < 1) || (val > 127) ) { 640 | return RETCODE_ERROR_OPTIONWRONG; 641 | } 642 | retcode = write_Param(servolocalID, sccode, val); 643 | return retcode; 644 | } 645 | 646 | 647 | 648 | 649 | 650 | //////////////////////////////////////////////////////////////////////////////////// 651 | //////////////////////////////////////////////////////////////////////////////////// 652 | //EEPROM系 653 | 654 | //EEPROM読み取り(生バイト) 655 | //引数: サーボID、受信バッファ 656 | //通常は、次のget_EEPROM関数を使ってください。 657 | //戻り値にRETCODE_OK(1の値)、またはエラーコード(負の値)が入ります。 658 | int IcsCommunication::read_EEPROMraw(uint8 servolocalID, byte *rxbuf ) { 659 | int txsize = 2; 660 | int rxsize = 66; 661 | byte txbuf[2]; 662 | 663 | for (int a=0; a ID_MAX)) { 672 | return RETCODE_ERROR_OPTIONWRONG; 673 | } 674 | 675 | //送信データ作成 676 | txbuf[0] = 0xA0 | servolocalID; 677 | txbuf[1] = sccode; 678 | 679 | //ICS送信 680 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 681 | 682 | //受信データ確認 683 | if (retcode != RETCODE_OK) { 684 | return retcode; 685 | } 686 | 687 | //バッファチェック ID, SC, 0x5A 688 | if ( (rxbuf[0] != (0x20 | servolocalID)) || (rxbuf[1] != sccode) || (rxbuf[2] != 0x5) || (rxbuf[3] != 0xA) ) { 689 | //debugPrint("ID,SC,0x5A error.\r\n"); 690 | return RETCODE_ERROR_RETURNDATAWRONG; 691 | } 692 | 693 | 694 | return RETCODE_OK; 695 | } 696 | 697 | 698 | 699 | //EEPROM読み取り 700 | //引数: サーボID、EEPROMデータ構造体 701 | //戻り値にRETCODE_OK(1の値)、またはエラーコード(負の値)が入ります。 702 | int IcsCommunication::get_EEPROM(uint8 servolocalID, EEPROMdata *r_edata ) { 703 | byte rxbuf[66]; 704 | 705 | retcode = read_EEPROMraw(servolocalID, rxbuf); 706 | 707 | //受信データ確認 708 | if (retcode != RETCODE_OK) { 709 | //debugPrint("get_EEPROM inside read_EEPROMraw error. retcode: " + String(retcode) + "\r\n"); 710 | return retcode; 711 | } 712 | 713 | r_edata->stretch = combine_2byte(rxbuf[4],rxbuf[5]) / 2 ; //2倍値で収納されてる 714 | r_edata->speed = combine_2byte(rxbuf[6],rxbuf[7]); 715 | r_edata->punch = combine_2byte(rxbuf[8],rxbuf[9]); 716 | r_edata->deadband = combine_2byte(rxbuf[10],rxbuf[11]); 717 | r_edata->dumping = combine_2byte(rxbuf[12],rxbuf[13]); 718 | r_edata->safetimer = combine_2byte(rxbuf[14],rxbuf[15]); 719 | 720 | r_edata->flag_slave = (rxbuf[16]>>3) & 0b00000001; 721 | r_edata->flag_rotation = (rxbuf[16] ) & 0b00000001; 722 | r_edata->flag_pwminh = (rxbuf[17]>>3) & 0b00000001; 723 | r_edata->flag_free = (rxbuf[17]>>1) & 0b00000001; 724 | r_edata->flag_reverse = (rxbuf[17] ) & 0b00000001; 725 | 726 | r_edata->poslimithigh = (combine_2byte(rxbuf[18],rxbuf[19]) << 8) | combine_2byte(rxbuf[20],rxbuf[21]); 727 | r_edata->poslimitlow = (combine_2byte(rxbuf[22],rxbuf[23]) << 8) | combine_2byte(rxbuf[24],rxbuf[25]); 728 | 729 | int commflagval = combine_2byte(rxbuf[28],rxbuf[29]); 730 | if (commflagval == 0x00) { 731 | r_edata->commspeed = 1250000; 732 | } else if (commflagval == 0x01) { 733 | r_edata->commspeed = 625000; 734 | } else if (commflagval == 0x0A) { 735 | r_edata->commspeed = 115200; 736 | } else { 737 | r_edata->commspeed = EEPROM_NOTCHANGE; 738 | } 739 | 740 | 741 | 742 | r_edata->temperaturelimit = combine_2byte(rxbuf[30],rxbuf[31]); 743 | r_edata->currentlimit = combine_2byte(rxbuf[32],rxbuf[33]); 744 | r_edata->response = combine_2byte(rxbuf[52],rxbuf[53]); 745 | 746 | byte tmpoffset = combine_2byte(rxbuf[54],rxbuf[55]); 747 | //ICSマネージャ挙動では、正負反対に収納されているのでそれに合わせる 748 | if ((tmpoffset >> 7) == 0b00000001) { //負ビット 749 | r_edata->offset = ( ( ~(tmpoffset) & 0b01111111 ) + 1 ); 750 | } else { //正ビット 751 | r_edata->offset = 0 - tmpoffset; 752 | } 753 | 754 | r_edata->ID = combine_2byte(rxbuf[58],rxbuf[59]); 755 | 756 | r_edata->charstretch1 = combine_2byte(rxbuf[60],rxbuf[61]) / 2; //2倍値で収納されてる 757 | r_edata->charstretch2 = combine_2byte(rxbuf[62],rxbuf[63]) / 2; //2倍値で収納されてる 758 | r_edata->charstretch3 = combine_2byte(rxbuf[64],rxbuf[65]) / 2; //2倍値で収納されてる 759 | 760 | 761 | retcode = check_EEPROMdata(r_edata); 762 | 763 | if (retcode != RETCODE_OK) { 764 | //debugPrint("get_EEPROM inside check_EEPROMdata error. retcode: " + String(retcode) + "\r\n"); 765 | return retcode; 766 | } 767 | 768 | return RETCODE_OK; 769 | } 770 | 771 | 772 | 773 | //(beta test) 774 | //EEPROM書き込み 775 | //引数: サーボID、EEPROMデータ構造体 776 | //戻り値にRETCODE_OK(1の値)、またはエラーコード(負の値)が入ります。 777 | //書き込みコマンドは時間がややかかるようで、この関数内のみ別途タイムアウト時間を長くしています。 778 | //https://twitter.com/devemin/status/1165875204419010561 779 | int IcsCommunication::set_EEPROM(uint8 servolocalID, EEPROMdata *w_edata){ 780 | //w_edata 内のデータのうち、EEPROM_NOTCHANGE でないものだけ書き込む 781 | int txsize = 66; //処理2つ目のEEPROM書き込みでのサイズ 782 | int rxsize = 2; //処理2つ目のEEPROM書き込みでのサイズ 783 | byte txbuf[66]; //処理2つ目のEEPROM書き込みでのサイズ 784 | byte rxbuf[66]; //処理1つ目のEEPROM読み取り、処理2つ目のEEPROM書き込み、の両方で使うバッファなのでsize:66としてる 785 | 786 | byte sccode = SC_CODE_EEPROM; 787 | 788 | for (int a=0; a ID_MAX)) { 797 | return RETCODE_ERROR_OPTIONWRONG; 798 | } 799 | //変更禁止部分以外の、設定値の正当性チェック 800 | retcode = check_EEPROMdata(w_edata); 801 | if (retcode != RETCODE_OK) { 802 | return RETCODE_ERROR_EEPROMDATAWRONG; 803 | } 804 | 805 | ////////////////////////////////////////////////////////////////////// 806 | //関数内1つ目の処理 EEPROM読み取り 807 | //書き込む前に必ず最新のEEPROM読み取り! 808 | retcode = read_EEPROMraw(servolocalID, rxbuf); 809 | if (retcode != RETCODE_OK) { 810 | return retcode; 811 | } 812 | 813 | //EEPROMデータ先頭の0x5Aチェック 814 | int checkdata = combine_2byte(rxbuf[2],rxbuf[3]); 815 | if ( checkdata != 0x5A ) { 816 | return RETCODE_ERROR_EEPROMDATAWRONG; 817 | } 818 | 819 | ////////////////////////////////////////////////////////////////////// 820 | //関数内2つ目の処理 EEPROM書き込み 821 | //EEPROMに書き込むデータの準備 822 | for (int a=0; astretch != EEPROM_NOTCHANGE ) { 832 | txbuf[4] = (byte)(w_edata->stretch*2) >>4; //2倍値で収納されてるので処理 833 | txbuf[5] = (byte)(w_edata->stretch*2) & 0b0000000000001111; 834 | } 835 | 836 | if (w_edata->speed != EEPROM_NOTCHANGE ) { 837 | txbuf[6] = (byte)(w_edata->speed) >>4; 838 | txbuf[7] = (byte)(w_edata->speed) & 0b0000000000001111; 839 | } 840 | if (w_edata->punch != EEPROM_NOTCHANGE ) { 841 | txbuf[8] = (byte)(w_edata->punch) >>4; 842 | txbuf[9] = (byte)(w_edata->punch) & 0b0000000000001111; 843 | } 844 | if (w_edata->deadband != EEPROM_NOTCHANGE ) { 845 | txbuf[10] = (byte)(w_edata->deadband) >>4; 846 | txbuf[11] = (byte)(w_edata->deadband) & 0b0000000000001111; 847 | } 848 | if (w_edata->dumping != EEPROM_NOTCHANGE ) { 849 | txbuf[12] = (byte)(w_edata->dumping) >>4; 850 | txbuf[13] = (byte)(w_edata->dumping) & 0b0000000000001111; 851 | } 852 | if (w_edata->safetimer != EEPROM_NOTCHANGE ) { 853 | txbuf[14] = (byte)(w_edata->safetimer) >>4; 854 | txbuf[15] = (byte)(w_edata->safetimer) & 0b0000000000001111; 855 | } 856 | 857 | if (w_edata->flag_slave != EEPROM_NOTCHANGE ) { 858 | if (w_edata->flag_slave == 1) { txbuf[16] = txbuf[16] | 0b00001000 ; } 859 | if (w_edata->flag_slave == 0) { txbuf[16] = txbuf[16] & 0b11110111 ; } 860 | } 861 | if (w_edata->flag_rotation != EEPROM_NOTCHANGE ) { 862 | if (w_edata->flag_rotation == 1) { txbuf[16] = txbuf[16] | 0b00000001 ; } 863 | if (w_edata->flag_rotation == 0) { txbuf[16] = txbuf[16] & 0b11111110 ; } 864 | } 865 | if (w_edata->flag_pwminh != EEPROM_NOTCHANGE ) { 866 | if (w_edata->flag_pwminh == 1) { txbuf[17] = txbuf[17] | 0b00001000 ; } 867 | if (w_edata->flag_pwminh == 0) { txbuf[17] = txbuf[17] & 0b11110111 ; } 868 | } 869 | if (w_edata->flag_free != EEPROM_NOTCHANGE ) { 870 | //freeフラグは参照のみとのこと。ここを書き込む事は、マニュアル等に説明は無いので挙動不明 871 | //if (w_edata->flag_free == 1) { txbuf[17] = txbuf[17] | 0b00000010 ; } 872 | //if (w_edata->flag_free == 0) { txbuf[17] = txbuf[17] & 0b11111101 ; } 873 | } 874 | if (w_edata->flag_reverse != EEPROM_NOTCHANGE ) { 875 | if (w_edata->flag_reverse == 1) { txbuf[17] = txbuf[17] | 0b00000001 ; } 876 | if (w_edata->flag_reverse == 0) { txbuf[17] = txbuf[17] & 0b11111110 ; } 877 | } 878 | 879 | 880 | if (w_edata->poslimithigh != EEPROM_NOTCHANGE ) { 881 | txbuf[18] = (w_edata->poslimithigh >> 12) & 0b00000000000000000000000000001111; 882 | txbuf[19] = (w_edata->poslimithigh >> 8 ) & 0b00000000000000000000000000001111; 883 | txbuf[20] = (w_edata->poslimithigh >> 4 ) & 0b00000000000000000000000000001111; 884 | txbuf[21] = (w_edata->poslimithigh ) & 0b00000000000000000000000000001111; 885 | } 886 | 887 | if (w_edata->poslimitlow != EEPROM_NOTCHANGE ) { 888 | txbuf[22] = (w_edata->poslimitlow >> 12) & 0b00000000000000000000000000001111; 889 | txbuf[23] = (w_edata->poslimitlow >> 8 ) & 0b00000000000000000000000000001111; 890 | txbuf[24] = (w_edata->poslimitlow >> 4 ) & 0b00000000000000000000000000001111; 891 | txbuf[25] = (w_edata->poslimitlow ) & 0b00000000000000000000000000001111; 892 | } 893 | 894 | 895 | if (w_edata->commspeed != EEPROM_NOTCHANGE ) { 896 | if (w_edata->commspeed == 115200) { 897 | txbuf[28] = 0x0; 898 | txbuf[29] = 0xA; 899 | } else if (w_edata->commspeed == 625000) { 900 | txbuf[28] = 0x0; 901 | txbuf[29] = 0x1; 902 | } else if (w_edata->commspeed == 1250000) { 903 | txbuf[28] = 0x0; 904 | txbuf[29] = 0x0; 905 | } 906 | } 907 | 908 | if (w_edata->temperaturelimit != EEPROM_NOTCHANGE ) { 909 | txbuf[30] = (byte)(w_edata->temperaturelimit) >>4; 910 | txbuf[31] = (byte)(w_edata->temperaturelimit) & 0b0000000000001111; 911 | } 912 | if (w_edata->currentlimit != EEPROM_NOTCHANGE ) { 913 | txbuf[32] = (byte)(w_edata->currentlimit) >>4; 914 | txbuf[33] = (byte)(w_edata->currentlimit) & 0b0000000000001111; 915 | } 916 | if (w_edata->response != EEPROM_NOTCHANGE ) { 917 | txbuf[52] = (byte)(w_edata->response) >>4; 918 | txbuf[53] = (byte)(w_edata->response) & 0b0000000000001111; 919 | } 920 | if (w_edata->offset != EEPROM_NOTCHANGE ) { //ICSマネージャ挙動では、正負反対に収納されているのでそれに合わせる 921 | byte tmpoffset = ~(w_edata->offset) + 1; 922 | txbuf[54] = (byte)(tmpoffset) >>4; 923 | txbuf[55] = (byte)(tmpoffset) & 0b0000000000001111; 924 | } 925 | if (w_edata->ID != EEPROM_NOTCHANGE ) { 926 | //IDは専用のコマンドがあるので、本来はそちらで行う。こちらから書き込んでも私の環境ではID書き換えできているが、リファレンスマニュアルには記載無し 927 | txbuf[58] = (byte)(w_edata->ID) >>4; 928 | txbuf[59] = (byte)(w_edata->ID) & 0b0000000000001111; 929 | } 930 | 931 | if (w_edata->charstretch1 != EEPROM_NOTCHANGE ) { 932 | txbuf[60] = (byte)(w_edata->charstretch1*2) >>4; //2倍値で収納されてるので処理 933 | txbuf[61] = (byte)(w_edata->charstretch1*2) & 0b0000000000001111; 934 | } 935 | if (w_edata->charstretch2 != EEPROM_NOTCHANGE ) { 936 | txbuf[62] = (byte)(w_edata->charstretch2*2) >>4; //2倍値で収納されてるので処理 937 | txbuf[63] = (byte)(w_edata->charstretch2*2) & 0b0000000000001111; 938 | } 939 | if (w_edata->charstretch1 != EEPROM_NOTCHANGE ) { 940 | txbuf[64] = (byte)(w_edata->charstretch3*2) >>4; //2倍値で収納されてるので処理 941 | txbuf[65] = (byte)(w_edata->charstretch3*2) & 0b0000000000001111; 942 | } 943 | 944 | 945 | change_timeout(TIMEOUT_LONG); //タイムアウトを長くする(重要!) 946 | 947 | //ICS送信 948 | retcode = transceive(txbuf, rxbuf, txsize, rxsize); 949 | 950 | change_timeout(TIMEOUT_NORMAL); //タイムアウトを戻す(重要!) 951 | 952 | 953 | if (retcode != RETCODE_OK) { 954 | //debugPrint("error: " + String(retcode)); 955 | return retcode; 956 | } 957 | 958 | //受信データ確認 959 | //バッファチェック ID, SC 960 | if ( (rxbuf[0] != (0x40 | servolocalID)) || (rxbuf[1] != sccode) ) { 961 | //debugPrint("return data is incorrect.\r\n"); 962 | return RETCODE_ERROR_RETURNDATAWRONG; 963 | } 964 | 965 | return RETCODE_OK; 966 | 967 | 968 | } 969 | 970 | 971 | //データがEEPROM用として正当かどうかを確認する関数 972 | //元々のサーボ内の変更禁止バイト部分の読み込み等は別で行っている 973 | //内容がEEPROM_NOTCHANGE(初期状態)だと、書き込み不適と判断しエラーを返す 974 | int IcsCommunication::check_EEPROMdata(EEPROMdata *edata) { 975 | int checkdata; 976 | int tmpretcode= RETCODE_OK; 977 | 978 | checkdata = edata->stretch; 979 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 1) || (checkdata > 127) ) { 980 | debugPrint("EEPROMdata error: stretch\r\n"); 981 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 982 | } 983 | checkdata = edata->speed; 984 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x01) || (checkdata > 0x7F) ) { 985 | debugPrint("EEPROMdata error: speed\r\n"); 986 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 987 | } 988 | checkdata = edata->punch; 989 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x00) || (checkdata > 0x0A) ) { 990 | debugPrint("EEPROMdata error: punch\r\n"); 991 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 992 | } 993 | checkdata = edata->deadband; 994 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x00) || (checkdata > 0x10) ) { 995 | debugPrint("EEPROMdata error: deadband\r\n"); 996 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 997 | } 998 | checkdata = edata->dumping; 999 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x01) || (checkdata > 0xFF) ) { 1000 | debugPrint("EEPROMdata error: dumping\r\n"); 1001 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1002 | } 1003 | checkdata = edata->safetimer; 1004 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x01) || (checkdata > 0xFF) ) { 1005 | debugPrint("EEPROMdata error: safetimer\r\n"); 1006 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1007 | } 1008 | 1009 | //フラグ 1010 | if ( (edata->flag_slave != EEPROM_NOTCHANGE) && (edata->flag_slave != 0) && (edata->flag_slave != 1) ) { 1011 | debugPrint("EEPROMdata error: flag_slave\r\n"); 1012 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1013 | } 1014 | if ( (edata->flag_rotation != EEPROM_NOTCHANGE) && (edata->flag_rotation != 0) && (edata->flag_rotation != 1) ) { 1015 | debugPrint("EEPROMdata error: flag_rotation\r\n"); 1016 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1017 | } 1018 | if ( (edata->flag_pwminh != EEPROM_NOTCHANGE) && (edata->flag_pwminh != 0) && (edata->flag_pwminh != 1) ) { 1019 | debugPrint("EEPROMdata error: flag_pwminh\r\n"); 1020 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1021 | } 1022 | if ( (edata->flag_free != EEPROM_NOTCHANGE) && (edata->flag_free != 0) && (edata->flag_free != 1) ) { 1023 | debugPrint("EEPROMdata error: flag_free\r\n"); 1024 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1025 | } 1026 | if ( (edata->flag_reverse != EEPROM_NOTCHANGE) && (edata->flag_reverse != 0) && (edata->flag_reverse != 1) ) { 1027 | debugPrint("EEPROMdata error: flag_reverse\r\n"); 1028 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1029 | } 1030 | 1031 | 1032 | checkdata = edata->poslimithigh; 1033 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 8000) || (checkdata > POS_MAX) ) { 1034 | debugPrint("EEPROMdata error: poslimithigh\r\n"); 1035 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1036 | } 1037 | checkdata = edata->poslimitlow; 1038 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < POS_MIN) || (checkdata > 7000) ) { 1039 | debugPrint("EEPROMdata error: poslimitlow\r\n"); 1040 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1041 | } 1042 | 1043 | if ( (edata->commspeed != EEPROM_NOTCHANGE) && (edata->commspeed != 115200) && (edata->commspeed != 625000) && (edata->commspeed != 1250000) ) { 1044 | debugPrint("EEPROMdata error: commspeed\r\n"); 1045 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1046 | } 1047 | 1048 | checkdata = edata->temperaturelimit; 1049 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x01) || (checkdata > 0x7F) ) { 1050 | debugPrint("EEPROMdata error: temperaturelimit\r\n"); 1051 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1052 | } 1053 | checkdata = edata->currentlimit; 1054 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x01) || (checkdata > 0x3F) ) { 1055 | debugPrint("EEPROMdata error: currentlimit\r\n"); 1056 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1057 | } 1058 | checkdata = edata->response; 1059 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x01) || (checkdata > 0x05) ) { 1060 | debugPrint("EEPROMdata error: response\r\n"); 1061 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1062 | } 1063 | checkdata = edata->offset; 1064 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < -128) || (checkdata > 127) ) { 1065 | debugPrint("EEPROMdata error: offset\r\n"); 1066 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1067 | } 1068 | checkdata = edata->ID; 1069 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 0x00) || (checkdata > 0x1F) ) { 1070 | debugPrint("EEPROMdata error: ID\r\n"); 1071 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1072 | } 1073 | checkdata = edata->charstretch1; 1074 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 1) || (checkdata > 127) ) { 1075 | debugPrint("EEPROMdata error: charstretch1\r\n"); 1076 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1077 | } 1078 | checkdata = edata->charstretch2; 1079 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 1) || (checkdata > 127) ) { 1080 | debugPrint("EEPROMdata error: charstretch2\r\n"); 1081 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1082 | } 1083 | checkdata = edata->charstretch3; 1084 | if ( (checkdata != EEPROM_NOTCHANGE) && (checkdata < 1) || (checkdata > 127) ) { 1085 | debugPrint("EEPROMdata error: charstretch3\r\n"); 1086 | tmpretcode = RETCODE_ERROR_EEPROMDATAWRONG; 1087 | } 1088 | 1089 | 1090 | return tmpretcode; 1091 | } 1092 | 1093 | 1094 | //上位下位4bitずつに分かれた2byteを、1byteにして取得する関数 1095 | byte IcsCommunication::combine_2byte(byte a, byte b){ 1096 | return (byte)((a<<4) | b); 1097 | } 1098 | 1099 | 1100 | //バッファ内のEEPROM生バイトデータを表示する関数 1101 | void IcsCommunication::show_EEPROMbuffer(byte *checkbuf) { 1102 | 1103 | ////////////////////////////////////////////////////////////////// 1104 | //テストデバッグコード 1105 | debugPrint("//////////////////////////////////////////////\r\n"); 1106 | 1107 | debugPrint(String(checkbuf[0],HEX) + " " ); 1108 | debugPrint(String(checkbuf[1],HEX) + " " ); 1109 | debugPrint("\r\n" ); 1110 | for (int c=0; c<=63; c++) { 1111 | debugPrint(String(checkbuf[c+2],HEX) + " " ); 1112 | if ((c%8) == 7) { 1113 | debugPrint("\r\n" ); 1114 | } 1115 | } 1116 | debugPrint("\r\n" ); 1117 | ////////////////////////////////////////////////////////////////// 1118 | 1119 | } 1120 | 1121 | 1122 | 1123 | //EEPROMデータの表示関数 1124 | void IcsCommunication::show_EEPROMdata(EEPROMdata *edata) { 1125 | 1126 | debugPrint("===================================================\r\n"); 1127 | debugPrint("----EEPROM data------------------------------------\r\n"); 1128 | 1129 | debugPrint("stretch: " + String(edata->stretch) + "[0x" + String(edata->stretch, HEX) + "] (1-127)\r\n"); 1130 | debugPrint("speed: " + String(edata->speed) + "[0x" + String(edata->speed, HEX) + "] (1-127)\r\n"); 1131 | debugPrint("punch: " + String(edata->punch) + "[0x" + String(edata->punch, HEX) + "] (0-10)\r\n"); 1132 | debugPrint("deadband: " + String(edata->deadband) + "[0x" + String(edata->deadband, HEX) + "] (0-5)\r\n"); 1133 | debugPrint("dumping: " + String(edata->dumping) + "[0x" + String(edata->dumping, HEX) + "] (1-255)\r\n"); 1134 | debugPrint("safetimer: " + String(edata->safetimer) + "[0x" + String(edata->safetimer, HEX) + "] (10-255)\r\n"); 1135 | 1136 | debugPrint("flag_slave: " + String(edata->flag_slave) + " (0/1)\r\n"); 1137 | debugPrint("flag_rotation: " + String(edata->flag_rotation) + " (0/1)\r\n"); 1138 | debugPrint("flag_pwminh: " + String(edata->flag_pwminh) + " (0/1)\r\n"); 1139 | debugPrint("flag_free: " + String(edata->flag_free) + " (0/1)\r\n"); 1140 | debugPrint("flag_reverse: " + String(edata->flag_reverse) + " (0/1)\r\n"); 1141 | 1142 | debugPrint("poslimithigh: " + String(edata->poslimithigh) + "[0x" + String(edata->poslimithigh, HEX) + "] (8000-11500)\r\n"); 1143 | debugPrint("poslimitlow: " + String(edata->poslimitlow) + "[0x" + String(edata->poslimitlow, HEX) + "] (3500-7000)\r\n"); 1144 | debugPrint("commspeed: " + String(edata->commspeed) + " (115200/625000/1250000)\r\n"); 1145 | debugPrint("temperaturelimit: " + String(edata->temperaturelimit) + "[0x" + String(edata->temperaturelimit, HEX) + "] (1-127)\r\n"); 1146 | debugPrint("currentlimit: " + String(edata->currentlimit) + "[0x" + String(edata->currentlimit, HEX) + "] (1-63)\r\n"); 1147 | debugPrint("response: " + String(edata->response) + "[0x" + String(edata->response, HEX) + "] (1-5)\r\n"); 1148 | debugPrint("offset: " + String(edata->offset) + "[0x" + String(edata->offset, HEX) + "] (-127-127)\r\n"); 1149 | debugPrint("ID: " + String(edata->ID) + "[0x" + String(edata->ID, HEX) + "] (0-31)\r\n"); 1150 | debugPrint("charstretch1: " + String(edata->charstretch1) + "[0x" + String(edata->charstretch1, HEX) + "] (1-127)\r\n"); 1151 | debugPrint("charstretch2: " + String(edata->charstretch2) + "[0x" + String(edata->charstretch2, HEX) + "] (1-127)\r\n"); 1152 | debugPrint("charstretch3: " + String(edata->charstretch3) + "[0x" + String(edata->charstretch3, HEX) + "] (1-127)\r\n"); 1153 | debugPrint("\r\n"); 1154 | debugPrint(" -4096: this mean NO_CHANGE. \r\n"); 1155 | debugPrint("---------------------------------------------------\r\n"); 1156 | debugPrint("===================================================\r\n"); 1157 | debugPrint("\r\n"); 1158 | 1159 | } 1160 | 1161 | 1162 | 1163 | //サーボの存在を確認 1164 | //EEPROMからID読み込みを繰り返して、判断する。 1165 | //EEPROM読み取りは各種データチェックが入ってるので、その処理を複数回乗り越えてれば、 1166 | //おそらくそのIDは本物だろう、という考え。 1167 | bool IcsCommunication::IsServoAlive(uint8 servolocalID) { 1168 | EEPROMdata tmped; 1169 | int repnum = 10; //チェック回数 1170 | 1171 | for (int a=0; a> 5) == 0b00000111) { 1212 | retval = (rxbuf[0] & 0b00011111); 1213 | return retval; 1214 | } else { 1215 | return RETCODE_ERROR_IDWRONG; 1216 | } 1217 | } else { 1218 | //error 1219 | return retcode; 1220 | } 1221 | 1222 | } 1223 | 1224 | 1225 | //このID書き込みコマンドは、標準のものだが、ホストーサーボを1対1で接続して使用するもの。 1226 | //もし複数接続していた場合は、全てのサーボが同じIDに書き換わってしまうので注意。 1227 | //もし該当サーボのIDが既にわかってるのであれば、こちらを使わずEEPROM書き替え関数の方でID指定して書き替えられます。 1228 | //20μsec 程で返信コマンドは来るが、再度書き込みする場合は、 1229 | //EEPROM書き込みと同等時間待たないとエラーとなり返信来ないので、別途delay()が必要 1230 | //KRS-4031HV で500μsec 程 1231 | //https://twitter.com/devemin/status/1165865232318775296 1232 | int IcsCommunication::set_ID(uint8 servolocalID) { 1233 | int txsize = 4; //この関数固有の、送信データバイト数 1234 | int rxsize = 1; //この関数固有の、受信データバイト数 1235 | byte txbuf[4]; 1236 | byte rxbuf[66]; //重複IDチェックのため多バイト確保 1237 | 1238 | for (int a=0; a> 5) == 0b00000111) && ( (rxbuf[0] & 0b00011111) == servolocalID ) ) { 1257 | retval = (rxbuf[0] & 0b00011111); 1258 | return retval; 1259 | } else { 1260 | return RETCODE_ERROR_IDWRONG; 1261 | } 1262 | } else { 1263 | //error 1264 | return retcode; 1265 | } 1266 | 1267 | } 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | IcsCommunication ics2(Serial2); //HV 1275 | IcsCommunication ics3(Serial3); //MV 1276 | 1277 | 1278 | 1279 | void setup() { 1280 | debugSer->begin(SERIAL1_BAUDRATE); 1281 | 1282 | ics2.begin(SERIAL2_BAUDRATE, 50, true); 1283 | ics3.begin(SERIAL3_BAUDRATE, 50, true); 1284 | 1285 | } 1286 | 1287 | 1288 | void loop() { 1289 | 1290 | /* 1291 | //全EEPROM読み込み 1292 | EEPROMdata tested; 1293 | int endid = 11; 1294 | for (int a=1; a<=endid; a++) { 1295 | int retcode = ics3.get_EEPROM(a, &tested); 1296 | if (retcode != RETCODE_OK) { 1297 | debugPrint("error.\r\n"); 1298 | delay(200); 1299 | break; 1300 | } 1301 | debugPrint(String(a,DEC) + ","); 1302 | debugPrint(String(tested.stretch,DEC) + ","); 1303 | debugPrint(String(tested.speed,DEC) + ","); 1304 | debugPrint(String(tested.punch,DEC) + ","); 1305 | debugPrint(String(tested.deadband,DEC) + ","); 1306 | debugPrint(String(tested.dumping,DEC) + ","); 1307 | debugPrint(String(tested.safetimer,DEC) + ","); 1308 | debugPrint(String(tested.flag_slave,DEC) + ","); 1309 | debugPrint(String(tested.flag_rotation,DEC) + ","); 1310 | debugPrint(String(tested.flag_pwminh,DEC) + ","); 1311 | debugPrint(String(tested.flag_free,DEC) + ","); 1312 | debugPrint(String(tested.flag_reverse,DEC) + ","); 1313 | debugPrint(String(tested.poslimithigh,DEC) + ","); 1314 | debugPrint(String(tested.poslimitlow,DEC) + ","); 1315 | debugPrint(String(tested.commspeed,DEC) + ","); 1316 | debugPrint(String(tested.temperaturelimit,DEC) + ","); 1317 | debugPrint(String(tested.currentlimit,DEC) + ","); 1318 | debugPrint(String(tested.response,DEC) + ","); 1319 | debugPrint(String(tested.offset,DEC) + ","); 1320 | debugPrint(String(tested.ID,DEC) + ","); 1321 | debugPrint(String(tested.charstretch1,DEC) + ","); 1322 | debugPrint(String(tested.charstretch2,DEC) + ","); 1323 | debugPrint(String(tested.charstretch3,DEC) + ","); 1324 | debugPrint("\r\n"); 1325 | 1326 | delay(200); 1327 | } 1328 | delay(2000); 1329 | */ 1330 | 1331 | 1332 | 1333 | 1334 | /* 1335 | int retval; 1336 | //ポジション値送信・戻り値 テスト 1337 | for (int b=10; b<=11; b++) { 1338 | retval = ics3.set_position(b, 7500); 1339 | debugPrint(String(retval) + "\r\n" ); 1340 | } 1341 | delay(1000); 1342 | for (int b=10; b<=11; b++) { 1343 | retval = ics3.set_position(b, 8000); 1344 | debugPrint(String(retval) + "\r\n" ); 1345 | } 1346 | delay(1000); 1347 | */ 1348 | 1349 | 1350 | /* 1351 | //サーボ脱力 テスト 1352 | int retpos; 1353 | for (int b=10; b<=11; b++) { 1354 | retpos = ics3.set_position(b, 7500); 1355 | debugPrint(String(retpos) + "\r\n" ); 1356 | delay(1000); 1357 | 1358 | retpos = ics3.set_position(b, 8000); 1359 | debugPrint(String(retpos) + "\r\n" ); 1360 | delay(1000); 1361 | 1362 | retpos = ics3.set_position_weak(b); 1363 | debugPrint(String(retpos) + "\r\n" ); 1364 | delay(1000); 1365 | } 1366 | */ 1367 | 1368 | 1369 | /* 1370 | //サーボ脱力アンドキープ テスト 1371 | int retpos; 1372 | for (int b=10; b<=11; b++) { 1373 | retpos = ics3.set_position(b, 7500); 1374 | debugPrint(String(retpos) + "\r\n" ); 1375 | delay(1000); 1376 | 1377 | retpos = ics3.set_position(b, 8000); 1378 | debugPrint(String(retpos) + "\r\n" ); 1379 | delay(1000); 1380 | 1381 | retpos = ics3.set_position_weakandkeep(b); 1382 | debugPrint(String(retpos) + "\r\n" ); 1383 | delay(1000); 1384 | } 1385 | */ 1386 | 1387 | 1388 | /* 1389 | //パラメータ 読み書き テスト (EEPROM以外) 1390 | int retval; 1391 | bool test = false; 1392 | for (int b=10; b<=11; b++) { 1393 | debugPrint("#######################################\r\n"); 1394 | retval = ics3.get_stretch(b); 1395 | debugPrint("ID: " + String(b,DEC) + ", stretch: " + String(retval,DEC) + "\r\n"); 1396 | retval = ics3.get_speed(b); 1397 | debugPrint("ID: " + String(b,DEC) + ", speed: " + String(retval,DEC) + "\r\n"); 1398 | retval = ics3.get_current(b); 1399 | debugPrint("ID: " + String(b,DEC) + ", current: " + String(retval,DEC) + "\r\n"); 1400 | retval = ics3.get_temperature(b); 1401 | debugPrint("ID: " + String(b,DEC) + ", temperature: " + String(retval,DEC) + "\r\n"); 1402 | delay(1000); 1403 | if (test) { ics3.set_stretch(b, 100); } 1404 | else { ics3.set_stretch(b, 99); } 1405 | retval = ics3.get_stretch(b); 1406 | debugPrint("ID: " + String(b,DEC) + ", stretch: " + String(retval,DEC) + "\r\n"); 1407 | test = !test; 1408 | if (test) { delay(1000); } 1409 | else { delay(10000); } 1410 | } 1411 | */ 1412 | 1413 | 1414 | /* 1415 | //EEPROMデータ読み取り 1416 | EEPROMdata reted; 1417 | int retcode = ics3.get_EEPROM(2, &reted); 1418 | if (retcode != RETCODE_OK ) { 1419 | debugPrint("getEEPROM modoriti error.\r\n"); 1420 | return ; 1421 | } 1422 | ics3.show_EEPROMdata(&reted); 1423 | delay(2000); 1424 | */ 1425 | 1426 | 1427 | 1428 | /* 1429 | //EEPROM書き込み テスト 1430 | int retcode; 1431 | EEPROMdata newed; 1432 | EEPROMdata reted; 1433 | 1434 | newed.stretch = 100; 1435 | newed.speed = 100; 1436 | newed.punch = 0; 1437 | newed.deadband = 2; 1438 | newed.dumping = 25; 1439 | newed.safetimer = 250; 1440 | newed.flag_slave = 0; 1441 | newed.flag_rotation = 0; 1442 | newed.flag_pwminh = 1; 1443 | newed.flag_free = 1; 1444 | newed.flag_reverse = 0; 1445 | newed.poslimithigh = 11500; 1446 | newed.poslimitlow = 3500; 1447 | newed.commspeed = 1250000; 1448 | newed.temperaturelimit = 40; 1449 | newed.currentlimit = 40; 1450 | newed.response = 1; 1451 | newed.offset = 0; 1452 | newed.ID = 2; 1453 | newed.charstretch1 = 60; 1454 | newed.charstretch2 = 30; 1455 | newed.charstretch3 = 90; 1456 | 1457 | ics3.show_EEPROMdata(&newed); 1458 | 1459 | retcode = ics3.set_EEPROM(2, &newed); 1460 | if (retcode != RETCODE_OK) { 1461 | debugPrint("set_EEPROMdata error.\r\n"); 1462 | return ; 1463 | } else { 1464 | debugPrint("set_EEPROMdata OK!\r\n"); 1465 | } 1466 | delay(1000); 1467 | 1468 | retcode = ics3.get_EEPROM(2, &reted); 1469 | if (retcode != RETCODE_OK) { 1470 | debugPrint("get_EEPROM error.\r\n"); 1471 | return ; 1472 | } else { 1473 | debugPrint("get_EEPROM OK!\r\n"); 1474 | } 1475 | ics3.show_EEPROMdata(&reted); 1476 | 1477 | delay(3000); 1478 | */ 1479 | 1480 | 1481 | 1482 | /* 1483 | //ID存在テスト 1484 | bool servo_table[3][ID_MAX+1]; 1485 | int baudratelist[3] = {1250000, 625000, 115200}; 1486 | //テーブルは[0]:1250000bps, [1]:625000, [2]:115200 とする 1487 | //ID 0-31の計32個、存在をBOOLで保管 あればtrue 1488 | 1489 | debugPrint("##########################################\r\n"); 1490 | 1491 | for (int a=0; a<=2; a++) { 1492 | debugPrint("ID check: " + String(baudratelist[a]) + "bps.\r\n"); 1493 | ics3.change_baudrate(baudratelist[a]); 1494 | 1495 | for (int b=ID_MIN; b<=ID_MAX; b++) { 1496 | servo_table[a][b] = ics3.IsServoAlive(b); 1497 | debugPrint(String(servo_table[a][b]) + "," ); 1498 | } 1499 | debugPrint("\r\n"); 1500 | } 1501 | ics3.change_baudrate(baudratelist[0]); 1502 | delay(1000); 1503 | */ 1504 | 1505 | 1506 | /* 1507 | //コマンド必要時間チェック用 1508 | //transceive 内のデバッグ表示部をコメントアウト除去してから実行すると所要時間が測れる 1509 | delay(10000); 1510 | 1511 | debugPrint("servo move\r\n" ); 1512 | for (int a=0; a<10; a++) { 1513 | retval = set_position(1, 7500); 1514 | delay(200); 1515 | 1516 | retval = set_position(1, 8000); 1517 | delay(200); 1518 | } 1519 | delay(2000); 1520 | 1521 | debugPrint("servo weak\r\n" ); 1522 | for (int a=0; a<10; a++) { 1523 | retval = set_position(1, 7500); 1524 | delay(200); 1525 | 1526 | retval = set_position(1, 8000); 1527 | delay(200); 1528 | 1529 | retval = set_position_weak(1); 1530 | delay(200); 1531 | } 1532 | delay(2000); 1533 | 1534 | debugPrint("parameter read\r\n" ); 1535 | for (int a=0; a<10; a++) { 1536 | retval = get_stretch(1); 1537 | delay(200); 1538 | } 1539 | delay(2000); 1540 | 1541 | debugPrint("parameter write\r\n" ); 1542 | for (int a=0; a<10; a++) { 1543 | set_stretch(1, 64); 1544 | delay(200); 1545 | } 1546 | delay(2000); 1547 | 1548 | debugPrint("read EEPROM\r\n" ); 1549 | EEPROMdata tested; 1550 | for (int a=0; a<10; a++) { 1551 | get_EEPROM(1, &tested); 1552 | delay(200); 1553 | } 1554 | delay(2000); 1555 | 1556 | debugPrint("write EEPROM\r\n" ); 1557 | EEPROMdata newed; 1558 | for (int a=0; a<10; a++) { 1559 | newed.offset = 0; 1560 | retcode = set_EEPROM(1, &newed); 1561 | delay(200); 1562 | } 1563 | delay(2000); 1564 | 1565 | 1566 | */ 1567 | 1568 | 1569 | } 1570 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 devemin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STM32-Arduino-ICSservo 2 | STM32 x Arduino にて近藤科学ICS 3.5 サーボを使用するライブラリです。(プリメイドAI含む) 3 |
4 | 5 | ※このページの情報は結構古いです。特にArduino IDE でのSTM32ボード情報は新しいものがあるはずです。このライブラリは古いボード情報での利用前提となっていますのでご注意下さい。 6 | 7 |
プリメイドAIハックで初めてロボットいじりの楽しさを知ったので、是非いろんな方に使ってほしいです。 8 |
何かありましたら、Issues(掲示板)の方でお教えいただけると幸いです。 9 |
10 |
近藤科学のICS 3.5/3.6ソフトウェアマニュアルに則り実装しています。 11 |
https://kondo-robot.com/faq/ics3-5_3-6softwaremanual_2 12 |
13 | # ●機能 14 | ・サーボ移動、脱力(現在位置確認も) 15 |
ID 読み書き(通常コマンド、ホスト-サーボを1対1接続時) 16 |
全パラメータ読み書き(EEPROM含む)(ストレッチ、スピード、パンチ、デッドバンド、ダンピング、セイフタイマー、回転モード、PWM禁止、リバースモード、上下リミット、通信速度、温度制限、電流制限、レスポンス、オフセット、キャラスタリスティックチェンジのストレッチ1-3) 17 |
EEPROM書き込みを行う set_EEPROM 関数のみ、現在はベータ版としておきます。必要な方のみコード内容をご理解の上、set_EEPROM関数をお使いください。詳しくは下の方に書きました。) 18 |
19 |
(独自)サーボ脱力後に同位置で即動作(現在位置確認用として) 20 |
(独自)ID読み書き(EEPROM書き替えにより、複数接続時でも可能) 21 |
(独自)ID指定によるサーボ存在確認 22 |
23 |
24 | # ●動作確認 25 | プリメイドAI(STM32F102)、BluePill(同F103) 26 |
27 |
28 | # ●利用する想定回路 29 | プリメイドAIであれば、回路はそのままで利用できます。 30 |
31 |
プリメイドAI内回路における1線式UARTを想定しています。 32 |
近藤科学公式のArduino ICSサーボライブラリとの違いは、2線式か1線式か、の利用回路の違いです。 33 |
公式の回路は3ステートバッファを用意するものですが、1線式は回路がシンプルになるのがメリットです。 34 |
35 |
BluePill(STM32F103)等であれば、 36 |
STM32F103 - レベルコンバータ(3.3V-5V) - ICSサーボ 37 |
接続するpin番号 は、 38 |
Serial2: PA2 39 |
Serial3: PB10 40 |
となっております。 41 |
(Serial1: PA9) 当ライブラリではSerial1はデバッグ用として利用想定しています。Serial2-3を利用下さい。 42 |
レベルコンバータは、私は秋月電子のこちらを利用しました。(3.3Vでも動いてはいましたが。) 43 |
4ビット双方向ロジックレベル変換モジュール BSS138使用 44 |
http://akizukidenshi.com/catalog/g/gK-13837/ 45 |
電源・GNDは別途用意してください。信号線(5V)、HV系(9-12V)、MV系(6-7.4V) 46 |
私はプリメイドAI回路と同様に、ダンピング?抵抗(直列、330表記、33Ω?)・プルアップ抵抗(333表記、33kΩ)も接続しました。 47 |
48 |
49 | # ●利用方法 50 | https://github.com/devemin/Pre-maiduino 51 |
をご覧いただき、Arduino IDE にSTM32ボード情報をインストールしてください。 52 |
プリメイドAIの場合は、上記に記載の通り、書き込み保護解除とともに、元ファーム消去が必要となります(元ファームのバックアップ不可)。 53 |
STM32とPCの接続は、ST Linkケーブルを利用します。 54 |
その後、当ライブラリのコードをArduino IDE にて開いてビルド、STM32に転送してもらえば利用できるかと思います。 55 |
56 |
57 | # ●コード例 58 | ICS_library.ino の コード内 loop() に処理サンプルを書いてありますので、ご覧ください。 59 |
あえて1ファイルにクラスのコードをまとめてありますので、必要に応じ適宜別ファイルに移すなどしてください。 60 | 61 | ```cpp 62 | IcsCommunication ics2(Serial2); //HV 63 | IcsCommunication ics3(Serial3); //MV 64 | 65 | void setup() { 66 | ics2.begin(SERIAL2_BAUDRATE, 50, true); //初期化 67 | ics3.begin(SERIAL3_BAUDRATE, 50, true); 68 | } 69 | void loop() { 70 | int retval; 71 | retval = ics3.set_position(11, 7500); //サーボ移動(ID, ポジション) 72 | delay(500); 73 | retval = ics3.set_position(11, 8000); 74 | delay(500); 75 | } 76 | ``` 77 | 78 | 79 |
80 |
81 | 82 | # ●(重要!)EEPROM書き込みを行う set_EEPROM 関数について 83 | set_EEPROM 関数以外は、安全に使えますので思う存分使ってください。 84 |
EEPROM書き込み処理を行う set_EEPROM 関数についてですが、自分の個体では問題なく使えてますし、充分注意してコーディングしたつもりですが、万が一バグやバッファオーバーランで書き込みデータが狂うと最悪サーボ修理(800円)となります。(EEPROM内でデータ変更不可の部分があり、そこを変えて書き込んでしまうとサーボ内マイコンの処理がおかしくなる) 85 |
一応この関数はベータ版としておきます。 86 |
使用例: https://twitter.com/devemin/status/1169402692139044865?s=19 87 |
set_EEPROM 関数をご利用の方は、まず1か所(手先など)からお試し頂き、その後、他の場所に使ってみてください。万が一エラーの出た方は、エラーコードやコーディングとともにお教え頂ければ幸いです。(エラーコードが出たからといって、即サーボ破損というわけではありません。) 88 |
処理時間は1回 500msほどかかります。書き込み処理の途中で電源を切ったりリセットするのももちろん危ないと思います。 89 |
ご理解の上、ご自身の責任でご利用ください。心配な方は、パラメータ書き換えに関しては公式ICSマネージャから行ってください。 90 |
実機使用のデータやフィードバックが集まり次第、情報更新し、ベータ扱いを解除したいと思います。 91 |
92 | # ●補足 93 | 秋月にたくさん売ってるNucleo ボードもSTM32シリーズが使われていますので、当ライブラリが使用できるかと思います。 94 |
また、内部のtransceive 関数と通信速度等を書き替えれば他機種でも使えるかと思います。(他Arduino機種など) 95 |
上位のICS 3.6規格には現在位置取得コマンドが存在しますが、それもtranscieve 関数を利用してもらえば、簡単に追加実装できると思います。 96 |
97 |
98 | # ●作成者 99 | devemin 100 |
101 |
102 | # ●ライセンス 103 |
MIT License 104 |
105 |
106 | # ●Thanks! 107 | @GOROman ( https://twitter.com/GOROman ) 108 |
@izm ( https://twitter.com/izm) 109 |
@kazzlog ( https://twitter.com/kazzlog ) 110 |
@Schwarz_Sardine ( https://twitter.com/Schwarz_Sardine ) 111 |
@witch_kazumin ( https://twitter.com/witch_kazumin ) 112 |
and my twitter-follower...! 113 |
114 | # ●注意事項 115 | 当ライブラリから発生する事象に対し、責任は全て利用者にあります。 116 |
コードをよくご理解の上、ご利用下さい。 117 |
118 |
119 | # ●更新履歴 120 | ver 0.50: publish 121 |
122 | --------------------------------------------------------------------------------