Dobot Magician UART 2020/03/12 ~ 2020/07/27
■Dobot Magician + Pixy2 + Arduino MEGA を使った Pick & Place のサンプルコードです。
・2020/07/27 コード中 "==" と書くべきところが、 "=" になっていたのを修正
※最小半径の判断、MOVL/ARC の切り替えは MOVL を使っているためで、MOVJ の場合そういった処理は不要になります。
通常の Pick & Place では、始点-終点の座標だけが重要で、通過点の軌跡が直線である必要はないので、MOVJ が最適です。
移動速度もかなり早くなります。
・・・そういうことも分からない頃に作ったものなので、ご注意を!
/* * Dobot Magician UART Control for Arduino MEGA * Dobot + Pixy2 Pick and Place Demo 2019.12.04 f.izawa * URL : http://www.izawa-web.com/ * e-mail : f.izawa@dream.com * * 2019/12/06 ピック範囲の制限を追加。 * Dobot の最小半径内を通る時、中間点を通るを追加。 * 制限範囲外の時は、ブザーを鳴らすを追加 * 2020/07/27 コード中 "=="と書くべきところが "=" になっていたのを修正 */ #include <Pixy2.h> // ********************** // Dobot IOFunction // ********************** enum { IOFunctionDummy, // Do not config function IOFunctionPWM, // PWM Output IOFunctionDO, // IO Output IOFunctionDI, // IO Input IOFunctionADC // AD Input }; // ********************** // ClearAllAlarmsState // ********************** int ClearAllAlarmsState(void) { byte buf[6]; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 0; // len= 2 + Payload Len; buf[3] = 20; // id; buf[4] = 1; // ctrl r/w($01) = W, isQueued($02) = false; buf[5] = 0xEB; // checkSum for (int i= 0; i<6; i++) Serial1.write(buf[i]); delay(100); int len = 6; int index = 0; while (index < 6 && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } return (index == 6 && buf[3] == 20); } // ********************** // GetQueuedCmdCurrentIndex // ********************** int GetQueuedCmdCurrentIndex(uint64_t &queuedCmdCurrentIndex, uint16_t msec) { byte buf[14]; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 0; // len= 2 + Payload Len; buf[3] = 246; // id;=0xF6 buf[4] = 0; // ctrl r/w = R, isQueued = False; buf[5] = 0x0A; // checkSum for (int i = 0; i < 6; i++) Serial1.write(buf[i]); delay(msec); int len = 14; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } if (index == len && buf[3] == 246){ queuedCmdCurrentIndex = buf[5+0] | buf[5+1] << 8 | buf[5+2] << 16 | buf[5+3] << 24 | buf[5+4] << 32 | buf[5+5] << 40 | buf[5+6] << 48 | buf[5+7] << 56; return true; } else return false; } // ********************** // GetPose // ********************** int GetPose(float &x, float &y, float &z, float &r) { union data{ byte buf[4]; float value; }f; byte buf[38]; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 0; // len= 2 + Payload Len; buf[3] = 10; // id; buf[4] = 0; // ctrl r/w = R, isQueued = False; buf[5] = 0xF6; // checkSum for (int i = 0; i < 6; i++) Serial1.write(buf[i]); delay(100); int len = 38; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } if (index == len && buf[3] == 10){ for (int i = 0; i < 4; i++) f.buf[i] = buf[5 + i]; x = f.value; for (int i = 0; i < 4; i++) f.buf[i] = buf[9 + i]; y = f.value; for (int i = 0; i < 4; i++) f.buf[i] = buf[13 + i]; z = f.value; for (int i = 0; i < 4; i++) f.buf[i] = buf[17 + i]; r = float(f.value); // 以降アーム角度が続くが、省略 // a0 : buf[21 + i]; // a1 : buf[25 + i]; // a2 : buf[29 + i]; // a3 : buf[33 + i]; return true; } else return false; } // ********************** // SetEndEffectorSuctionCup // ********************** int SetEndEffectorSuctionCup(byte ctrl, byte suck) { byte buf[14]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 2; // len= 2 + Payload Len; buf[3] = 62; // id; buf[4] = 3; // ctrl r/w($01) = W, isQueued($02) = false; buf[5] = ctrl; //isCtrlEnabled buf[6] = suck; //issucked for (int i=3; i < 7; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[7] = checkSum; for (int i = 0; i < 8; i++) Serial1.write(buf[i]); delay(100); int len = 14; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } return (index == len && buf[3] == 62); } // ********************** // GetEndEffectorSuctionCup // ********************** int GetEndEffectorSuctionCup(byte &isCtrlEnable, byte &isSucked) { byte buf[8]; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 0; // len= 2 + Payload Len; buf[3] = 62; // id; buf[4] = 0; // ctrl r/w(0x01) = R, isQueued(0x02) = false; buf[5] = 0xC2; // checkSum; for (int i = 0; i < 6; i++) Serial1.write(buf[i]); delay(100); int len = 8; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } if (index == len && buf[3] == 62){ isCtrlEnable = buf[5]; isSucked = buf[6]; return true; } else return false; } // ********************** // HomeCmd // ********************** int HomeCmd(void) { byte buf[14]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 4; // len= 2 + Payload Len; buf[3] = 31; // id; buf[4] = 3; // ctrl r/w = W, isQueued = True; // ダミー(4バイト) for (int i = 0; i < 4; i++) buf[5 + i] = 0; // チェックサム for (int i = 3; i<9; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[9] = checkSum; for (int i = 0; i < 10; i++) Serial1.write(buf[i]); delay(500); //最小 300 msec; int len = 14; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); Serial.print(buf[index], HEX); Serial.print(":"); index++; } if (index == len && buf[3] == 31){ uint64_t queuedCmdIndex = buf[5+0] | buf[5+1] << 8 | buf[5+2] << 16 | buf[5+3] << 24 | buf[5+4] << 32 | buf[5+5] << 40 | buf[5+6] << 48 | buf[5+7] << 56; Serial.print("\nqueuedCmdIndex="); char sbuf[50]; sprintf(sbuf, "%ld", queuedCmdIndex); Serial.print(sbuf); // ホーミング完了まで待つ uint64_t executedCmdIndex = 0; while (executedCmdIndex < queuedCmdIndex){ // 最小 1200 msec GetQueuedCmdCurrentIndex(executedCmdIndex, 1500); Serial.print("\nexecutedCmdIndex="); sprintf(sbuf, "%ld", executedCmdIndex); Serial.print(sbuf); } return true; } else{ return false; } } // ********************** // PTPCmd // ********************** int PTPCmd(float x, float y, float z, float r) { union data{ byte buf[4]; float value; }f; byte buf[23]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 17; // len= 2 + Payload Len; buf[3] = 84; // id; buf[4] = 3; // ctrl r/w = W, isQueued = True; buf[5] = 2; // PTPMode 2= MOVL_XYZ f.value = x; for (int i= 0 ; i < 4; i++) buf[6 + i] = f.buf[i]; f.value = y; for (int i= 0 ; i < 4; i++) buf[10 + i] = f.buf[i]; f.value = z; for (int i= 0 ; i < 4; i++) buf[14 + i] = f.buf[i]; f.value = r; for (int i= 0 ; i < 4; i++) buf[18 + i] = f.buf[i]; for (int i = 3; i < 22; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[22] = checkSum; for (int i = 0; i < 23; i++) Serial1.write(buf[i]); delay(100); int len = 14; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } if (index == len && buf[3] == 84){ uint64_t queuedCmdIndex = buf[5+0] | buf[5+1] << 8 | buf[5+2] << 16 | buf[5+3] << 24 | buf[5+4] << 32 | buf[5+5] << 40 | buf[5+6] << 48 | buf[5+7] << 56; Serial.print("\nqueuedCmdIndex="); char sbuf[50]; sprintf(sbuf, "%ld", queuedCmdIndex); Serial.print(sbuf); // 移動完了まで待つ uint64_t executedCmdIndex = 0; while (executedCmdIndex < queuedCmdIndex){ // 500msec は長いかも・・・ GetQueuedCmdCurrentIndex(executedCmdIndex, 500); Serial.print("\nexecutedCmdIndex="); sprintf(sbuf, "%ld", executedCmdIndex); Serial.print(sbuf); } return true; } else return false; } // ********************** // ArcCmd // ********************** int ArcCmd(float cirx, float ciry, float cirz, float cirr, float tox, float toy, float toz, float tor) { union data{ byte buf[4]; float value; }f; byte buf[38]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 32; // len= 2 + Payload Len; buf[3] = 101; // id; buf[4] = 3; // ctrl r/w = W, isQueued = True; f.value = cirx; for (int i= 0 ; i < 4; i++) buf[5 + i] = f.buf[i]; f.value = ciry; for (int i= 0 ; i < 4; i++) buf[9 + i] = f.buf[i]; f.value = cirz; for (int i= 0 ; i < 4; i++) buf[13 + i] = f.buf[i]; f.value = cirr; for (int i= 0 ; i < 4; i++) buf[17 + i] = f.buf[i]; f.value = tox; for (int i= 0 ; i < 4; i++) buf[21 + i] = f.buf[i]; f.value = toy; for (int i= 0 ; i < 4; i++) buf[25 + i] = f.buf[i]; f.value = toz; for (int i= 0 ; i < 4; i++) buf[29 + i] = f.buf[i]; f.value = tor; for (int i= 0 ; i < 4; i++) buf[33 + i] = f.buf[i]; for (int i = 3; i < 37; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[37] = checkSum; for (int i = 0; i < 38; i++) Serial1.write(buf[i]); delay(100); int len = 14; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } if (index == len && buf[3] == 101){ uint64_t queuedCmdIndex = buf[5+0] | buf[5+1] << 8 | buf[5+2] << 16 | buf[5+3] << 24 | buf[5+4] << 32 | buf[5+5] << 40 | buf[5+6] << 48 | buf[5+7] << 56; Serial.print("\nqueuedCmdIndex="); char sbuf[50]; sprintf(sbuf, "%ld", queuedCmdIndex); Serial.print(sbuf); // 移動完了まで待つ uint64_t executedCmdIndex = 0; while (executedCmdIndex < queuedCmdIndex){ // 500msec は長いかも・・・ GetQueuedCmdCurrentIndex(executedCmdIndex, 500); Serial.print("\nexecutedCmdIndex="); sprintf(sbuf, "%ld", executedCmdIndex); Serial.print(sbuf); } return true; } else return false; } // ********************** // SetIOMultiplexing // ********************** int SetIOMultiplexing(byte ioAddress, byte ioFunction) { byte buf[8]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 2; // len= 2 + Payload Len; buf[3] = 130; // id; buf[4] = 1; // ctrl r/w = W, isQueued = False; buf[5] = ioAddress; // EIO Num(1..20) buf[6] = ioFunction; // IOFunction, for (int i = 3; i < 7; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[7] = checkSum; for (int i = 0; i < 8; i++) Serial1.write(buf[i]); delay(100); // 10 msec でも大丈夫 int len = 8; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } return (index == len && buf[3] == 130); } // ********************** // SetIODO // ********************** int SetIODO(byte ioAddress, byte ioLevel) { byte buf[8]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 2; // len= 2 + Payload Len; buf[3] = 131; // id; buf[4] = 1; // ctrl r/w = W, isQueued = False; buf[5] = ioAddress; // EIO Num(1..20) buf[6] = ioLevel; // Level output 0-Low level 1-High level for (int i = 3; i < 7; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[7] = checkSum; for (int i = 0; i < 8; i++) Serial1.write(buf[i]); delay(100); // 10 msec でも大丈夫 int len = 8; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } return (index == len && buf[3] == 131); } // ********************** // GetIODO // ********************** int GetIODO(byte ioAddress, byte &ioLevel) { byte buf[8]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 2; // len= 2 + Payload Len; buf[3] = 131; // id; buf[4] = 0; // ctrl r/w = r, isQueued = False; buf[5] = ioAddress; buf[6] = 0; for (int i = 3; i < 7; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[7] = checkSum; for (int i = 0; i < 8; i++) Serial1.write(buf[i]); delay(100); // 10 msec でも大丈夫 int len = 8; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } if (index == len && buf[3] == 131 && buf[5] == ioAddress){ ioLevel = buf[6]; return true; } else return false; } // ********************** // GetIODI // ********************** int GetIODI(byte ioAddress, byte &ioValue) { byte buf[8]; byte checkSum = 0; buf[0] = 0xAA; buf[1] = 0xAA; buf[2] = 2 + 2; // len= 2 + Payload Len; buf[3] = 133; // id; buf[4] = 0; // ctrl r/w = r, isQueued = False; buf[5] = ioAddress; buf[6] = 0; for (int i = 3; i < 7; i++) checkSum = checkSum + buf[i]; checkSum = 0x100 - checkSum; buf[7] = checkSum; for (int i = 0; i < 8; i++) Serial1.write(buf[i]); delay(100); // 10 msec でも大丈夫 int len = 8; int index = 0; while (index < len && Serial1.available() > 0) { buf[index] = Serial1.read(); index++; } if (index == len && buf[3] == 133 && buf[5] == ioAddress){ ioValue = buf[6]; return true; } else return false; } Pixy2 pixy; const int pixyW = 316; // Pixy2 水平解像度 const int pixyH = 208; // Pixy2 垂直解像度 // プログラム開始位置 float startPosX = 200.0; float startPosY = 0.0; float startPosZ = 0.0; float startPosR = 0.0; // キャプチャ位置(カメラの中心線が Dobot の中心を通ること) // Pixy2 の取付角度によってある程度制限される float captureX = 220.0; float captureY = -48.7; float captureZ = 70.0; // 吸引チューブの影ができるので、回転 float captureR = 90.0; // プレース位置(7点) // Arduino 版では、通過点の処理をしていないため // Dobot の最小半径にかかる位置は指定しないほうが良い float placingX[] = { 100.0, 50.0, 0.0, 100.0, 50.0, 0.0, -50.0}; float placingY[] = {-200.0, -200.0, -200.0, -250.0, -250.0, -250.0, -250.0}; float placingZ[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // 吸引時のZ座標 float suctionZ = -60.0; // 移動中のZ値 float movingZ = 0.0; // Doobot の床レベル(重要) float dobotFL = -130.0; // ピッキングの Z 値が Dobot フロアーレベルの時、エラーにならない半径 float radMin = 220.0; float radMax = 320.0; // ピッキング範囲の制限 Y 値 float pickAreaYMin = -110.0; float pickAreaYMax = 110.0; // Z = 0 の時、エラーにならない最小半径 // Dobot PTPCmd は 2 点間を直線移動するため、この半径内を通る時は、中間点を追加する float radLimMin = 140.0; // カメラ位置 // アームを X 軸方向(Y=0)にした状態で、基準座標からの相対距離 float pixyOffX = 30.0; float pixyOffY = 53.0; // ピクセルからミリへの変換係数の初期値(キャプチャ時の Z により再計算される) // キャプチャ高さが固定であれば、固定値で良い float pixToMMScale = 0.7308; // 外部スイッチ入力 const int PICKPLACE_PIN = 31; const int HOMING_PIN = 33; const int DOTEST_PIN = 35; const int ARCTEST_PIN = 37; const int LED_PIN = 41; const int BUZZER_PIN = 11; // PWM OUT // ****************************** // 座標変換 // ****************************** float degToRad(float deg){ return (PI * deg) / 180.0; } float radToDeg(float rad){ return (rad * 180.0) / PI; } float getAngle(float x, float y){ float ang = 0.0; if (x != 0.0){ ang = abs(atan(y / x)); if ((x < 0.0) && (y >= 0.0)) ang = PI - ang; else if ((x >= 0.0) && (y < 0.0)) ang = PI * 2.0 - ang; else if ((x < 0.0) && (y < 0.0)) ang = ang + PI; } return ang; } float getDistance(float x, float y){ return sqrt(sq(x) + sq(y)); } void getPolar(float x, float y, float rad, float dist, float &resX, float &resY){ resX = dist * cos(rad) + x; resY = dist * sin(rad) + y; } // Z軸廻りに左回転 void rotateZ(float x, float y, float rad, float &resX, float &resY){ resX = x * cos(rad) + y * sin(rad); resY = x * -sin(rad) + y * cos(rad); } void rotatePoint(float genX, float genY, float x, float y, float rad, float &resX, float &resY){ rotateZ(x - genX, y - genY, rad, resX, resY); resX = resX + genX; resY = resY + genY; } // 垂線 void getPerPoint(float ptX, float ptY, float x1, float y1, float x2, float y2, float &resX, float &resY){ float faz = 0.00000001; if (abs(x2 - x1) <= faz){ resX = x1; resY = ptY; } else if (abs(y2 - y1) <= faz){ resX = ptX; resY = y1; } else { float ang = atan((y2-y1) / (x2-x1)); float xx, yy; rotatePoint(x1, y1, ptX, ptY, ang, xx, yy); rotatePoint(x1, y1, xx, y1, -ang, resX, resY); } } // Pixy 座標をDobot座標に void pixyToDobotXY(int pixX, int pixY, float poseX, float poseY, float poseZ, float &resX, float &resY){ // Z = 0 の時のカメラ位置から Dobot の床レベルまでの距離を基準にする float baseZ = poseZ - dobotFL; // キャプチャ画像の座標を左下原点の座標に int pxx = pixX; int pxy = pixyH - pixY; // Dobot アームの回転角度 float ang0 = getAngle(poseX, poseY); // Dobot のヘッド座標からのカメラの方向と距離 float pxdist = getDistance(pixyOffX, pixyOffY); float pxang = getAngle(pixyOffX, pixyOffY); // カメラ位置 float camx = pxdist * cos(pxang + ang0) + poseX; float camy = pxdist * sin(pxang + ang0) + poseY; // キャプチャ高さが一定であれば、再計算の必要ない // Pixy画面一杯の横幅(これが基準)カメラの水平レンズ視野角度60°の 1 / 2 float pcw = baseZ * tan(degToRad(30.0)) * 2.0; pixToMMScale = pcw / pixyW; //ピクセル基準 // Pixy画面の中心を 0, 0 にした座標に(ピクセル単位)それをミリメートルに float cadx = (pxx - pixyW / 2.0) * pixToMMScale; float cady = (pxy - pixyH / 2.0) * pixToMMScale; // 中心からの角度と距離(ミリメートル単位) float dist = getDistance(cadx, cady); float rad = getAngle(cadx, cady); // カメラの座標から同じ距離、角度の座標を取得(角度はカメラ角度分を足す) resX = dist * cos(rad - PI / 2.0) + camx; resY = dist * sin(rad - PI / 2.0) + camy; //dobotPartX = dist * cos(rad - PI / 2.0) + camx; //dobotPartY = dist * sin(rad - PI / 2.0) + camy; } // ********************** // setup // ********************** boolean homingFlag = false; boolean pickingFlag = false; boolean dotestFlag = false; boolean arctestFlag = false; void setup() { // GPIO pinMode(PICKPLACE_PIN, INPUT_PULLUP); pinMode(HOMING_PIN, INPUT_PULLUP); pinMode(DOTEST_PIN, INPUT_PULLUP); pinMode(ARCTEST_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); // PWM buzzer // シリアルモニタ Serial.begin(115200); // Dobot UART Serial1.begin(115200); // Pixy2 初期化 Serial.print("\npixyInit "); pixy.init(); pixy.setLamp(0, 0); //SetIOMultiplexing(18, IOFunctionDO); //SetIOMultiplexing(20, IOFunctionDI); ClearAllAlarmsState(); digitalWrite(LED_PIN, HIGH); PTPCmd(startPosX, startPosY, startPosZ, startPosR); digitalWrite(LED_PIN, LOW); homingFlag = false; pickingFlag = false; dotestFlag = false; } void loop() { // ピック&プレース if (!pickingFlag && !digitalRead(PICKPLACE_PIN)){ pickingFlag = true; delay(500); Serial.print("\nPICK&PLACE ... "); // キャプチャ位置へ移動 //digitalWrite(LED_PIN, HIGH); PTPCmd(captureX, captureY, captureZ, captureR); //digitalWrite(LED_PIN, LOW); delay(50); // Pixy2 の照明を ON pixy.setLamp(1, 1); delay(400); // キャプチャ中 ... のLED digitalWrite(LED_PIN, HIGH); delay(50); // Pixy2 でブロックを検出 static int activeSignature; pixy.ccc.getBlocks(); Serial.print("\nBlocks = "); Serial.print(pixy.ccc.numBlocks); delay(100); // キャプチャ中 ... の LED を消す digitalWrite(LED_PIN, LOW); if (pixy.ccc.numBlocks > 0){ float dobotPartX = 0.0; float dobotPartY = 0.0; int loopFlag = true; int index = 0; int activeIndex = -1; while (loopFlag && index < pixy.ccc.numBlocks){ pixy.ccc.blocks[index].print(); // 毎回、最初に見つかった 1 個を採用 activeSignature = pixy.ccc.blocks[0].m_signature; // Pixy2 画像を Dobot 座標に変換 pixyToDobotXY( pixy.ccc.blocks[index].m_x, pixy.ccc.blocks[index].m_y, captureX, captureY, captureZ, dobotPartX, dobotPartY); float dist = getDistance(dobotPartX, dobotPartY); Serial.print("\ncadDist= "); Serial.print(dist); Serial.print("\npartX= "); Serial.print(dobotPartX); Serial.print("\npartY= "); Serial.print(dobotPartY); Serial.print("\npartAge= "); Serial.print(pixy.ccc.blocks[index].m_age); // ピッキング範囲と Pixy2 検出の Age によって制限(ちらちらしているものは、Age が若い、安定しているものは Age =255) if (dist >= radMin && dist <= radMax && dobotPartY >= pickAreaYMin && dobotPartY <= pickAreaYMax && pixy.ccc.blocks[index].m_age >= 100 && activeSignature < 7){ activeIndex = index; loopFlag = false; Serial.print("\ndobotPartX="); Serial.print(dobotPartX); Serial.print("\ndobotPartY="); Serial.print(dobotPartY); } index++; } // 制限範囲外、またはちらつき if (activeIndex == -1){ // ブザーを鳴らす tone(BUZZER_PIN, 800, 250) ; // 800Hz, 250msec //analogWrite(BUZER_PIN, 128); //delay(500); //analogWrite(BUZZER_PIN, 0); } else { // Pixy2 画像を Dobot 座標に変換 delay(100); // Pixy2 の照明を消す pixy.setLamp(0, 0); digitalWrite(LED_PIN, HIGH); // 検出位置に移動 PTPCmd(dobotPartX, dobotPartY, movingZ, 0.0); // 下げる PTPCmd(dobotPartX, dobotPartY, suctionZ, 0.0); // 吸引 SetEndEffectorSuctionCup(1,1); // 上げる PTPCmd(dobotPartX, dobotPartY, movingZ, 0.0); // 最小半径にかかる時は、中間点を追加 float resX = 0.0; float resY = 0.0; getPerPoint(0, 0, dobotPartX, dobotPartY, placingX[activeSignature], placingY[activeSignature], resX, resY); float dist = getDistance(resX, resY); Serial.print("\ndist = "); Serial.print(dist); float ang = getAngle(resX, resY); if (dist < radLimMin) { tone(BUZZER_PIN, 1500, 1000) ; Serial.print(" MidPoint ... "); getPolar(0, 0, ang, radLimMin, resX, resY); // 中間点を通る折れ線移動でプレース位置へ //PTPCmd(resX, resY, placingZ[activeSignature], 0.0); //PTPCmd(placingX[activeSignature], placingY[activeSignature], placingZ[activeSignature], 0.0); // 中間点を通る円弧移動でプレース位置へ ArcCmd(resX, resY, placingZ[activeSignature], 0.0, placingX[activeSignature], placingY[activeSignature], placingZ[activeSignature], 0.0); } else{ // プレース位置へ移動 PTPCmd(placingX[activeSignature], placingY[activeSignature], placingZ[activeSignature], 0.0); } // 離す SetEndEffectorSuctionCup(1, 0); // Z 座標 0 でキャプチャ位置に戻す PTPCmd(captureX, captureY, movingZ, 0.0); digitalWrite(LED_PIN, LOW); } } else{ // 見つからない(ブザーは鳴らさない) delay(490); } pickingFlag = false; } // ホーミング else if (!homingFlag && !digitalRead(HOMING_PIN)){ homingFlag = true; delay(500); Serial.print("\nHOMING ... "); // ホーミング中 ... digitalWrite(LED_PIN, HIGH); //SetIOMultiplexing(18, IOFunctionDO); //SetIODO(18, 1); HomeCmd(); digitalWrite(LED_PIN, LOW); //SetIODO(18, 0); homingFlag = false; } else if (!dotestFlag && digitalRead(DOTEST_PIN) == LOW){ dotestFlag = true; delay(500); Serial.print("\nDOTEST ... "); digitalWrite(LED_PIN, HIGH); //SetIOMultiplexing(18, IOFunctionDO); //byte ioLevel; //GetIODO(18, ioLevel); //SetIODO(18, 1);//!ioLevel); dotestFlag = false; } // ArcCmd のテスト else if (!arctestFlag && !digitalRead(ARCTEST_PIN)){ arctestFlag = true; delay(500); Serial.print("\nARCTEST ... "); digitalWrite(LED_PIN, HIGH); PTPCmd(200.0, 150.0, 0.0, 0.0); ArcCmd(250.0, 0.0, 0.0, 0.0, 200.0, -150.0, 0.0, 0.0); digitalWrite(LED_PIN, LOW); arctestFlag = false; } delay(10); }