SEA ROCKS at Lung Ha Wan
在龍蝦灣對出約五百米海面,突出了幾塊礁石,
當海浪衝擊著它激起的浪花千變萬化,吸引著我。
My notes of DIY drones
在龍蝦灣對出約五百米海面,突出了幾塊礁石,
當海浪衝擊著它激起的浪花千變萬化,吸引著我。
One of the three treacherous peaks in Hong Kong.
釣魚翁山是香港數一數二的尖山,
山頂一段路很斜,要用爬的才能上去,
下山後有一段郊遊徑可以通往田下山及布袋澳。
上次試過1.5公里的飛行,今次打算試飛3公里,用的也是IBCrazy的Airblade天線。
飛行路線以mission設定好,可讓我專心留意OSD的數據-用電量,距離等等。
到了2.7公里斷了圖,心一驚就回航了。其實只是mission轉向時天線在一些角度下被降落架遮擋所至,感覺上超越3公里都無問題。
問題反而是電量支持不了,電量下跌至14.4時我還在海中心,mission設定了時速30公里,這個速度一定返不到來。就立刻轉為手動模式,一於高速返航。裝上了兩顆5400mAh 4S電池,飛行時間也只有10-12分鐘。試過後,覺得Y6機架是為了安全性而放棄了效率的設計。
高速返航時在OSD看到速度可達90公里以上,當時油門還未推盡,怕電機支持不了而收油了。感覺上,SkyHero真的是一隻力量型的機。
因為minimosd的顯示很差,還有兩次無故死掉,很想找一個代替品,直至找到了PlayUAV OSD。顯示很細緻,功能也多,硬件穩定,一試便知道我會繼續用了。何況是國產開發,還是開源project,就更少見,更應該支持了。
Air Antenna: IBCrazy 5.8 GHz Airblade Antenna
Ground Antenna : FatShark Patch Antenna
Frame: Sky Hero Spy 600
Controller : Pixhawk
Firmware : ArduCopter 3.3
Props : APC 12″ MR
Motors : Antigravity MT2814 710KV
Batteries : 4S 5400mAh battery x 2
OSD : PlayUAV OSD
Total distance : 6.2km
Farthest distance : 2.7km
我把一些自己的航拍短片上載到pixabay.com,供有興趣的朋友免費使用。希望自己的航拍興趣除了自己高興外,也能為其他人提供一點價值。很高興短片上載後的10天內已有超過1,000次的下載,也有3條片選為Editor Choise。
pixabay.com網站上的所有相片及影片都是以Creative Commons CC0出版。你可以複製、修改、發布或展示作品,亦可進行商業利用。當然,如果你使用了我的短片在你作品上,告訴我會使我好高興的。
要同時控制航拍機飛行及鏡頭的角度是一件困難的事,幸好多數航拍機都有自動導航的功能,只要在軟件中輸入路線,高度,速度等設定,航拍機就能自動航行。拍攝者就能專心地控制鏡頭的方向及角度,往往能拍出更多變化的片段。
我會在APM Planner小心計劃好路線,要特別留意飛行高度和地形的變化,最好是自己熟識的地點,而路線也要在視線範圍之內,有意外時可以立即接手操控。也會把自動返航(RTL)的高度設定得高一點(例如50米)。
我也會設定同一條路線飛行多次(DO_JUMP),第一次飛行時鏡頭向前平放,注要留意飛行高度,是否太接近障外物,做好除時取消導航的準備。當第一圈成功,就能專心於取景了。
在APM Planner裡還有一個很好用的功能(DO_SET_ROI),ROI是region of interest的簡寫,意思是航機的頭永遠向著這一點。上圖的#5就是ROI,所以航機飛到#6, #7機頭就會向著那更個半島。到了#8就取消了ROI,航拍機又會回復向前。
以下是一條短片,一次過飛了兩圈約六分鐘,已得到很多不同角度的片段。
請先看以下完成品的片。可遙控開關,改變閃光效果,效果式樣也可以自定。如果你也想DIY到你的多軸機上,只要小於HK$100,一些焊接技巧和簡單的編程知識。
我以為LED燈條就是LED燈條啦,但原來它們有很多種,甚麼WS2801, WS2811 和 WS2812,而我們要用的是WS2812,因為無論在接線和編程上它都比較簡單方便。
通常WS2812都是以一米為單位賣的,例如你隻四軸機想裝四條燈條,你可以買一條回來自己剪開便好了。
WS2812只有三條接線,5v電源,地線和數據線。要注意數據的方向,燈條上有箭頭指示。數據線要焊在DIN上, 如果焊錯了在DOUT,燈條是不會著的。
你需要提供5v電源給Arduino和LED燈條。你可以用獨立電源或由多軸機電池取電。多軸機電池一般由7v-21v不等,所以必須降壓才可接上,否則你會馬上燒掉Arduino和燈條。
也不要由receiver,flight controller取電。如果你使用了大量的LED,receiver和flight controller都沒有足夠的電流可以提供,最壞的情況可使你失去愛機。
如果已經接上了燈條,不要單獨用USB接上Arduino,要先接上5v電才插USB,否則可能會燒了Arduino。
如果用降壓,也要知道它可提供的電流。每粒LED使用60mA電流,例如一條一米的燈條有60粒LED,60 x 60mA = 3600mA = 3.6A,要確保你的降壓板能提供3.6A電流而不會過熱燒掉。否則便要滅少LED的數量。
每一顆LED用60mA電(紅綠藍各20 mA)
Arduino是控制LED燈條如何閃動的控製器,如果你沒有接觸過Arduino,可以看看它的網站,有很清楚的教學,基本的如何使用就不在這裡說了。
Arduino有很多版本,我使用了SparkFun Pro Micro,因為它細,而且有USB頭,不用FTDI,比較方便。
淘寶有很多這個版本的複製品,名稱都不一樣,文件更不用說了。找了好一回才知道原版是SparkFun Pro Micro,也找到了清楚的文件,使用起來也確定些。(對不起,我有想過買原版的,但運費貴過塊版,實在買不下去。)
我用了pin9-6連接4條LED,可以根據需要連接不同數量的燈條,pin位也可以任意,編程時對應輸出的pin位就行了。還要加上470Ω電阻,以保護Arduino。
我們可以用遙控來開關LED,改變顏色,閃光效果等。我用的receiver是FrSky X8R,把channel12連到Arduino的A0 pin,同樣地channel和pin位沒有硬性規定,視乎你的需要而改變,編程時應改動就好了。
我設定了channel12到遙控的TRN switch,這個鍵會自動回彈,剛好可用來每撥一次改變LED到下一個的顯示模式。
在Arduino編程控制WS2812
我們已完成了硬件的連接,可以看看如何加入軟件,使LED做事了。
控制LED,有兩個很好用的library:
如果你還沒有安裝Arduino的軟件,可以先看看入門篇。
如果你用SparkFun Pro Micro,可以跟這裡裝driver。
我用的是FastLED,由它的example中找了一些合適的再作修改,得到以下的程式:
[cpp]
#include <FastLED.h>
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define BRIGHTNESS 255
#define FRAMES_PER_SECOND 120
#define LED_TOP_PIN 6
#define LED_LEFT_PIN 8
#define LED_RIGHT_PIN 7
#define LED_BACK_PIN 9
#define RC_PIN A0
#define LONG_LEDS_NUM 12
#define LEDS_NUM 8
CRGB leds_top[LONG_LEDS_NUM];
CRGB leds_left[LEDS_NUM];
CRGB leds_right[LEDS_NUM];
CRGB leds_back[LEDS_NUM];
void setup() {
delay(3000); // 3 second delay for recovery
FastLED.addLeds<LED_TYPE, LED_TOP_PIN, COLOR_ORDER>(leds_top, LONG_LEDS_NUM).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, LED_LEFT_PIN, COLOR_ORDER>(leds_left, LEDS_NUM).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, LED_RIGHT_PIN, COLOR_ORDER>(leds_right, LEDS_NUM).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, LED_BACK_PIN, COLOR_ORDER>(leds_back, LEDS_NUM).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
pinMode(RC_PIN, INPUT);
}
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { off, flash, off, police };
uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating “base color” used by many of the patterns
int pulse_light = LEDS_NUM-1;
int leds_pos = 0;
int rc;
int rc_high = true;
void loop() {
rc = pulseIn(A0, HIGH, 25000);
leds_pos ++;
leds_pos = (leds_pos > 100) ? 0 : leds_pos;
// Top LED effect
topEffect();
// Call the current pattern function once, updating the ‘leds’ array
gPatternsgCurrentPatternNumber;
// pulse light in last LED of arms
pulse();
// send the ‘leds’ array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
// FastLED.delay(1000 / FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) {
gHue++; // slowly cycle the “base color” through the rainbow
}
EVERY_N_SECONDS( 10 ) {
// nextPattern(); // change patterns periodically
}
// RC control
if (rc > 1500 && !rc_high) {
rc_high = true;
nextPattern();
}
if (rc < 1500 && rc_high) {
rc_high = false;
}
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
// add one to the current pattern number, and wrap around at the end
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void topEffect()
{
// a colored dot sweeping back and forth, with fading trails
fadeToBlackBy( leds_top, LONG_LEDS_NUM, 30);
int pos = beatsin16(40, 0, LONG_LEDS_NUM);
leds_top[pos] += CHSV( gHue, 255, 192);
}
void off()
{
for (int i = 0; i < LEDS_NUM; i++) {
leds_left[i] = CRGB::Black;
leds_right[i] = CRGB::Black;
leds_back[i] = CRGB::Black;
}
}
void flash()
{
fadeToBlackBy( leds_left, LEDS_NUM, 50);
fadeToBlackBy( leds_right, LEDS_NUM, 50);
fadeToBlackBy( leds_back, LEDS_NUM, 50);
if (leds_pos < pulse_light) { leds_left[leds_pos] = CRGB::Red; leds_right[leds_pos] = CRGB::Blue; leds_back[leds_pos] = CRGB::White; } } void police() { CRGB c1 = CRGB::Red; CRGB c2 = CRGB::Blue; CRGB c3 = CRGB::White; if (leds_pos > 50) {
c1 = CRGB::Blue;
c2 = CRGB::Red;
c3 = CRGB::White;
}
if ((leds_pos % 5) == 0) {
c1 = c2 = c3 = CRGB::Black;
}
for (int i = 0; i < pulse_light; i++) {
leds_left[i] = c1;
leds_right[i] = c2;
leds_back[i] = c3;
}
}
void pulse()
{
if ((leds_pos % 50) == 0) {
leds_left[pulse_light] = leds_right[pulse_light] = leds_back[pulse_light] = leds_top[0] = CRGB::White;
} else {
leds_left[pulse_light] = leds_right[pulse_light] = leds_back[pulse_light] = leds_top[0] = CRGB::Black;
}
}
[/cpp]
下載後,修改一下pins位,燈的數量,以配合你硬件的設定,再上傳到Arduino執行便可以了。我只寫了兩個燈效,你有興趣可以輕易地修改或增加自己的燈效。
剛剛砌好隻SkyHero Spy,立刻試機,但一飛即反!
起初以為是電機的次序錯了,又以為是方向錯了,又檢查了螺旋槳方向,全部無問題。
再install firmware (Y6 frame),再做accelerometer calibration,再飛,再死。
原來我的frame type是Y6B,必須在Frame Type選Y6B。
選好了就成功了。
後來發現在Full Parameter List選Download Param File,把3DR Y6的設定載入,再自己調整不適合的會更方便。
這個星期在砌Sky-Hero SPY 600,SPY是一部Y6機,費了一番功夫在它的摩打轉向與螺旋槳上。
由於都是Y6,所以跟著上面3DR Y6這張說明去調6個摩打。如圖以為要setup三個順時針及三個反時針的摩打,但裝好一試便知道錯了。它們都向同一個方向轉,負負得正嘛,反時針的摩打把它反轉裝,它變回順時針轉了!所以,所有的摩打都要順時針轉,裝好了便自然得到以上的結果了。原本很簡單的事,被我復雜化了。裝好,焊好了的摩打都要打開再焊,真的想殺人哦。
我買的是MT2814,是一對買的。很體貼的是正反槳座,給四軸用是剛剛好的,但給Y6就有問題了。於由6個摩打都向順時針轉,所以全部都應該用反槳座,使我有一半的槳座要再買了。
還有,反轉了的摩打,螺旋槳會跟著反轉嗎?不是!所有螺旋槳都應該label向上,上面裝正槳,下面裝反槳就是了。
試裝APC13吋槳上QAV500成功,做了一次簡單的測試,轉用13″槳是否有好處?
左面的13″槳明顯地比右面的12″槳震動率高出30%有多。
13″槳以45%油門維持高度(AltHold),12″槳要55%油門。
13″槳以45%油門AltHold,飛行時間會長一點嗎?也不是,反而12″槳有更長的飛行時間。
用的是4S電,設定了14.8v自動返航,13″槳更早開始返航。
無論在飛行時間,震動率再看,較細的槳能提供更好的效能。但為什麼多數人還是追求更安裝更大的槳?我想是負載罷,如果要負載更大的電池,gimbal,相機,更大的槳是必須的。13″比12″槳減少10%的油門hold機,意味更重的負載。如果沒大負載的需要,大槳是沒有必要的。