示範影片:
機構總覽:
- 托盤 加 輸送帶:
透過PFMate控制LEGO PF馬達驅動輸送帶,並使用EV3 Touch sensor控制PFMate一次只運送一個積木給顏色感應器。EV3 Touch Sensor - 顏色辨識:使用EV3 Color sensor
EV3 Color Sensor - 積木傳送機構(Brick feeder):
以一顆EV3中型馬達驅動包含:抓取以及傳送兩個動作的Under-actuation機構(即:機構的自由度大於驅動的馬達數目)。Brick Feeder機構(Under-actuation) - 積木載入機構(Brick loader):
透過PFMate控制LEGO PF伺服馬達將Technic beam垂直抬舉,以方便機械手臂抓取。Brick Loader機構 - 機械手臂機構 加 積木分色置放槽:
透過NXTServo驅動一個四個自由度的機械手臂將積木放入各個顏色的置放槽中。Robot Arm
- 輸送待分類積木:
以輸送帶由托盤一次運送一個Technic beam給Color Sensor進行辨識,。 - 顏色辨識:
當Color Sensor測量到color value非等於None時,就可以判斷已經有一個積木正等待分類,接著就驅動Brick Feeder將積木傳送給Brick Loader。 - 轉送積木給機械手臂:透過判讀Brick Feeder Under-actuation機構 的EV3中型馬達RPM值,可以判斷積木已經轉送到Brick Loader,接著驅動Brick Loader將積木垂直抬起。
- 積木分類:以機械手臂從Brick Loader抓取積木放置在不同顏色的分類槽中(紅' 白' 黃),而如果不是上述三種顏色的積木,機械手臂會移到後方丟棄。
RobotC I2C通訊程式摘要:
- PFMate與NXTServo等I2C數位感應器的Sensor Type需要設定成 sensorEV3_GenericI2C
#pragma config(Sensor, S1, EV3_COLOR, sensorEV3_Color, modeEV3Color_Color)
#pragma config(Sensor, S2, EV3_TOUCH, sensorEV3_Touch)
#pragma config(Sensor, S3, PFMATE, sensorEV3_GenericI2C)
#pragma config(Sensor, S4, NXTSERVO, sensorEV3_GenericI2C)
#pragma config(Motor, motorA, EV3_Mmotor, tmotorEV3_Medium, PIDControl, encoder)
- 讀取I2C Sensor Value的範例程式碼:
首先需要先寫入I2C bus 以及所要讀取的register位址,等EV3完成建立通訊之後,再傳送資料buffer以及讀取的資料byte數。
//////////////////////////////////////////////////////////////////////////////////////////
// Read battery voltage value of NXTServo.
//////////////////////////////////////////////////////////////////////////////////////////
float getNXTServoBatteryVoltage()
{
TI2CStatus nStatus;
ubyte I2C_Request[3], I2C_Reply[1];
short errCnt=0;
while(nI2CStatus[NXTSERVO] == i2cStatusPending) {
errCnt++;
if(errCnt>500) {
displayBigTextLine(7, "NXTServo_TimeOut(M)");
delay(5000);
return false;
}
delay(10);
}
memset(I2C_Request, 3, 0);
I2C_Request[0] = 2;
I2C_Request[1] = NXTSERVO_ADDR;
I2C_Request[2] = 0x41;
sendI2CMsg(NXTSERVO, &I2C_Request[0], 1);
delay(100); // Do not change this value, or servos will unstable.
while(nI2CStatus[NXTSERVO] == i2cStatusPending) wait1Msec(1);
memset(I2C_Reply, 1, 0);
nStatus = readI2CReply(NXTSERVO, &I2C_Reply[0], 1);
return ((4700.0/127.0)*I2C_Reply[0]);
}
寫入I2C 裝置的範例程式碼:
//////////////////////////////////////////////////////////////////////////////////////////
// Control multiple servors simultaneously.
//////////////////////////////////////////////////////////////////////////////////////////
bool setMultiServo(const int delayMSec)
{
TI2CStatus nStatus;
ubyte I2C_Request[19];
short errCnt=0;
while(nI2CStatus[NXTSERVO] == i2cStatusPending) {
errCnt++;
if(errCnt>500) {
displayBigTextLine(7, "NXTServo_TimeOut(M)");
delay(5000);
return false;
}
delay(10);
}
// Set servo speed
memset(I2C_Request, 19, 0);
I2C_Request[0] = 2+NO_OF_SERVOS;
I2C_Request[1] = NXTSERVO_ADDR;
I2C_Request[2] = servoSpeedReg[0];
for(int xi=0; xi<NO_OF_SERVOS; xi++) {
I2C_Request[xi+3] = servoArray[xi].servoSpeed;
}
sendI2CMsg(NXTSERVO, &I2C_Request[0], 0);
delay(200); // Do not change this value, or servos will unstable.
// Set servo position
memset(I2C_Request, 0, 19);
I2C_Request[0] = 2+NO_OF_SERVOS*2;
I2C_Request[1] = NXTSERVO_ADDR;
I2C_Request[2] = servoPosReg[0];
for(int xi=0; xi<NO_OF_SERVOS; xi++) {
I2C_Request[2*xi+3] = (servoArray[xi].servoPos & 0x00FF);
I2C_Request[2*xi+4] = ((servoArray[xi].servoPos >> 8) & 0x00FF);
}
nStatus = sendI2CMsg(NXTSERVO, &I2C_Request[0], 0);
delay(delayMSec);
return (nStatus == i2cStatusNoError);
}
樓主 你好 之前在查閱ROBOTC的文檔發現沒有提供同步原語的支持 不知道樓主的作品有沒有這樣的需要 有的話是要自己實作嗎?
回覆刪除你好, 我查過確實也是沒有, 我的作法是使用多執行緒, 透過全域變數狀態去控制
回覆刪除恭喜RobotC官方部落格推薦文章!
回覆刪除http://www.robotc.net/blog/2015/07/22/lego-ev3-sorter-machine/
謝謝邱老師告知,
刪除大約一個多月前, 收到一個 mail 邀請我提供程式碼與照片給 RobotC, 原來是放到他們的部落格, 早知道影片應該多一點 RobotC的介紹 ^^