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);
}