2016年12月12日 星期一

[Ardunio]MPU9250


手邊的MPU9255是九加一軸感測器
基本上就是MPU9250加上溫度,
MPU9250是三軸加速度計加上三軸陀螺儀加上三軸羅盤
挺威的,

今天測試拿掉範例的中斷,直接存取Row data
看起來應該正常,但因為時間趕,得多測幾次看看有沒有bug。

MPU9250規格書
https://www.invensense.com/products/motion-tracking/9-axis/mpu-9250/


2016年12月3日 星期六

[Ardunoi]Wire.h



Wire Library

This library allows you to communicate with I2C / TWI devices. On the Arduino boards with the R3 layout (1.0 pinout), the SDA (data line) and SCL (clock line) are on the pin headers close to the AREF pin. The Arduino Due has two I2C / TWI interfaces SDA1 and SCL1 are near to the AREF pin and the additional one is on pins 20 and 21.
As a reference the table below shows where TWI pins are located on various Arduino boards.
BoardI2C / TWI pins
Uno, EthernetA4 (SDA), A5 (SCL)
Mega256020 (SDA), 21 (SCL)
Leonardo2 (SDA), 3 (SCL)
Due20 (SDA), 21 (SCL), SDA1SCL1
As of Arduino 1.0, the library inherits from the Stream functions, making it consistent with other read/write libraries. Because of this, send() and receive() have been replaced with read() and write().

2016年11月30日 星期三

[無人機]姿態擷取問題



如官網上說的,擷取raw值很容易,剩下的很麻煩,
其實,歸功於許多開源的前輩,在ardunio上已經很容易取得raw值了,

至於如何估算姿態?
用MPU6050有個好處,裡面的DMP模組已經可以提供pitch,row,yaw角度了,
如果單純只做角度估測,DMP就夠用。

But....
四軸的控制,我們還有許多工作得處理,像是再加上其他的感測器如超音波,
就會造成時序的衝突,導致DMP或者超音波其中一個不work,

所以,拿掉DMP吧,如果你未來的內容不只是角度估測而已的話。

好家在,之前碩論做過,不過之前只用卡曼估算Pitch、Roll兩軸,很快就可以解決,
但是如果想加上Yaw軸,網路上多用四元數來解決,下面就紀錄一下這過程。

拿到MPU6050,有幾項工作得做,

一、確認raw值的scale範圍
在下面網頁有說明
http://www.i2cdevlib.com/forums/topic/4-understanding-raw-values-of-accelerometer-and-gyrometer/

在MPU6050.cpp初始化函示有提到,預設為+/-2g,+/-250degree/s
/** Power on and prepare for general usage.
 * This will activate the device and take it out of sleep mode (which must be done
 * after start-up). This function also sets both the accelerometer and the gyroscope
 * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
 * the clock source to use the X Gyro for reference, which is slightly better than
 * the default internal clock source.
 */
void MPU6050::initialize() {
    setClockSource(MPU6050_CLOCK_PLL_XGYRO);
    setFullScaleGyroRange(MPU6050_GYRO_FS_250);
    setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
    setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
}

如果有必要修改,下面是修改方式
mpu.setFullScaleGyroRange(0);
//0 = +/- 250 degrees/sec | 1 = +/- 500 degrees/sec | 2 = +/- 1000 degrees/sec | 3 =  +/- 2000 degrees/sec
mpu.setFullScaleAccelRange(0);
 //0 = +/- 2g | 1 = +/- 4g | 2 = +/- 8g | 3 =  +/- 16g 


二、取得重力與角速度
在這個函式拿到xyz軸的加速度計重力值以及陀螺儀的角速度
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

三、四元數是啥?

幾個背景知識參考
四元數四元數與旋轉
開源飛行器crazepony的軟體姿態解法,他的參考來源
對岸的參考資料有提到Z方向的需求要看應用
關於六軸與九軸的比較

一個簡單的範例,這個範例簡單好用,不過只有在運動時穩定,靜止時十分糟糕,
應該是沒有濾波的關係。


But....我發現我手邊有個九軸感測器,對於Yaw旋轉的效果會比六軸好

網路資源,網路資源二資源三感覺資源二可以試試看。
如果還是會造成時序衝突,那就用之前碩論的卡曼,可能還比較好一點。









2016年11月28日 星期一

[Ardunio]陸製Ardunio Mega 2560驅動



真的是強國人....

https://www.youtube.com/watch?v=FhmG5J-AHrg

http://wch.cn/download/CH341SER_ZIP.html

[無人機]關於Schedule-MPU6050 DMP Mode的中斷問題


加入超音波後,DMP常常會當掉,或者OVERFLOW

研究了超音波的讀取方式使用pulsein()
詳見官網文件如下連結
https://www.arduino.cc/en/Reference/PulseIn
發現這個會依照echo長度而變動的值,也就是echo高電位多久,就會被hold在這裡多久,


另外
下面連結
http://www.i2cdevlib.com/forums/topic/27-fifo-overflow/
有提到修改I2C的傳輸頻率,以及DMP資料的輸出速度


目前將I2C改成100KHz
DMP輸出改50Hz

發現沒有用,超音波很容易就會因為距離太遠而停止

2016年11月25日 星期五

[無人機]Ardunio Shield 規劃與參考



http://forum.arduino.cc/index.php?topic=7013.0
https://aaroneiche.com/2010/06/24/a-beginners-guide-to-making-an-arduino-shield-pcb/


The SparkFun Eagle Library
http://www.opencircuits.com/SFE_Footprint_Library_Eagle


這個擴展版的接腳比較符合我想用的,因為目前UNO上面還是有接腳未用完,
如果就直接蓋住,實在浪費
http://matthewcmcmillan.blogspot.tw/2014/09/seeed-can-bus-shield-with-arduino-mega.html

比較麻煩的是這種連接器要去哪買?
https://www.adafruit.com/products/192


另外,Ardunio Mega的接腳較多,後面有一部份可以考慮做成可折斷的版本,
這樣就可以通用於UNO以及MEGA
http://tmuel1123.blogspot.tw/2013/12/the-idea-design-mistake.html


目前預計要上shield的幾個模組有
1.GY521
2.超音波
3.BT,要加上降壓與分壓電阻
4.四組ESC
5.一組5V轉3v3的buffer, 74lvc125
6.Mega的ICSP要接出來,Reset要按的到

2016年11月24日 星期四

[無人機]出來跑還是要還的


今天測試懸停的時候,用手拿著四軸,慢慢開油門,
轉到高速時,兩片槳片噴飛,
敲到我小指,立馬噴血,不過槳片沒斷,倒是槳夾只找回來一個,
晚點去模型店找找,否則就只能上網訂了。




2016年11月23日 星期三

[無人機]第一次懸停





[無人機]X Type



http://technicaladventure.blogspot.tw/2012/09/quadcopter-stabilization-control-system.html
https://rcexplorer.se/educational/2011/02/kk-quad-x-setup-guide/
https://www.quora.com/Why-is-x-configuration-preferred-over-+-config-of-quadcopter

http://www.crazepony.com/book/wiki/algorithm-pid.html
http://blog.csdn.net/nemol1990/article/details/45131603

[Arduino]HC-05 BT Module(二)


這個模組雜訊的問題困擾了我一天

起因還是因為想整理上方一堆的線,所以將許多線改成單心線
結果雜訊變得十分大,
改回多心線後有好轉,但是依然起起伏伏,

目前
BT模組的TX接10K電阻到ardunio的接收
BT模組的RX接1K2K分壓電阻到Ardunio的傳送
雜訊有比較少,溝通也較穩定了。



2016年11月20日 星期日

[Arduino]HC-05 BT Module




http://www.martyncurrey.com/arduino-with-hc-05-bluetooth-module-at-mode/
http://www.martyncurrey.com/using-an-arduino-mega-with-a-hc-05-zs-040-at-mode/
http://gsyan888.blogspot.tw/2014/03/arduino-hc-06-at-command.html

http://swf.com.tw/?p=693
http://swf.com.tw/?p=705
http://swf.com.tw/?p=712


最後接線起來能夠正確的資料是參考
TX線的接法
http://www.martyncurrey.com/arduino-with-hc-05-bluetooth-module-at-mode/
RX線的接法
http://swf.com.tw/?p=705

這真是詭異...= =

Arduino裡面的設定要記得
// 定義連接藍牙模組的序列埠
SoftwareSerial BT(8, 7); // 接收腳, 傳送腳要設定


關於藍芽
AT模式的命令要參考HC-05,不能參考HC-06
藍芽連接後,出現COM27以及COM28,必須使用COM27,鮑率9600。



2016年11月18日 星期五

[Arduino]Sharp 2Y0A21


雖然可以用紅外線,但是紅外線在機體靜止於地面時,
得到的數據是離地50cm左右的位置,
會發生這樣的原因是紅外線偵測到的位置剛好是機體的陰影,
所以....排除使用紅外線吧...@@


Sharp IR Sensor

http://playground.arduino.cc/Main/SharpIR



以下資料來源為下面連結
http://communityofrobots.com/tutorial/kawal/how-use-sharp-ir-sensor-arduino


Components you'll need:

  • Arduino uno
  • Sharp GP2D12 or any other analog model like GP2D120
  • Half sized breadboard
This is actually explained here but for ease of users i am posting it separately.

Connections:

You can power the arduino through USB or 9V battery.
=========================================
int sensorpin = 0;                 // analog pin used to connect the sharp sensor
int val = 0;                 // variable to store the values from sensor(initially zero)

void setup()
{
  Serial.begin(9600);               // starts the serial monitor
}
 
void loop()
{
  val = analogRead(sensorpin);       // reads the value of the sharp sensor
  Serial.println(val);            // prints the value of the sensor to the serial monitor
  delay(100);                    // wait for this much time before printing next value
}

[Blogger]奇技淫巧


Blogger上使用數學符號
http://skypieah.blogspot.tw/2013/05/blogger.html
http://mathjaxtest.blogspot.tw/

線上轉換
http://www.codecogs.com/latex/eqneditor.php

Blogger插入程式片段和syntax highlight
http://skypieah.blogspot.tw/2014/01/code-block-on-blogger.html

2016年11月17日 星期四

[無人機]運動學方程式


以下方程式是下面論文的筆記
微型四旋翼直升機之模擬、設計與控制,龍華科大,廖啟賓


\(\Omega_{1}^{2}=\frac{1}{4b}\mathit{U}_{1}-\frac{1}{2bl}U_{3}-\frac{1}{4d}U_{4}\)
\(\Omega_{2}^{2}=\frac{1}{4b}\mathit{U}_{1}-\frac{1}{2bl}U_{2}+\frac{1}{4d}U_{4}\)
\(\Omega_{3}^{2}=\frac{1}{4b}\mathit{U}_{1}+\frac{1}{2bl}U_{3}-\frac{1}{4d}U_{4}\)
\(\Omega_{4}^{2}=\frac{1}{4b}\mathit{U}_{1}+\frac{1}{2bl}U_{2}+\frac{1}{4d}U_{4}\)

其中\(\mathit{U}_{1}\) ~ \(\mathit{U}_{4}\)分別代表了力或者力矩\((U\)),這個將會與馬達轉速\((\Omega)\)平方成正比,力矩種類如下

\(\mathit{U}_{1}\):垂直升力
\(\mathit{U}_{2}\):滾轉力矩
\(\mathit{U}_{3}\):俯仰力矩
\(\mathit{U}_{4}\):偏航力矩

\(\Omega_{1}\) ~ \(\Omega_{1}\)分別為前、右、後、左的馬達轉速
\(b\)為推力系數,\(d\)為推力系數,\(l\)為馬達中心到四旋翼中心距離[m],

四旋翼的直線加速度運動方程式如下

\(\ddot{X}=(sin\varphi sin\phi +cos\varphi sin\theta cos\phi )\frac{U_{1}}{m}\)
\(\ddot{Y}=(-cos\varphi sin\phi +sin\varphi sin\theta cos\phi )\frac{U_{1}}{m}\)
\(\ddot{Z}=-g+(cos\theta cos\phi  )\frac{U_{1}}{m}\)

\(\)
要再讀第六章 系統控制,可以求出U1~U4



直線運動方程式參考
http://ezphysics.nchu.edu.tw/ccp/kinematics/k1.htm
當加速度為定值時,運動方程式 可直接積分得到avst的關係式。
等加速度直線運動的公式:物體的初始位置x0、初速度v0,由t=0開始。
,末速度
t秒內的位移 
末速度的平方




綜合以上

因為我們會固定\(\theta\) 以及\(\phi \)為零,
所以把起飛的運動簡單想,Z軸加速度就可簡化如下
\(\ddot{Z}=-g+\frac{U_{1}}{m}\)

Z=1/2(a)t2






2016年11月16日 星期三

2016年11月14日 星期一

[無人機]組裝後輸出測試




[無人機]動力學



http://www.crazepony.com/book/about-algorithm.html
http://www.neovincent.com/?p=465
http://andrew.gibiansky.com/blog/physics/quadcopter-dynamics/


目前我的配置



3、10
9、11

2016年11月10日 星期四

[無人機]MPU6050控轉速




[Ardunio]Stray error


編譯Ardunio時候出現莫名其妙的錯誤如下
stray '\23' in program

搜尋一下是編碼的問題,如下頁面

http://askubuntu.com/questions/272741/how-to-fix-compilation-errors-that-mention-stray-342-and-stray-200

[Ardunio]GY-521六軸姿態


這顆六軸姿態很普及,Arduino對這顆已經有現成資源
可以看下面文章

http://dory168.blogspot.tw/p/gy-521sensormpu-6050dmp-ic.html

http://ming-shian.blogspot.tw/2014/05/arduino21mpu6050row-data.html

http://playground.arduino.cc/Main/MPU-6050

http://www.i2cdevlib.com/usage





2016年11月9日 星期三

[無人機]電調測試與自動油門行程偵測


這幾天測試了好盈Flyfun

根據使用手冊上的內容,將電機一上電要做的初始化寫在Arduino裡

一開始很不順利,一直無法正確抓到油門行程

後來測試出來將電調調回原廠設定的方式,

再將PWM經過LVC245調整電壓為3.3V

整個就回春了,下面是初始化的影片



Ardunio code
========================================================

int potpin=0;
int PWM_pin=10;//use timer1
int Pot_Value=0;
int Throttle_Min = 500;
int Throttle_Max = 900;
//

void setup() {
// put your setup code here, to run once:
int fff = 3;  // 可以是 1~5
TCCR1B = TCCR1B & 0xF8 | fff;//3設定PWM頻率為 490 Hz
pinMode(PWM_pin,OUTPUT);
Serial.begin(9600);

//  //編程模式
//  Serial.print("Set ESC: Max Throttle! \n");//
//  analogWrite(PWM_pin,Throttle_Max/4);//
//  delay(10000);

//  //初始化電變
  Serial.print("Set ESC: Max Throttle! \n");//
  analogWrite(PWM_pin,Throttle_Max/4);//
  delay(3000);

  Serial.print("Set ESC: Min Throttle! \n");//
  analogWrite(PWM_pin,Throttle_Min/4);//
  delay(2000);

  Serial.print("Set ESC OK \n");//
}

void loop() {
  // put your main code here, to run repeatedly:
  Pot_Value=analogRead(potpin);
  Serial.println(Pot_Value);//一邊將數值往序列埠顯示
  if(Pot_Value < Throttle_Max && Pot_Value > Throttle_Min)
  {
    analogWrite(PWM_pin,Pot_Value/4);//對Digital腳位寫入PWM
    delay(10);
  }
 
}

2016年11月8日 星期二

[無人機]測試用硬體


電機
新西達480S/950KV 無刷馬達
http://blueskymodel.com/product_info.php?products_id=2380

15級引擎馬力...高效率優質馬達!!!
輕質量高扭力大馬力的一顆優質馬達
全新改款設計…精選材料/精緻設計/精密加工/高品質/重量輕/高馬力/高推力/
適用保麗龍及巴爾沙木製大小機型相當於15級2行程引擎馬力
 3D機、滑翔機、特技機、像真機、適用 
高效能12槽14極外轉子無刷馬達高精度動平衡設計
◎最新高純度超薄0.2mm矽鋼片定子,低鐵損無磁殘留,有效提昇馬達效率降低馬達溫度
◎高精度防磁外轉子高轉速平衡低噪音
◎加強型耐衝擊低阻力日本高速培林
◎三個培林支撐軸心設計運轉精度更高
 480S /A2217/15級飛機用外轉子無刷馬達規格表

直徑                     
27.8mm
長度
34mm
重量
65g
軸心尺寸
4.00mm
每伏特轉速
950/1100/1250/1500/1750rpm/V
最佳效率值
85%
適用電池數
2~3cell Li-ion/Li-poly
最大持續電流 
20~28A 
最大瞬間電流
22~35A / 60sec
最佳效率電流
8~28A(>80%)
建議機體重量     

600~1000g
電調
好盈 飛騰系列 FlyFun-40A/2~6S/NO BEC 無刷電子調速器/電變
http://www.gejore.tw/shop/goods-5034.html


適用於
1. 400/450直升機3D。
2. 32級固定翼Sports。
3. 多軸飛行器。


FlyFun-40A和FlyFun-40A-OPTO的主要區別在於:前者有內置BEC而後者沒有。
產品編號分別為:80020620(FlyFun-40A) 和  80020622 (FlyFun-40A-OPTO)



產品規格: 
1、 輸出能力:持續電流40A,短時電流55A(不少於10秒)。
2、 電源輸入:2-6節鋰電池組或5—18節鎳氫/鎳鎘電池組。
3、 BEC輸出:
      ●FlyFun-40A: 3A (開關電源穩壓模式-switch mode)
      ●FlyFun-40A-OPTO:無
4、 油門信號頻率範圍(Refresh rate):50Hz—432Hz。
5、 最高轉速:2極馬達210000轉/分鐘,6極馬達70000轉/分鐘,12極馬達35000轉/分鐘。
6、 尺寸:
      ●FlyFun-40A: 60mm(長)*28mm(寬)*15mm(高)。
      ●FlyFun-40A-OPTO: 60mm(長)*28mm(寬)*12mm(高)。
7、 重量:
      ●FlyFun-40A: 38.8g(含散熱片)。
      ●FlyFun-40A-OPTO: 35.2g(含散熱片)。
8、 附件: 參數設定卡(可選配)。
 
產品功能:
1、 安全上電功能:接通電源時,無論油門搖桿處於任何位置均不會立即啟動電機,避免造成人身傷害。
2、 油門行程校調功能:適應不同遙控器油門行程的差別,提高油門響應的線性度。
3、 程序設定項目:
      ●剎車設定:無剎車/有剎車。
      ●電池類型:Li-xx(鋰電池)/ Ni-xx(鎳鎘或鎳氫)。
      ● 低壓保護模式:降低功率/關閉輸出。
      ●低壓保護閾值:低/中/高。
      ●啟動模式:普通/柔和/超柔和啟動。
      ●進角:低/中/高。
      ●恢復出廠默認值。
4、 全面的保護功能:
      ●欠壓保護:由用戶通過程序設定,當電池電壓低於保護閾值時,電調自動降低輸出功率。
      ●過壓保護:輸入電壓超過輸入允許範圍不予啟動,自動保護,同時發出急促的「嗶嗶」告警音。
      ●過熱保護:內置溫度檢測電路,電調溫度過高時自動降低輸出功率。
      ●遙控信號丟失保護:遙控信號丟失1秒後降低功率,再有2秒無遙控信號則關閉輸出。

工藝特點:1、 電源輸入端採用超低阻抗大容量電解電容,極大提高抗干擾能力。
2、 輸出MOSFET功率管配備獨立散熱片,有效降低器件溫升,提高系統大電流工作能力。
3、 單片機採用獨立穩壓芯片,避免BEC負載變化造成電源干擾,提高單片機工作穩定性。

2016年11月7日 星期一

[MultiWii]Source Page

https://code.google.com/archive/p/multiwii/

[MultiWii]參考文章



http://rcinterest.blogspot.tw/2013/10/multiwii.html

http://rcinterest.blogspot.tw/2013/10/multiwii_11.html

注意每個電變都內含 BEC (電池電壓轉換器,其實就是一個 5V 穩壓器),所以只能有一個電變是提供 5V 給接收跟 MWC 的,另外三個電變的紅線必須拆掉,免的四個 5V 輸出短接在一起。對了,在把這四個電變接上 MWC 之前,最好先一個個直接接在接收機上做油門校正,這樣四個電變的油門才會一致,油門校正的方法要看電變的說明,一般是把遙控器油門調到最高再接上電變電池,聽到嗶嗶聲後再把油門壓到最低,這樣電變就知道了油門的最大及最小值。

http://rcinterest.blogspot.tw/2013/10/multiwii_3701.html

[Arduino]PWM


TC0 - 8-bit Timer/Counter0 with PWM
TC1 - 16-bit Timer/Counter1 with PWM
TC2 - 8-bit Timer/Counter2 with PWM and Asynchronous Operation


Timer/Counter 0, 1 Prescalers
The 8-bit Timer/Counter0 (TC0) , 16-bit Timer/Counters 1 (TC1) share the same prescaler module, but the Timer/Counters can have different prescaler settings. The following description applies to: TC0 , TC1 .




以下內容來自這裡

大家都知道在 Arduino UNO 有六支 pin 可以使用 analogWrite( )做 PWM 輸出,
在板子上 pin 旁邊標示有 "~" 符號, analogWrite( ) 可以用來產生模擬電壓,
很多人一定很好奇那是怎麼做到的 ?

首先來看看 PWM 模擬電壓的原理, 這在官網上就有解說了:
     http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM
所謂的 PWM 全稱是 Pulse-Width Modulation (PWM), 其實這也沒啥學問,
就是對 GPIO 腳位不斷的切換 "有電" "沒電", 
每秒鐘循環幾次即為其 Frequency(頻率), 
每次"有電"時間佔一個循環的百分比稱為其佔空比(Duty cycle);
以下是官網上的模擬範例:
int pin = 13;
void setup() {
  pinMode(pin, OUTPUT);
}
void loop(){
  digitalWrite(pin, HIGH);
  delayMicroseconds(100); // Approximately 10% duty cycle @ 1KHz
  digitalWrite(pin, LOW);
  delayMicroseconds(1000 - 100);
}
這個範例中, 一個循環是 1000 us = 1ms, 所以一秒循環 1000次, 因此 Frequency 是 1 KHz,
每個循環中, 有電的比率是 100/1000 * 100% = 10%, 所以 duty cycle (佔空比)為 10%;
這樣就可以模擬出 5Volt x 10% = 0.5 Volt 的電壓!
    如果真的這樣做, 有好處也有壞處, 官網上已經說了:
好處是任一支 pin 都可這樣用, 包括 Pint 0 到 Pin 13, 以及 Pin A0 到 A5 共 20支 pin 都可以!
壞處卻更多, 首先就是頻率(Frequency)和佔空比(duty cycle)可能受中斷(Interrup)的影響變成不是很準確 !!
最大的壞處是, 在某支 pin 做 PWM 輸出期間都沒辦法做別的事情 !!

    既然說這只是示範可以這樣做, 在  Arduino 當然不可能是這麼做,
那 Arduino 是怎麼做的呢?

就是透過 Timer 計時器直接控制 pin 做 PWM 輸出, Arduino UNO 的 MCU 有三個 timer,
其中 timer0 控制 pin 5, pin 6; timer1 控制 pin 9, pin 10; timer 2 控制 pin 11, pin 3;
所以, 我們可以對這些 pin  analogWrite(pin, val); 輸出 0 到 255(2的8次方,8Bit) 的 val 值到 pin ;
如果輸出 val 是 0, 它會偷偷直接改用 digitalWrite(pin, 0); 輸出,
如果 val 是 255, 也是會偷偷直接改用 digitalWrite(pin, 1); 輸出!
如果 val 是 1 到 254, 則會下命令請 pin 腳對應的 timer 計時器(定時器)幫忙!!
How ?
首先要知道 timer 的基本知識:
(1)每個 timer 一定有個 counter, 例如 timer0 的TCNT0, timer1 的TCNT1, timer2 的TCNT2;
   該 counter 一定是每個 tick 會加 1, 每個 tick 通常是把 CPU 的 clock 拿來經過一個除頻電路,
   然後給 timer 使用; Arduino UNO 採用 AVR ATmega328 MCU, 且 clock Rate 是 16MHz,
   每個 timer 的除頻 Prescaler 是獨立設定的, 通常可以設 1, 2, 4, 8, 64, 256, or 1024 等,
   這必須看 MCU 的 datasheet.

(2)每個 timer 通常提供許多 mode 運作模式, 例如 counter 溢出(Overflow)或Rollover歸零時產生中斷,
   或 TCNT? 達到某個值時產生中斷等, Arduino ATmega328 的 timer 有 16種 mode, 許多 Mode 是與 PWM 有關;
   要設定 timer 的 Mode 可以透過修改 timer 的控制暫存器, 例如 TCCR?A, TCCR?B,    注意以 ATmega328 為例, TCCR?A 和 TCCR?B 要合起來用, 此處的 A, B 與 channel A, channel B 無關!!

(3)每個 timer 通常有比較暫存器(Compare Register), 當 TCNT? 值與該些比較暫存器相同時可以做某事,
   不一定是對 CPU 產生中斷! Arduino 每個 timer 有兩個比較暫存器, 分別命名 OCR?A 和 OCR?B,
  其中 ? 是 0, 1, 2 分別對應到 timer0, timer1, 和 timer2 這三個計時器.
你可以先偷看 analogWrite( ) 的程序碼:
    在你 Arduino IDE 下的 hardware\arduino\cores\arduino\wiring_analog.c
很簡單, 真正請 timer 幫忙只做三件事: a.找出對應的 port, b.設定控制暫存器, c.填入 analog的值到比較暫存器!
不過你會發現看不太懂, 因為還不知道硬體 timer 控制 PWM 運作方式與原理!
不想看 datasheet 可以參考這:
      http://letsmakerobots.com/conten ... mers-and-interrupts

    以Arduino UNO 的 timer1為例, 在 mode 5 (Fast PWM, 8 bit), 此時, TCNT1 從 0 數到 255, 然後又加 1 就變0, ...
通常從 255 (此 mode 的最大值)又加 1 變為 0 之時會產生 OVF 中斷(TIMSK1的TOIE1要 set), 不過這與 PWM 無關!
PWM 不是用 Interrupt  中斷請求做的, 不必麻煩 CPU, CPU 只要下命令給 timer, timer 就會照命令執行PWM工作 !!
    PWM 是利用每個 timer 上的兩個"匹配符合輸出"暫存器(Compare Match Output) COM?A 和 COM?B;
(注意雖是 Compare Match Output, 但暫存器名稱是 COMxy 不是 CMOxy 喔 !)
在timer1 的 mode 5, 又稱 Fast PWM mode, (不過請注意 Arduino 的 init( ) 設定只有 timer0 用這, 另外 timer1 和 timer2 不是用這 mode),
這時可以把 1 到 254 之間的值放入 OCR1A 或 OCR1B 以便控制 pin 9 或 pin 10
的 PWM duty cycle, 1 到 254 分別對應到 (1+1)/256, .., (254+1)/256 的 duty cycle.

會 +1 是硬體電路設計上的關係, data sheet 上說:
   Note that fast PWM holds the output high one cycle longer than the compare register value.
在 TCNT1 等於 0  之時, COM1A and/or COM1B 會輸出(當然要 TCCR1A 內的 COM1A1 and/or COM1B1 有set),
然後在 TCNT1 等於 OCR1A 則關閉 COM1A, 當 TCNT1 等於 OCR1B 則關閉 COM1B,
注意沒有立即關閉, 是延遲一個 tick 才關閉 ! 所以才會多加1, 因為一個循環是 256, 不是 255,如果不延遲加 1, 則輸出 val 是 254 時變成 254/256, 還差一點點, 所以犧牲 1/256, 就是沒有 1/256佔空比 !!

   由於 Arduino 的 init( )把 timer1 的 Prescaler 設定為 64,
(參考在你 Arduino IDE 內的   hardware\arduino\cores\arduino\wiring.c )
且把 timer1 設定為 8-bit phase correct pwm mode, 所以其頻率是 490.196Hz, 不是 976.5625Hz;
   所謂的 8-bit phase correct pwm mode, 意思是 TCNT? 從 0 數到 255, 接著又從 255 倒著數回 0,
那何時把 COM1A and/or COM1B 的輸出打開或關閉呢?

根據 datasheet, 在從 0 往上數, 碰到 OCR1A 時把 COM1A 關閉,
後從 255 往回數, 數到 OCR1A 時把 COM1A 打開(有電); 對於 OCR1B 和 COM1B 也是這樣!
這使得 duty cycle (佔空比) 更準確, 也就是 val 1 ~ 254 分別對應到 1/255 到 254/255 的 duty cycle.
但是 Frequency 則不是除以 256, 是要除以 255 再除以 2, 於是: (注意是 255, 不是 256喔!)
Frequency = 16 MHz / 64 / 255 / 2 = 490.196Hz;
timer 2 也是在 init( )被設為 Prescaler 64 的 phase correct pwm (8-bit);
但是, timer0 雖然 Prescaler 也設 64, 但 PWM 是用 Fast PWM mode,
不使用 phase correct mode 是為了避免影響維護 millis( ) 的中斷 timer0 Overflow Interrupt,
ISR(TIMER0_OVF_vect) 這中斷處理程序, 否則 millis( ) 和 micros( ) 以及 delay() 都會受到影響 !!
因此 , timer0 控制的 PWM 其 Frequency 是 976.5625Hz,
    16 MHz / 64 / 256 = 976.5625Hz
注意用 timer0 控制的pin 5, pin 6 之 PWM 的 duty cycle 無法是 1/256, 它是 0 再來就 2/256了!
結論:

  timer0 控制 pin 5, pin 6, PWM 頻率 976.5625Hz, duty cycle可以 2/256 ~ 255/256 (對應 1 到254);
  timer1 控制 pin 9, pin 10, PWM 頻率 490.196Hz, duty cycle 可以 1/255 ~ 254/255(對應 1 到254);
timer2 控制 pin 11, pin 3, PWM 頻率 與 duty cycle 跟 timer1 控制的相同 !!

Q: 那 PWM 的 Frequency 可不可以更改?
A: 可以, 偷改 timer 的 Prescaler 就可以達到更改 Frequency 的目的 !
   但是, 千萬不要更改 timer0 的 Prescaler, 否則 millis( ) 和 micros( ) 以及 delay() 都會受到影響 !!!
   以下是以 timer1 控制的 pin 9, pin 10 為例(注意兩個 pin 的頻率相同!)
   在你的 setup( ) { 內, 寫如下兩句即可:
      int fff = 3;  // 可以是 1, 2, 3, 4, 5
      TCCR1B = TCCR1B & 0xF8 | fff;
  其中 fff 與對應頻率如下:
  fff   Prescaler   Frequency
   1           1        31372.549 Hz
   2           8          3921.569
   3         64            490.196   <--DEFAULT
   4       256           122.549
   5    1024               30.637 Hz

至於 timer2 控制的 pin 11 和 pin 3,
則在 setup( ) { 內寫:
     TCCR2B = TCCR2B & 0xF8 | ?;
此處的 ? 可以有七種:
   ?  Prescaler   Frequency
   1         1       31372.549 Hz
   2         8         3921.569
   3            32          980.392
   4        64         490.196   <--DEFAULT
   5      128         245.098
   6      256         122.549
   7    1024           30.637 Hz

如果你堅持要改 timer0 的 Prescaler, 以更改 pin 5, pin 6 的 PWM 頻率:
   (注意 millis( ) 和 micros( ) 以及 delay() 都會受到影響 !! )
則在 setup( ) { 內寫:
     TCCR0B = TCCR0B & 0xF8 | ?;
此處的 ? 可以有五種:
   ?  Prescaler   Frequency
   1          1       362500 Hz
   2          8           7812.5
   3        64             976.5625   <--DEFAULT
   4      256             244.140625
   5    1024               61.03515625 Hz

參考:
   http://playground.arduino.cc/Main/TimerPWMCheatsheet
   http://www.atmel.com/Images/doc8161.pdf

[Sensor]MPU92/65

MPU92/65是很久以前買的感測器 基本上有加速度計、陀螺儀、電子羅盤、溫度計 以下是該電子商城的介紹 https://www.factoryforward.com/product/gy-87-mpu-9265-3-axis-9-dof-attitude-gyro-magnet...