顯示具有 Servo 標籤的文章。 顯示所有文章
顯示具有 Servo 標籤的文章。 顯示所有文章

2016年8月6日 星期六

四驅車GP晶片計畫

自從去年發現租屋處附近開了一家四驅車店家之後,就又重新燃燒起熱血
台灣不流行的期間基本上幾乎完全沒有消息,也沒有軌道可玩(日本好一點四驅車一直都存在,但也是沉寂多年官方沒有辦全國性的比賽)

回鍋後發現現在的玩家有很大的比例跟我一樣是二十多到三十多歲的大人,小時候有玩過,長大後又跳進來玩
可能因此導致現在軌道跟十多年前相比比較偏向技術軌,多了很多難度,所以不是單純比高速,而是變成在不飛車的前提下盡快跑完全程

之前看了很多四驅車相關的網站、論壇、玩家的部落格
基本上是都是以田宮 or 半田宮 的規則在玩,使用固定的機制去應付像是跳台或交換到這種難關
例如跳台落地為了穩定度,改成避震車或使用金球、吊鐘,為了過彎加裝單向輪/彈簧前後翼等...
為了因應不同場地而做調整,須累積大量的經驗,熟悉各種零件的特性,以整體賽道所有難關的"最大公約數" 的方向去做調整

在這個過程中,不斷的去發揮創意改裝與測試,真的有很多樂趣,這也是四驅車吸引人的地方

不過玩了一陣子後,就一直在想以這種玩法,就算玩到最極限,也是要配合賽道在各種方面(速度、重量、改裝方式等...)做取捨,所以漸漸地有了一個想法:
何不結合單晶片,讓車子自行適應軌道後做調整,這樣可以使用幾個基本車型(像是輕量高速型或是扭力型)來稱霸所有類型跑道

其實這就是卡通裡的GP 晶片啊!!!
在網路上有看到一些玩家使用單晶片改裝GP晶片,但是偏向語音或人工控制車子
https://www.youtube.com/watch?v=85913C7MjoQ
https://www.youtube.com/watch?v=C1x2Jdm_9eA


而我比較感興趣的部分則是讓車子自行學習,能夠自行適應各種跑到跑出不錯的成績

有了這個想法後,漸漸的想了一些可行的架構與做法,部分的功能也曾經做出可行的成品
(綠色部分是已經有做過有經驗的部分,藍色部分是已有方向正在研究中,紅色部分是還沒有想法或是需要重頭學習的領域)

目前先規劃一下架構,整理一下有能力與需要學習的部分,最後再全部整合起來




2014年9月18日 星期四

DIY 小小遙控車

好幾年前的作品,主要零件如下:
1. DIY BEC - 使用LM317,將模型電池降壓至6V(一般servo應該可以吃到6V)
2. 動力: DIY 改造的連續旋轉servo
3. 轉向: 小型9G servo
4. 一般遙控模型用接收





2014年4月23日 星期三

一般模型伺服機控制原理

普通類比伺服機
  1. 控制訊號使用pwm
    1. 周期約20ms
    2. 拉high時間控制伺服機轉動角度
      1. 1ms: 0度
      2. 1.5ms: 90度
      3. 2ms: 180度


將一般伺服機改為連續轉動的伺服機(continuous rotation servo)

一般伺服機的動作角度大約為0-180度

若要改造成可以連續轉動,主要修改的步驟如下


  1. 不要使用偵測擺臂角度的可變電阻
    1. 將可變電阻上面的線路切斷,並量測最大電阻(ex. 5K 歐姆)
    2. 將控制板上偵測可變電阻的線路用最大電阻的一半(ex. 2.5K 歐姆)分別接到Vin與Gnd(使控制板覺得擺臂角度一直維持在中立點)
  2. 改造機構使其連續旋轉
    1. 通常殼上或齒輪上會有限制最大轉動角度的機構(例如突出物),將其切除即可

由於將可變電阻改成固定電阻,所以控制板會覺得擺臂位置一直在九十度(中立點),
  • 若此時送給伺服機的訊號為
    • 90度,馬達不會旋轉
    • 小於90度,馬達往某一方向轉
    • 大於90度,馬達往另一方向轉
可以注意到,若送給伺服機的訊號角度與90度差越多,控制板會認為目前位置與目標位置差距越大,所以會讓馬達轉越快

伺服機內部構造/控制電路

拆了一個壞掉的伺服機

內部使用的控制晶片為YT5188,是控制伺服器專用的晶片,搭配少量外部原件即可控制馬達正反轉與速度與偵測擺臂位置

馬達經過減速齒輪控制擺臂,擺臂連接5K電阻使控制晶片可以偵測其位置

datasheet上建議使用推動馬達的電晶體建議為2SA695


ps.日本的電晶體的命名規則(JIS)
http://elect.taivs.tp.edu.tw/course/ch04_11.htm

2014年3月20日 星期四

Arduino 小技巧 - 修改servo library, 使其更新動作速度更快


http://www.diy-robots.com/?p=1183

一般servo控制,都是20ms更新一次,每次拉高一段時間,拉高的時間範圍約為1000-2000us, 
1500us為中間點

可以修改Arduino servo library,使更新間隔降到2500us(2.5ms),對於需要快速控制的用途很有幫助

libraries\Servo\Servo.h
//#define REFRESH_INTERVAL    20000     // minumim time to refresh servos in microseconds 
#define REFRESH_INTERVAL 2500

2014年2月25日 星期二

MTADRL293D 馬達(電機)驅動模組 - 簡介/控制直流馬達

這個模組買來沒有電路圖,也沒有說明,版子又做成Arduino shield的樣式,完全不知道腳位對應

google只找到一些購物網站,只有普通簡介,完全沒有講細節

後來終於在這個網站上找到電路圖,比對了servo控制的部分相同,應該是同一塊電路板

##注意 M3/M4電路圖與控制板是相反的


上面主要有兩種chip:
  1. 74HCT595N *1
    1. 計數器轉換暫存器
    2. 相關連結
  2. L293D *2
    1. 每棵可控制兩顆直流馬達或是一顆四線式步進馬達
    2. 相關連結

MTADRL293D主要功能:
  1. RESET
    1. 與Arduino 的RESET接在一起
  2. POWER JUMP
    1. 接上代表MTADRL293D的電池同時供電給arduino
      •   電池正極(V+)接到Arduino VIN(Arduino內部可以自己轉成5V VCC)
  3. 兩路servo控制(只是幫忙轉換腳位,實際上還是使用Arduino 輸出的PWM控制)
    • servo 1:直接接到Arduino pin 10
    • servo 2:直接接到Arduino pin 9
    • servo VCC: Arduino 5V <==不是直接接到MTADRL293D的BATT,或是由他降壓
  4. 四路馬達控制:
    1. M1 
      • EN: (PWM2A) 接到Arduino pin 11
      • 電源: V+
    2. M2 
      • EN: (PWM2B) 接到Arduino pin 3
      • 電源: V+
    3. M4
      • EN: (PWM0B) 接到Arduino pin 5
      • 電源: V+
    4. M3
      • EN: (PWM0A) 接到Arduino pin 6
      • 電源: V+
  5. 兩路四線式步進馬達控制
    1. 待續...

可使用我寫的Arduino Library控制此模組:

控制範例:

#include "MTADRL293D.h"

MTADRL293D l293d;

void setup(){

  Serial.begin(115200);
  while (!Serial){
    ;
  }
  
  delay(5000);
  
  Serial.println("=== loop() ===");

  l293d.enableDbg(true);
  l293d.begin();

  l293d.setMotorDir(MTADRL293D_M1, MTADRL293D_DIR_POS);
  l293d.setMotorDir(MTADRL293D_M2, MTADRL293D_DIR_POS);
  l293d.setMotorDir(MTADRL293D_M3, MTADRL293D_DIR_POS);
  l293d.setMotorDir(MTADRL293D_M4, MTADRL293D_DIR_POS);

  l293d.setMinMotorSpeed(MTADRL293D_M1, 100);
  l293d.setMinMotorSpeed(MTADRL293D_M2, 100);
  l293d.setMinMotorSpeed(MTADRL293D_M3, 100);
  l293d.setMinMotorSpeed(MTADRL293D_M4, 100);

  l293d.setMotorSpeed(MTADRL293D_M1, 0);
  l293d.setMotorSpeed(MTADRL293D_M2, 0);
  l293d.setMotorSpeed(MTADRL293D_M3, 0);
  l293d.setMotorSpeed(MTADRL293D_M4, 0);
}


void loop(){
  Serial.println("=== loop() ===");

  Serial.println("=== m1 pos 100");
  l293d.setMotorDir(MTADRL293D_M1, MTADRL293D_DIR_POS);
  l293d.setMotorSpeed(MTADRL293D_M1, 100);
  delay(3000);

  Serial.println("=== m1 0");
  l293d.setMotorSpeed(MTADRL293D_M1, 0);
  delay(1000);

  Serial.println("=== m1 neg 100");
  l293d.setMotorDir(MTADRL293D_M1, MTADRL293D_DIR_NEG);
  l293d.setMotorSpeed(MTADRL293D_M1, 100);
  delay(3000);

  Serial.println("=== m1 0");
  l293d.setMotorSpeed(MTADRL293D_M1, 0);
  delay(1000);

  Serial.println("=== m3 pos 100");
  l293d.setMotorDir(MTADRL293D_M3, MTADRL293D_DIR_POS);
  l293d.setMotorSpeed(MTADRL293D_M3, 100);
  delay(3000);

  Serial.println("=== m3 0");
  l293d.setMotorSpeed(MTADRL293D_M3, 0);
  delay(1000);

  Serial.println("=== m3 neg 100");
  l293d.setMotorDir(MTADRL293D_M3, MTADRL293D_DIR_NEG);
  l293d.setMotorSpeed(MTADRL293D_M3, 100);
  delay(3000);

  Serial.println("=== m3 0");
  l293d.setMotorSpeed(MTADRL293D_M3, 0);
  delay(1000);

}