RoBoard魔人的機器人日誌

2011/10/20

[教學] 如何控制RS0263-DMP小手

DMP小手 (RS0263*3)


RS0263為RoBoard的馬達
必須用RC servo控制馬達轉動

  • RC servo的控制原理
  1. 利用 PWM pulse 的寬度指定 servo 轉動的位置
  2. controller circuit 控制 servo 轉到指定的位置
  3. feedback potentiometer 會將 servo 目前的位置迴授給控制器
由於RS0263沒有feedback的功能
所以並不會將servo的位置回傳


  • 腳位相對位置
RB100有24個PWM
而RB110只有16個PWM
但其實還是十分好分辨的
靠外側的腳位為地(GND) 通常接的為黑線
靠中間的腳位為電(Vxx) 通常接的為紅線
靠內側的腳位為訊號(GPxx) 沒有特定顏色

切記勿接錯 否則會發生慘案

然而腳位編號請看官網的介紹投影片(Hardware Introduction Slide)


  • RC Servo lib
 rcservo_Init(...);
這邊記得將要用的所有Pin腳都加入
例如要加入1號與5號的腳位即:
rcservo_Init(RCSERVO_USEPINS1 + RCSERVO_USEPINS5);



 rcservo_SetServo(pin, servo_model);
SetServo要為妳要用的腳位設定傳輸的型態
這lib很佛心的是 幾乎所有會用到的RCservo 都已經先幫我們寫好型態了
所以只要依照馬達給相對應的模式 就可以使用了


rcservo_EnterPWMMode()
這是一個告訴PWM要開始的函式

然而傳輸方式有以下兩種
1. rcservo_SendPWM(pin, PWM period, PWM duty, count)

2. reservo_SendCPWM(pin, PWM period, PWM duty)

相信有人會問兩者的差別
第1種方法要搭配另一個函式rcservo_IsPWMCompleted(pin)
如函式名稱所寫   它是用來判斷此腳位的通訊是否完成
然而第一種方法的count就是要連續發出count筆通訊資料給馬達
當然在發資料的同時 程式會繼續往下跑    為了讓程式能稍稍暫停
就會用到判斷通訊完成的函式了

第二種方法雖然比較好用
不過使用時必須要小心
因為它是一直傳送通訊資料
直到使用函式reservo_StopPWM(pin)為止

兩者各有優缺

















code: 用G146地磁控制DMP小手做剪刀石頭布
#include "stdio.h"
#include "conio.h"
#include "roboard.h"
#include "roboard_dll.h"
void rock(unsigned long);
void paper(unsigned long);
void scissors(unsigned long);
const unsigned char acceler_addr = 0x30>>1;
int main(void)
{
 roboio_SetRBVer(RB_110);
 rcservo_Init(RCSERVO_USEPINS1 + RCSERVO_USEPINS2 + RCSERVO_USEPINS3);
 rcservo_SetServo(RCSERVO_PINS1, RCSERVO_DMP_RS0263);
 rcservo_SetServo(RCSERVO_PINS2, RCSERVO_DMP_RS0263);
 rcservo_SetServo(RCSERVO_PINS3, RCSERVO_DMP_RS0263);
 rcservo_EnterPWMMode();

    i2c_Initialize(I2CIRQ_DISABLE);
 i2c0_SetSpeed(I2CMODE_AUTO, 400000L);
 i2c0master_StartN(acceler_addr, I2C_WRITE,2);
 i2c0master_WriteN(0x20);
 i2c0master_WriteN(0x37);

 unsigned int acceler_X, acceler_Y,mode,lastmode;
 unsigned long PWM_period = 10000L;
 while(!kbhit()){
  i2c0master_StartN(acceler_addr, I2C_WRITE,1);
  i2c0master_WriteN(0x29);
  i2c0master_StartN(acceler_addr, I2C_READ,1);
  acceler_X = i2c0master_ReadN();

  i2c0master_StartN(acceler_addr, I2C_WRITE,1);
  i2c0master_WriteN(0x2b);
  i2c0master_StartN(acceler_addr, I2C_READ,1);
  acceler_Y = i2c0master_ReadN();
  
  mode = 0;
  mode = acceler_X >= 0x80 ? mode + 1 : mode;
  mode = acceler_Y >= 0x80 ? mode + 2 : mode;
  switch(mode){
     case 0:
      if(lastmode != mode)
       printf("paper!\n");
      paper(PWM_period);
      break;
     case 1:
      if(lastmode != mode)
       printf("scissors!\n");
      scissors(PWM_period);
      break;
     case 3:
      if(lastmode != mode)
       printf("rock!\n");
      rock(PWM_period);
      break;
  }
  lastmode = mode;
 }
 i2c_Close();
 rcservo_Close();
 return 0;
}
void rock(unsigned long PWM_period){
 unsigned long PINS1_duty = 1900L;
 unsigned long PINS2_duty = 700L;
 unsigned long PINS3_duty = 1900L;
 rcservo_SendCPWM(RCSERVO_PINS1, PWM_period, PINS1_duty);
 rcservo_SendCPWM(RCSERVO_PINS2, PWM_period, PINS2_duty);
 rcservo_SendCPWM(RCSERVO_PINS3, PWM_period, PINS3_duty);
}
void paper(unsigned long PWM_period){
 unsigned long PINS1_duty = 700L;
 unsigned long PINS2_duty = 1900L;
 unsigned long PINS3_duty = 700L;
 rcservo_SendCPWM(RCSERVO_PINS1, PWM_period, PINS1_duty);
 rcservo_SendCPWM(RCSERVO_PINS2, PWM_period, PINS2_duty);
 rcservo_SendCPWM(RCSERVO_PINS3, PWM_period, PINS3_duty);
}
void scissors(unsigned long PWM_period){
 unsigned long PINS1_duty = 1900L;
 unsigned long PINS2_duty = 1900L;
 unsigned long PINS3_duty = 1900L;
 rcservo_SendCPWM(RCSERVO_PINS1, PWM_period, PINS1_duty);
 rcservo_SendCPWM(RCSERVO_PINS2, PWM_period, PINS2_duty);
 rcservo_SendCPWM(RCSERVO_PINS3, PWM_period, PINS3_duty);
}
Share:

2011/10/17

[教學] 如何控制RM-G146陀螺儀

RM-G146

 

 
控制G146必須要用I2C去控制
因為我這邊使用的範例為RB110

 
所以沒有特別再去弄線材
首先必須知道的資訊
陀螺儀的位址 在0xD0
以及陀螺儀的XYZ軸的位址
AddrHex   AddrDecimal     Register Name        
1D             29                       GYRO_XOUT_H
1E             30                       GYRO_XOUT_L

 
1F             31                       GYRO_YOUT_H
20             32                       GYRO_YOUT_L

 
21             33                       GYRO_ZOUT_H
22             34                       GYRO_ZOUT_L
這樣就可以用一些基本的指令去讀取陀螺儀得值了

 
而I2C的讀取方法為
| start | slave address | R/W | A | data | A/A |stop |

 
所以基本上會用到的指令有
i2c0master_StartN(slave address,R/W,byte)           告訴某位置要讀或寫N的byte
i2c0master_WriteN(byte)           寫入的值
i2c0master_ReadN()          會回傳一個值

 
在W/R之後會值接回傳STOP

 
所以無須再傳stop

 

 

 


 

 

 

 

 

 

 

 
範例code    用G146控制AX-12馬達:

#include "stdio.h"
#include "conio.h"
#include "windows.h"
#include "roboard.h"
#include "roboard_dll.h"

const unsigned char gyro_addr = 0xD0>>1;

int main()
{
 unsigned int gyro_X, gyro_Y, d;
 unsigned char cmd1[11] = {0xff, 0xff, 0x01, 0x07, 0x03, 0x1e, 0x00, 0x02, 0x00, 0x02, 0x00};
 unsigned char cmd2[11] = {0xff, 0xff, 0x02, 0x07, 0x03, 0x1e, 0x00, 0x02, 0x00, 0x02, 0x00};
 unsigned char buf[6] = {0};
 unsigned int i = 0;

 roboio_SetRBVer(RB_110);

 com3_Init(COM_HDUPLEX);
 com3_SetFormat(COM_BYTESIZE8, COM_STOPBIT1, COM_NOPARITY);
 com3_SetBaud(COMBAUD_115200BPS);

    i2c_Initialize(I2CIRQ_DISABLE);
 i2c0_SetSpeed(I2CMODE_AUTO, 400000L);
 i2c0master_StartN(gyro_addr, I2C_WRITE,2);
 i2c0master_WriteN(0x16);
 i2c0master_WriteN(0x18);
 while(i++ < 60){
  i2c0master_StartN(gyro_addr, I2C_WRITE,1);
  i2c0master_WriteN(0x1d);
  i2c0master_StartN(gyro_addr, I2C_READ,1);
  gyro_X = i2c0master_ReadN();
  gyro_X = gyro_X << 8;
  
  i2c0master_StartN(gyro_addr, I2C_WRITE,1);
  i2c0master_WriteN(0x1e);
  i2c0master_StartN(gyro_addr, I2C_READ,1);
  d = i2c0master_ReadN();
  gyro_X = gyro_X + d;

  i2c0master_StartN(gyro_addr, I2C_WRITE,1);
  i2c0master_WriteN(0x1f);
  i2c0master_StartN(gyro_addr, I2C_READ,1);
  gyro_Y = i2c0master_ReadN();

  gyro_Y = (gyro_Y + 1) &(~256);
  gyro_Y = gyro_Y << 8;

  i2c0master_StartN(gyro_addr, I2C_WRITE,1);
  i2c0master_WriteN(0x20);
  i2c0master_StartN(gyro_addr, I2C_READ,1);
  d = i2c0master_ReadN();
  gyro_Y = gyro_Y + d;
  
  gyro_X /= 0x40;
  if(gyro_X > 0x1ff){
   gyro_X -= 0x200;
   if(cmd1[6] + (gyro_X % 0x100) >= 0x100){
    cmd1[6] = cmd1[6] + (gyro_X % 0x100) - 0x100;
    cmd1[7] = cmd1[7] + 0x01;
   }else{
    cmd1[6] = cmd1[6] + (gyro_X % 0x100);
    cmd1[7] = cmd1[7] + (gyro_X >> 8);
   }
  }else{
   cmd1[6] = cmd1[6] + (gyro_X % 0x100) - 0x1ff; 
   cmd1[7] = cmd1[7] + (gyro_X >> 8) - 0x1ff;
  }

  gyro_Y /= 0x40;
  if(gyro_Y > 0x1ff){
   gyro_Y -= 0x200;
   if(cmd2[6] + (gyro_Y % 0x100) >= 0x100){
    cmd2[6] = cmd2[6] + (gyro_Y % 0x100) - 0x100;
    cmd2[7] = cmd2[7] + 0x01;
   }else{
    cmd2[6] = cmd2[6] + (gyro_Y % 0x100);
    cmd2[7] = cmd2[7] + (gyro_Y >> 8);
   }
  }else{
   cmd2[6] = cmd2[6] + (gyro_Y % 0x100) - 0x1ff; 
   cmd2[7] = cmd2[7] + (gyro_Y >> 8) - 0x1ff;
  }

  cmd1[7] = cmd1[7] >= 0x03 ? 0x03 : cmd1[2];
  cmd1[7] = cmd1[7] < 0x00 ? 0x00 : cmd1[2];
  cmd2[7] = cmd2[7] >= 0x03 ? 0x03 : cmd2[2];
  cmd2[7] = cmd2[7] < 0x00 ? 0x00 : cmd2[2];

  cmd1[10] = ~(cmd1[2] + cmd1[3] + cmd1[4] + cmd1[5] + cmd1[6] + cmd1[7] + cmd1[8] + cmd1[9]);
  cmd2[10] = ~(cmd2[2] + cmd2[3] + cmd2[4] + cmd2[5] + cmd2[6] + cmd2[7] + cmd2[8] + cmd2[9]);
  com3_ServoTRX(cmd1, 11, buf, 6);
  com3_ServoTRX(cmd2, 11, buf, 6);
  _sleep(250);
 }
 i2c_Close();
 com3_Close();
 return 0;
}
Share:

2011/10/7

[教學] 如何控制Bioloid AX-12馬達

上一個星期已經告訴過各位AX-12是如何傳輸的

那現在要控制其實已經差不遠了

首先必須要有一條com3轉接AX-12的轉接線
然後就可以開始撰寫程式部分了

首先要先將專案屬性先設定好

組態先選擇為Release (因為Debug會出現問題)

要把組態結構 -> C/C++ -> 一般 其中的 "其他Include目錄" 將他指定到RoBoIO-bin-v1.8-winxp\Include

然後組態結構 -> 連結器 -> 一般 中的 "其他程式庫目錄"  將他指定RoBoIO-bin-v1.8-winxp\Lib\VC2008

最後將組態結構 -> 連結器 -> 輸入 中的 "其他相依性" 內容輸入RoBoIO.lib

這樣設定好  就可以使用RoBoard的Lib了













首先程式碼

必須要有的是設定RB的型號
 roboio_SetRBVer(RB_100); 
Or
roboio_SetRBVer(RB_110);

之後就是做com3的設定了

首先至少要有2個array

一個是傳出 一個是傳入

將初值都設定好了之後

先做com3 Init的動作

然後設定Data Formate
com3_SetFormat(bytesize, stopbit, parity);
bytesize是每筆資料共有幾個bits
stopbit為停止位元
parity則是設定檢查碼的方式

接著設定Baud

Baud是用來讓RoBoard和馬達之間有一個共同的速度傳輸

否則收發速度不同則會導致資料錯亂

接著就可以開始設計一整個程式碼了

當中會用到的有
com3_ServoTRX(cmd, csize, buf, size);
cmd為傳出給馬達的資料陣列
csize為cmd的size
buf是用來儲存馬達回傳的值  通常若有錯誤訊息可以在這找到
size為buf的size

然後在程式的末端

記得打上com3_Close();

將com3關閉






#include "stdio.h"
#include "conio.h"
#include "roboard.h"

int main(void)
{
 unsigned char c;
 unsigned char cmd1[11] = {0xff, 0xff, 0x01, 0x07, 0x03, 0x1e, 0x00, 0x02, 0x00, 0x02, 0x00};
 unsigned char cmd2[11] = {0xff, 0xff, 0x03, 0x07, 0x03, 0x1e, 0x00, 0x02, 0x00, 0x02, 0x00};
 unsigned char buf[6] = {0};
 int num1, num2;

 num1 = num2 = 0x200;
 roboio_SetRBVer(RB_110);

 if(com3_Init(COM_HDUPLEX) == false)
 {
  printf("Init COM3 fail\n");
  return 1;
 }

 com3_SetFormat(COM_BYTESIZE8, COM_STOPBIT1, COM_NOPARITY);
 com3_SetBaud(COMBAUD_115200BPS);

 while((c = _getch()) != 27)
 {
  switch(c)
  {
  case 'a': case 'A':
   num1 += 0x05;
   break;
  case 'z': case 'Z':
   num1 -= 0x05;
   break;
  case 's': case 'S':
   num2 += 0x05;
   break;
  case 'x': case 'X':
   num2 -= 0x05;
   break;
  default:
   break;
  }
  
  switch(c)
  {
  case 'a': case 'A': case 'z': case 'Z':
   if(num1 < 0) num1 = 0x0000;
   if(num1 > 0x3ff) num1 = 0x3ff;
   cmd1[7] = (unsigned char) ((num1 >> 8) & 0xff);
   cmd1[6] = num1 & 0xff;
   cmd1[10] = ~(cmd1[2] + cmd1[3] + cmd1[4] + cmd1[5] + cmd1[6] + cmd1[7] + cmd1[8] + cmd1[9]);
   com3_ServoTRX(cmd1, 11, buf, 6);
   break;
  case 's': case 'S': case 'x': case 'X':
   if(num2 < 0) num2 = 0x0000;
   if(num2 > 0x3ff) num2 = 0x3ff;
   cmd2[7] = (unsigned char) ((num2 >> 8) & 0xff);
   cmd2[6] = num2 & 0xff;
   cmd2[10] = ~(cmd2[2] + cmd2[3] + cmd2[4] + cmd2[5] + cmd2[6] + cmd2[7] + cmd2[8] + cmd2[9]);
   com3_ServoTRX(cmd2, 11, buf, 6);
   break;
  default:
   cmd1[10] = ~(cmd1[2] + cmd1[3] + cmd1[4] + cmd1[5] + cmd1[6] + cmd1[7] + cmd1[8] + cmd1[9]);
   cmd2[10] = ~(cmd2[2] + cmd2[3] + cmd2[4] + cmd2[5] + cmd2[6] + cmd2[7] + cmd2[8] + cmd2[9]);
   com3_ServoTRX(cmd1, 11, buf, 6);
   com3_ServoTRX(cmd2, 11, buf, 6);
   break;
  }
 }

 com3_Close();
 return 0;
}
Share:

2011/10/1

[教學] Bioloid AX-12馬達如何傳輸

如果想要控制Bioloid AX-12馬達

首先必須先了解Bioloid AX-12馬達是如何傳輸的

可以看AX-12的datasheet比較容易理解




正如上圖

首先會先傳兩個0XFF告訴馬達要開始了

然後第三個指令封包ID 是要確認傳送給此ID的馬達

接著為LENGTH 是告訴馬達開始接收連續幾個封包

INSTRUCTION是決定要讀出,寫入等

接下來的幾個是下指令的部分

首先是指令的Address 可以把他想成程式中的指標

然後接下來的是將Address指到的後面N個改為給的值

最後的CHECK SUM正如datasheet寫的 將前面所有的值相加做not











舉個例子應該會比較好懂些
假如我傳入這串指令
0xff, 0xff, 0x01, 0x07, 0x03, 0x1e, 0x00, 0x02, 0x00, 0x02, 0x00

他的意思是對ID:1的馬達座寫入
寫入的Address為0x1e 後面有4個值0x00, 0x02, 0x00, 0x02
這邊看對照表





前面兩個為馬達的角度

後面兩個為馬達的速度

再來看到詳細的說明


這邊提到0x1e與0x1f為馬達角度 最高0~300度
極限設定為 0x000~0x3ff

這邊提醒下 前面提到0x1e為L 低電位 0x1f為H 高電位
所以連續兩個封包0x00, 0x02 在機器中是讀為0x200的角度
所以轉到會150度的地方



然後這邊是說 馬達的轉速為0x000~0x3ff

和前面一樣0x20為L 低電位 0x21為H 高電位
所以連續兩個封包0x00, 0x02 在機器中是讀為0x200的速度

所以馬達會用最中等的速度轉動




最後一個CHECK SUM我沒有計算出來
不過算式是很簡單的
~(0x01 + 0x07 + 0x03 + 0x1e + 0x00 + 0x02 + 0x00 + 0x02)
Share:
技術提供:Blogger.

追蹤者