- 磨練C programming
- 了解kernel programming(雖然最後幾乎沒用上)
- 想體驗Real-Time Linux的威力(雖然還沒開始用)
一般來說RPi拿來做四軸有點不太適合,因為作業系統是Linux(雖然據說可以安裝其他的RTOS,不過我暫時不討論這個),而屬於通用型作業系統的Linux為了能在較短時間內完成較多任務,其即時性(從系統收到任務的時間到系統開始處理這任務的時間)比較差(正在處理的任務不能被優先權較高的任務插隊)。我希望用多執行緒程式+搶佔式即時核心(Preempt RT Linux kernel)來改善這個問題。
稍微搜尋了一下前人用Rpi做四軸的經驗:
RPi only
https://github.com/idavidstory/goPiCopter
使用Go程式語言,sensor更新週期50Hz,控制週期10Hz,9 DOF + PWM(PCA9685)
http://blog.pistuffing.co.uk/
看起來似乎沒完成
RPi + Arduino
https://github.com/vjaunet/QUADCOPTER_V2
使用MPU6050,Arduino用來控制SPI介面的硬體和PWM
https://github.com/rpicopter/AvrMiniCopter-wiki/wiki
10 DOF
https://www.raspberrypi.org/forums/viewtopic.php?f=37&t=35746
MPU6050,使用特殊ESC所以不用PWM,sensor更新週期在300-400Hz,以C++編寫程式,不用Real-time OS,Arduino用於RFM12無線模組(與筆電交換訊息控制機體)
RPi + 其他飛控
http://www.instructables.com/id/Autonomous-Cardboard-Rasberry-Pi-Controlled-Quad/
http://www.botched.co.uk/quadrocopter/
使用dsPIC30F(PWM+I2C),10 DOF
看起來完全用RPi不用其他MCU好像也不是不可能。
四軸的飛行控制需要的硬體有:
- 機架、電池、(無刷馬達+螺旋槳)*4 (廢話)
- ESC (electronic speed control) :控制馬達轉速,需要用四個PWM(Pulse-width modulation,脈衝寬度調變)個別控制
- IMU(Inertial measurement unit,慣性測量單元):三軸加速度計(測量重力加速度方向+加速度)+三軸角速度計(測量角速度)+三軸電子羅盤(測知方向)+氣壓計(換算海拔高度),3+3+3+1簡稱10軸 (10 DOF,一般來說6軸勉強夠用)。
- 無線通訊模組(wifi 或RF)
- 如果想知道電池電量是不是快到底了,最好加個ADC(類比轉數位輸出)測量電池電壓。
而我手上的RPi model B+上面有:
- I2C * 1 (可接多個裝置,支援400kHz以上傳輸速度)
- SPI * 1 (可接兩個裝置,支援8MB/s以上傳輸速度)
- PWM * 1 (不夠用...),雖然可以用DMA做軟體PWM,不過更新頻率不能太高(~100Hz差不多極限了)
根據以上需求,結論就是我需要買:
- 10軸IMU:GY80(I2C,400kHz,前6軸資料更新可達1600Hz)
- nRF24L01*2:無線模組(250Kbps-2Mbps,頻寬愈大有效距離愈小)一個給RPi用,一個給Arduino用(操縱四軸),SPI
- ADC:MCP3008:10bit(量電壓夠用了) ,SPI
- PWM:PCA9685(Adafruit有賣已經設計好的電路,坊間也有類似的),I2C,12bit,頻率可達1526Hz
然後就是程式部份,我選擇bcm2835( http://www.airspayce.com/mikem/bcm2835/ ) 而不是比較知名的wiringPi。因為bcm2835比較單純(從mmap找到address->讀寫bit控制),不需要任何驅動程式,而wiringPi的SPI跟I2C控制是建立在驅動程式上,我希望能藉此避免驅動程式的介入把操縱單純化,這樣以後若是用Preempt RT kernel也比較不受影響。
目前我的進度到PID Control(調的好累),希望不久後我的PiQuadcopter能很快飛起來。
你好,請問你之後有將bcm2835的程式放到Preempt RT kernel上使用嗎?我的在跑bcm2835_delayMicroseconds()後就停了...
回覆刪除有的,我用的版本是4.1.12+ 4.1.12 RT patch,沒有任何問題。
刪除哦?我用的是4.1.13-rt15啊。
刪除我是跟著這個教學做的:http://www.frank-durr.de/?p=203
請問你在設定kernel時,除了CONFIG_PREEMPT_RT_FULL這個外,還有沒有改了甚麼?
印象中patch完改CONFIG_PREEMPT_RT_FULL後,就照一般compile kernel的步驟跑就好了阿,我沒另外改啥。需要的話可以給我你的code,我可以在我的pi上試一下。
刪除我第一次運行Raspbian Jessie並安裝BCM2835 Library後,bcm2835_delayMicroseconds()是可以成功跑到的。然後改kernel成RT,就路不到了。以下這段程式,顯示第一個"SLEEP"後就斷了...
刪除fprintf(stdout , "HIGH\n");
bcm2835_gpio_write(PIN, HIGH);
fprintf(stdout , "SLEEP\n");
bcm2835_delayMicroseconds(12);
fprintf(stdout , "LOW\n");
bcm2835_gpio_write(PIN, LOW);
fprintf(stdout , "SLEEP\n");
bcm2835_delayMicroseconds(12);
我本來沒有用C的,不知道可以怎樣debug。BCM2835 Library應該還存在,可能新的kernel沒有了甚麼driver之類?
bcm2835_delayMicroseconds 本身使用的成本就要100-200us,12us 太小囉
刪除你至少要改到450us看看...
刪除不是吧... 其實我是在做這個,這教學說usleep不夠精準,說要用BCM2835的...
刪除http://itpro.nikkeibp.co.jp/atcl/column/14/093000080/093000002/?ST=oss&P=1
不過就算12us太少,也不至於會掛掉跑不到啊
剛試了450us,也是跑不到
刪除我本來對電子、Linux和C也不太熟習,希望你不要介意指教
bcm2835_delayMicroseconds使用的是nanosleep,理論上會比usleep準,可是有使用成本的問題。
刪除等於這個clock_nanosleep()嗎?
刪除https://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO
如果要做到12us,linux可以做到嗎?如果不能,要用甚麼做呢?
刪除12us理論上nanosleep做不太到,你可能要用software pwm,google pigpio
刪除我是指你如果只是要讓他每12us切換狀態的話。再不然就用busy waiting (while loop直到時間到)
刪除剛看了一下airspayce,原來你說的100-200us成本在changelog有說,那不怪得一直以來訊號也不準確啊...... 好,我先再看一下pigpio。
刪除再請問一下,你用的OS,和BCM2835版本是甚麼?
我用的就是raspbian+bcm2835 1.48
刪除太好了,這困擾了我數星期了,實在感謝你啊!!
刪除不用客氣,以後多交流。
刪除你好,自從上一次留言後,我找了好幾個方法,大致上也是不能處理這麼短的廷時。
刪除就算是documentation寫可以的,也是用busy-loop方法,最終結果並不準確。
最後,我的解決方法是改用Arduino :D
因為這次我才接觸Arduino,我覺得Arduion在控制硬件上好像比Raspberry好。
我看你這網站上的玩意,你好像愛用Raspberry?
Arduino畢竟是microcontroller,它只要照你寫的程式操作就好,不需要維持整個作業系統。
刪除我並沒有說特別偏愛哪個,只是想挑戰自己,Arduino拿來做四軸也不是不行。
我想起汽車安全氣袋那例子,好像用Raspberry來控制四軸會比較不「即時反應」。我現在會想用Raspberry做中央控制,Arduino就控制獨立組件。
刪除這就要看你對「即時反應」的要求如何。
刪除我的Raspberry pi 四軸可以做到最大反應延遲為1ms左右(控制週期為4ms)不需要額外用arduino(當然我還是用arduino當遙控器就是了)。
嗯,你對,ms做單位其實也很夠用!
刪除今次真學了不少,謝謝你
不用客氣,有空多交流。
刪除作者已經移除這則留言。
回覆刪除