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

[Arduino]ADC input voltage


輸入電壓範圍
ADC input voltage range Vcc~0V,這裡VCC為5V
解析度0~1023,
10Bit
The device features a 10-bit successive approximation ADC.



[Sensor]MPU92/65

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