2016年2月29日 星期一

無人機電子變速器研究筆記



1.  Turnigy Multistar 10 Amp   >    http://www.hobbyking.com/hobbyking/store/__65151__Turnigy_Multistar_10A_V2_ESC_With_BLHeli_and_2A_LBEC_2_3S_V.html

$6.99

Specs:
Constant Current: 10AInput Voltage: 2-3 cell Lipoly 
BEC: Yes (linear) [Remove middle wire to dissable]
BEC Output: 5V/2APWM: 8 KHz
Max RPM: 240,000rpm for 2 Pole Brushless Motor
PCB Size: 22mm x 17mm
Discharge Plugs: Male 2mm Bullet Connector
Motor Plugs: Female 2mm Bullet Connector
Weight: 11.4g



2. 30A Simonk電變  250元
產品規格:
最大連續電流:11.1V/30A(需通風良好環境下)
電壓:2-3S(總W數為300W以下)
線性BEC:5V/3A
尺寸:35x23x8mm
兼容的信號頻率為30Hz - 550Hz
電源連接器:XT60型
電機插頭:3.5mm金插
重量:30g


sudo ./servod
Board revision:                  2
Using hardware:                PWM
Using DMA channel:              14
Idle timeout:             Disabled
Number of servos:                4
Servo cycle time:            20000us
Pulse increment step size:      10us
Minimum width value:            50 (500us)
Maximum width value:           250 (2500us)
Output levels:              Normal

Using P1 pins:               7,16,18,22
Using P5 pins:

Servo mapping:
     0 on P1-7           GPIO-4
     1 on P1-16          GPIO-23
     2 on P1-18          GPIO-24
     3 on P1-22          GPIO-25

Options:
--pcm tells servod to use PCM rather than PWM hardware
to implement delays
--idle-timeout=Nms tells servod to stop sending servo pulses for a
given output N milliseconds after the last update
--cycle-time=Nus Control pulse cycle time in microseconds, default
20000us
--step-size=Nus Pulse width increment step size in microseconds,
default 10us
--min={N|Nus|N%} specifies the minimum allowed pulse width, default
50 steps or 500us
--max={N|Nus|N%} specifies the maximum allowed pulse width, default
250 steps or 2500us
--invert Inverts outputs
--dma-chan=N tells servod which dma channel to use, default 14
--p1pins=<list> tells servod which pins on the P1 header to use
--p5pins=<list> tells servod which pins on the P5 header to use

min and max values can be specified in units of steps, in microseconds,
or as a percentage of the cycle time. So, for example, if cycle time is
20000us and step size is 10us then the following are equivalent:

--min=50 --min=500us --min=2.5%



echo 0=150 > /dev/servoblaster # Specify as a number of steps
echo 0=50% > /dev/servoblaster # Specify as a percentage
echo 0=1500us > /dev/servoblaster # Specify as microseconds
echo P1-7=150 > /dev/servoblaster # Using P1 pin number rather
echo P1-7=50% > /dev/servoblaster # ... than servo number
echo P1-7=1500us > /dev/servoblaster
定義在  servo.c

#define DEFAULT_CYCLE_TIME_US   20000
#define DEFAULT_STEP_TIME_US    10
#define DEFAULT_SERVO_MIN_US    500
#define DEFAULT_SERVO_MAX_US    2500

Servo cycle time:            20000us
Pulse increment step size:      10us
Minimum width value:            50 (500us)
Maximum width value:           250 (2500us)


電子變速器的週期為490 週期....

遙控器的油門 :  min :1100 ~ max : 1900  us.....


頭朝前面.....   左手邊為 1,  右手邊為2 ....  右後為 3.... 左後為 4....




依序接上 CC3D 的輸出....從右邊裝到左邊......從這個圖來看...CC3D 可以輸出到六軸....



遙控器的最大油門  1900 us.....最小油門  1100us....


然後我用 RPI  的PWM 來設定...發覺把 週期設成490.....  duty cycle 設成大於 50% ...

螺旋槳就開始啟動了....


順時針轉  接 正槳

逆時針轉  接 負槳





A quadcopter controller on a Raspberry PI


The only external devices needed are a MPU6050 for attitude measurment and a Wifi dongle. The quadcopter is remotely controlled via wifi and an Android App


The Raspberry PI hosts:
  • PID controller
  • ESC signal generator (ServoBlaster)
  • UDP server to get command from an android device
  • Communication with the MPU6050 through I2C.
The repository has several folders, that I initially made to code and test the different functions of the controller. The entire controller is in the PILOT folder.
Folders :
  • AND2RPI : a first version of socket programming for communication with a remote control over network
  • MODELS : some C programs that simulate the dyanmics of Quadcopter
  • MPU6050s : Richard Ghirst's MPU6050 tools with wrappers in order to simplify its use
  • PILOT : the complete controller currently under development
  • SERVOS : a cpp class used to write the ESC comands into /dev/servoblaster
This project is greatly inspired and using source code from :

Hardware

This projects includes :
  • 4 brushless motors (TURNIGY 2204-14T 19g Outrunner)
  • 4 Electronic Speed Controllers (Turnigy Multistar 10 Amp)
  • 1 LiPo 3s 3700 mAh battery
  • 1 sparkfun MPU6050 breakout board
  • 1 QuadCopter frame
  • 1 Android device for remote
Wiring (接線)
MPU6050 : -VDD -> 3.3V 
                   -GND -> GND 
                   -SDA -> SDA 
                   -SCL -> SCL 
                    -VIO -> 3.3V
ESCs: 
                   -GND -> GND 
                   -Signal Servo 0 -> pin 4 
                   -Signal Servo 1 -> pin 23 
                   -Signal Servo 2 -> pin 24 
                   -Signal Servo 3 -> pin 25
===================================================================

MPU6050s/

mpu6050_dmp.cpp contains routine to set-up, initialize and obtain Yaw, Pitch,
Raw angles from an MPU6050.

setup()
MPU_init()
MPU_setup()        (combination of both former ones)
MPU_getYPR(ypr[3]) (returns Y P R angles ina table)


SERVOS:

https://github.com/richardghirst/PiBits/tree/master/ServoBlaster


REMOTE_APP_ANDROID:

android source code

PILOT :  所有的code 都整合在這邊.....

===========================================================
當出現下面的error 的時候....
‘Sleep’ was not declared in this scope

只要include 這個檔頭就可以了
#include <unistd.h>


桔色 才是控制她的訊號
棕色GND
紅色是電變可供電給飛控的5V



Reference : https://github.com/vjaunet/QUADCOPTER?files=1

2016年2月26日 星期五



讀取 GY-80 模組:加速度計(ADXL345) 陀螺儀(L3G4200) 電子羅盤(HMC5883) 氣壓計(BMP085)





加速度計 ADXL345
陀螺儀 L3G4200
電子羅盤 HMC5883
氣壓計 BMP085

它有一堆接腳, 但我只會用四根, 也就是 i2c 的界面, 剩下是狀態腳和中斷腳
我這裡一律都用 polling mode, 目前我的應用還不需要中斷
這裡將依序紀錄各感測器的操作方法
i2c 界面將不做介紹, 這個資料到處都有, 不再重複, 文末會附上源碼供參考 
所有的 i2c 通信都是 stop 後再 start, 沒有做 re-start (或稱 no-stop)

加速度計 ADXL345
這貨的 i2c 位址是 0x53, 向左 shift 一位後加上 r/w bit 就可丟上 bus
它有多種量測模式, 這顆和別家的有點不同
別家的我看過的多是固定資料寬度, 透過暫存器切範圍
例如 10-bit 時, ±2g 範圍就是把 ±2g 切割成 10-bit
量測結果每多 1 就是多了 2g / 1024 = 0.0019g
而 ±4g 範圍就是把 ±4g 切割成 10-bit, 以此類推
這顆 ADXL345 可以進這種模式, 但也可以變成固定每個 bit 的 g 值增加量
也就是每多 1 就是多 4mg, 設定範圍越大值就越大, 資料寬度就越寬
最寬可以到 13-bit, 這樣比較好, 反正就設最大範圍, 資料收下就當 16-bit 整數算 
我們就不需要去管現在到底要除多少, 只要把它都乘 4mg 就對了
初始化流程丟在這函數裡

void adxl345_init(void){ 
  i2c_set_reg(ADXL345_SLA, 0x2D, 0x00); // normal mode, standby 
  i2c_set_reg(ADXL345_SLA, 0x31, 0x0B); // full resolution, +/- 16G 
  i2c_set_reg(ADXL345_SLA, 0x38, 0x00); // bypass mode 
  i2c_set_reg(ADXL345_SLA, 0x2C, 0x0A); // 100Hz 
  i2c_set_reg(ADXL345_SLA, 0x2D, 0x08); // start measure 
}

當裝置平躺在桌上, 會量得向下的 1g 加速度
Z = 257, 257 * 4mg = 1028mg = 1.028g
而 X, Y 則接近 0
當感測器呈現自由落體時則是 X, Y, Z 都會接近 0
當感測器固定的板子被觸碰時則會在該軸上產生一個小的加速度
這些在 datasheet 裡都有寫, 主要用於特殊應用 


老外的作法....參考網站2

How to get accelerometer data from the GY80 IMU

There are many people have been writing Arduino codes for this IMU, and there are even libraries available for these sensors. You can find the accelerometer ADXL345 library here. This is an example code how to use the ADXL345 library. It takes sensor measurements, calculate a human friendly value (in this case roll and pitch values) and output them to serial port.
[sourcecode language=”cpp”]
#include “Wire.h”
#include “ADXL345.h”
const float alpha = 0.5;
double fXg = 0;
double fYg = 0;
double fZg = 0;
ADXL345 acc;
void setup()
{
acc.begin();
Serial.begin(9600);
delay(100);
}
void loop()
{
double pitch, roll, Xg, Yg, Zg;
acc.read(&Xg, &Yg, &Zg);
//Low Pass Filter to smooth out data
fXg = Xg * alpha + (fXg * (1.0 – alpha));
fYg = Yg * alpha + (fYg * (1.0 – alpha));
fZg = Zg * alpha + (fZg * (1.0 – alpha));
//Roll and Pitch Equations
roll = (atan2(-fYg, fZg)*180.0)/M_PI;
pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg))*180.0)/M_PI;
Serial.print(pitch);
Serial.print(” “);
Serial.println(roll);
delay(50);
}
甚麼是Roll 和 Pitch 呢?

請參考下面的網址   http://howthingsfly.si.edu/flight-dynamics/roll-pitch-and-yaw




陀螺儀 L3G4200
這貨的 i2c 位址是 0x69, 向左 shift 一位後加上 r/w bit 就可丟上 bus 
官方說明文件 :

Technical article TA0343 
Everything about STMicroelectronics’ 3-axis digital MEMS gyroscopes

它的初始化流程很少, 只要兩行

void l3g4200_init(void){
  // 200Hz, Cutoff 12.5, enable 3 axis, and start 
  i2c_set_reg(L3G4200_SLA, 0x20, 0x4F);
  // block data update, 250dps  
  i2c_set_reg(L3G4200_SLA, 0x23, 0x80);
}

設定資料輸出速度, 然後啟動, 就這樣
第二行是設定只有讀完 LSB 和 MSB 才更新資料
避免分段讀取 16-bit 整數時讀到一半被更新導致資料錯亂
這顆的 datasheet 上寫了一堆功能, 可是有些好像不能用...
我的程式裡有留註解, 如果把 FIFO 打開, 資料還是會進去沒錯
但是會有一些奇怪的資料被塞進去, 看起來像是轉換出錯的
一開始以為是我系統電不穩, 電不穩會直接影響轉換結果 
不過 google 一下發現這個問題老外的論壇也有提到
所以最後就是不要用 FIFO, 改成直接輸出, 輸出前先讀狀態暫存器
自己親自確認當前資料是否有效, 有效才讀

陀螺儀的資料是角速度 (Angular Velocity)
datasheet 看了老半天沒發現到底怎麼轉換單位
它只說有三種範圍, 250 / 500 / 2000 dps, 但沒說資料寬度
(16-bit 是資料格式, 不是最大範圍) 
後來從老外的範例碼抽出, 每個 bit 的精度如下:
250dps : 0.00875
500dps : 0.0175
2000dps : 0.07

假設讀出值為 200, 範圍設 250dps, 那麼當前角速度就是 200 * 0.00875 = 1.75dps
dps = degree per second
degree 即是度數, 360 度 = 一圈那個, 不是數學常用的 radian (弧度)
如果需要三角函數計算會需要轉換一下
角速度要轉成方向需要乘上時間, d = V * t, d:距離 V:速度 t:時間, 簡單的國中數學
時間以感測器設 100 Hz 來說, 就是乘上 0.01 秒就可以獲得轉動量, 也就是轉了幾度
不過由於上面寫的, 有值可讀不代表值正確, 而等確認值後就不一定是 100 Hz 了
所以比較正確的算法應是量測時間後乘上去
量測時間可以設定 AVR 上的硬體 timer 來計算, 目前我沒這麼做, 只是概略的乘一個固定值
所以只要轉動太快就會失去方向, 這是執行結果:


顯示當前 X, Y, Z 軸所轉到的角度, 0-359 度
這貨是需要校正的, 需設定一個 0 值
類比轉數位難免會有雜訊, 就算都完全不動, 它仍然會量測到不規則漂移的極小值
廠商建議把這些值濾掉, 作法就是讓裝置不動, 然後讀取數十個樣本求平均
接著之後所有從感測器讀到的數都和這平均值比較, 低於平均的就丟棄, 當作裝置沒有動 

由於陀螺儀不受磁場影響, 對於飛行設備或船來說是最理想的指示裝備
不過目前我還不需要它, 所以只是簡單讀取計算後丟出
如果要正確知道方位最好加上時間量測, 老外的範例碼幾乎都有做 
一個老外的範例
Parallax Gyroscope Module 3-Axis L3G4200D sample code 




電子羅盤 HMC5883
這貨的 i2c 位址是 0x1E, 向左 shift 一位後加上 r/w bit 就可丟上 bus 
初始化流程也是少少的, 只要兩行

void hmc5883_init(void){ 
  i2c_set_reg(HMC5883_SLA, 0, 0x60); // 8 sample average 
  i2c_set_reg(HMC5883_SLA, 1, 0x20); // +/-1.3 Ga 


設定每次量測都是量 8 個樣本做平均才輸出
量測範圍為 ±1.3Ga (高斯, 磁力單位)
如果你和我一樣只是想知道方位, 那麼如何轉換成磁力值就不是那麼重要了
我的程式裡並沒有求磁力值, 若有需要可以查 datasheet
裡面有寫當範圍多少時對應的每個 bit 是幾個微高斯 (0.001Ga)
磁力感應器比較麻煩的是它一定要校正, 因為電能產生磁
而電路板上尤其電源部份一定會有磁力, 也就是有電感的地方
如果有外殼還會再受到影響, 所以組裝成系統後一定要校正
否則板上的磁場會和地球磁場混在一起, 難以區別方向
量測出的磁力值意義是這樣的 :
如下圖, 中間那顆球代表地球

隨便塗一下, 不要太計較XD
地磁會讓鐵分子呈南北向排列, 我們可以想像好像是由北流向南
這說法並不正確, 不過對我來說這樣比較容易想像, 尤其當考慮正負時
當感測器的 Y 軸指向磁北時, 可以量測到最大的正磁力值, 此時 X 軸的值為 0
如果把 X 軸指向磁北, 則 X 軸可以量測到最大的正磁力值, 此時 Y 軸的值為 0
如果把 X 軸背對磁北, 則 X 軸可以量測到最小的負磁力值, 此時 Y 軸的值為 0 
如果我們把 X, Y 的值全丟出來畫成圖, 它會長得像這樣 : 

就是一個圓
接著我們如果想知道方位, 就用國中數學算一下

這應該不用說明了吧XD
X^2 + Y^2 開根號就取得邊長, 然後用反餘弦函數 acos(y / L) 求得弧度
然後再把弧度換成角度就完成了
以往國中數學常常把 X 軸那裡當 0 度, 這裡要改一下
因為 Y 軸向北, 所以拿 Y 軸去求 acos
我們只是要知道 X, Y 的 "量", 並不需要知道它到底是幾高斯
所以直接把感測器出來的數字丟進去即可, 就不需要先算高斯值

以上是考慮理想狀態, 可惜的是如果加上電源磁力, 事情就不會那麼美好了
如果我們把 XY, YZ, ZX 的值全丟出來畫成圖, 它會像這樣

它還是圓沒錯, 但是不會在正中間
如果我們把上面的國中數學丟進去算, 那結果就是亂七八糟
以上圖藍色圈為例, 它將永遠不會有向南的角度值出現
因此我們會需要校正, 把他們都拉回中間, 要變成像這樣 :

這樣才有辦法知道方位
校正的方法就是找出每個軸的最大最小值, 然後求出中點值
每次讀取感測器值後都減去中點值, 它就會在中間了
校正時裝置要水平轉一圈, 垂直轉一圈, 以利找出最大最小值
校正的地點避免在室內, 以免受到鐵的家具影響

另外, 這是 X, Y 平面, 如果總是把三軸的值都丟出來
會發現 Z 方向還會有一個磁場, 由上往地心, 這個磁場我不知道怎麼解釋XD
如果有需要讓裝置可以站立著量測方向, 這個磁場要注意, 不要用它去計算方向
這需搭配加速度計來協同計算, 這裡我就沒做了 



-259 那是 Z 軸的值, 純參考用

校正畫面





氣壓計 BMP085
這貨的 i2c 位址是 0x77, 向左 shift 一位後加上 r/w bit 就可丟上 bus  
它不用初始化設定, 要量測時下命令即可
第一次量測前需從感測器讀出校正值, 它是一堆係數
這是工廠出廠時放進去的, 然後依照官方文件用一堆公式算一算就有了
各種感測器的值是否正確幾乎都和電壓以及溫度有關
有的感測器會把溫度補償自己做掉, 有的則要用戶自己算, 這顆就是屬於要自己算的
為什麼要這樣算就是他們的商業機密, 通常和他們的量測材料有關
我們搞系統所能做的就只有照著抄, 沒別的了
程式碼中所有 bmp085_ 開頭的函數自己翻一翻, 蠻多的, 所以就不貼出來了
算出來的單位是帕 (Pa), 氣象常用百帕 (hPa) 做單位, 也就是 1 hPa = 100 Pa
當高度每增加 8.43 公尺, 氣壓就會少 1 hPa, 我們可以用這來計算高度 
由於這感測器可以量測到 Pa, 所以我的程式是用 Pa 去算
氣壓少 1 Pa 就假設是增加 0.0843 公尺, 發現它還真可以量得準
坐電梯就可以看到高度逐漸變化, 相當有趣
不過氣壓會隨氣候改變, 所以如果要知道當前高度, 得先知道地面氣壓
所以我的程式有做一個功能, 就是按個按鈕就存下當前氣壓
然後開始移動, 我就可以知道高度增加了多少


另外還提供標準資料來計算, 通常海平面氣壓會以 1013 hPa 作為基準
按個按鈕會出現 Std 圖示表示以 1013 hPa 為基準計算


如果不想移動而想看值變化, 可以試試將裝置丟進透明夾鍊袋, 充滿氣後封起來
然後按壓袋子, 氣壓值應該要會上升




Reference : http://wukcsoft.blogspot.tw/2014/06/read-gy-80.html

Reference : http://blog.oscarliang.net/use-gy80-arduino-adxl345-accelerometer/

2016年2月14日 星期日

奶油蒼蠅2.0 的 研究 (1)


想要接觸四軸飛行器一陣了....可惜都還沒有行動....

剛好看到Ark Lab 的活動.... 就報名參加了....

買了一台奶油蒼蠅2.0 和一堂半天的課程.....


他用的晶片是  ATmega  328....相容於 arduino...

所以直接用Arduino 的IDE 來compile 和 upload....




插上usb 轉 TTL  (FTDI)  ...

然後看一下裝置管理員....


 在 連接阜那邊....如果有安裝好driver  就可以看到  USB-SERIAL CH340...

後面是他相對應的COM port number...以我的電腦來看是COM5....

如果沒有出現com port number.....需要安裝driver

driver 的 download path   :  http://www.driverscape.com/download/usb-serial-ch340

接下來就是連接  FDTI 和 電路板

兩邊都有寫  DTR.... 把線對上去就對了....  須注意...其實只需要5根線.... FDTI 的GND 不用連過去




接下來就是打開  Arduino  的 IDE ....



左上角的  分別為   compile (勾勾 符號) 和  upload ( -> 符號)

我直接用他的範例程式.....    

接下來設定  Serial port 和  Board....

Tool -> Serial Port -> COM5   (COM5 是要看你的裝置管理員)


Tool -> Board ->   XXX  ATmega 328..




接下來就是 compile 和  upload  了.....



接下來我們來看一下這個範例程式.....   

先來看setup ()  


void setup() {
  Serial.begin(9600);
  pinMode(3, OUTPUT);pinMode(9, OUTPUT);pinMode(10, OUTPUT);pinMode(11, OUTPUT);
  analogWrite(3, 0);analogWrite(9, 0);analogWrite(10, 0);analogWrite(11, 0);
  
}

這裡他會用到 serial .... 所以先設baud rate : 9600...

然後這個程式碼是要看多少的電壓對應馬達多少的轉速....

四顆馬達所對應到的gpio number 為 3,9,10,11....

所以要把它們設成  output mode.... 然後給他們initial value 0 

接下來看  loop ()

void loop() {

  if (stringComplete) {
     Serial.print(inputString); 
     inputString.toCharArray(text, 5);
    Serial.print("flag is:"); Serial.println(text[0]);
    Serial.println("you type:"); Serial.println(text[1]);
     Serial.println(text[2]);
     Serial.println(text[3]);
     //Serial.println(text[4]);
     
     if(text[0] == '!'){
      output = str2DEC();
       analogWrite(3, output);
       analogWrite(9, output);
       analogWrite(10, output);
       analogWrite(11, output);
       Serial.print("Output is:"); Serial.println(output);
     } 
      inputString = "";
      stringComplete = false;    
  }
}  

==============================

這裡他設定成   傳送的字串第一個字元必須是'!'
然後後面接3個數字..... 第五個必須是'\n' 換行符號....

所以他會check  if(text[0] == '!')
然後呼叫 str2DEC ...把字串轉成數字....然後寫到四個 馬達....你就可以看到馬達開始轉動

程式的大概就是這樣.....把他upload 到 ATmega 328....然後按下 arduino IDE的右上角的

Serial Monitor...



 然後就會看到類似終端機的畫面....



 先選下面的option  改成  NewLine....  他會幫你在後面多加一個 '\n' 的字元....

 你可以打一個數字試試看...例如   !020

然後你就會看到四個馬達開始轉了..... 轉數最大為  !255

這個例子只是示範馬達轉速...

最後要燒錄的code為  MultiWii_x4_mpu6050_last_bluetooth

打開裡面點選   MultiWii_x4_mpu6050_last_bluetooth.ino

就會打開整個project...然後把它upload 進去...就可以準備用手機來控制它了....




 Reference :   http://ark-lab.blogspot.tw/