2015年10月4日 星期日

PiQuadcopter(掰咖考特) -- 用Raspberry pi 做四軸飛行器(一) 前言

想做四軸很久了。會想用RPi不外乎以下理由:
- 磨練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能很快飛起來。

參考資料

http://blog.oscarliang.net/build-a-quadcopter-beginners-tutorial-1/

25 則留言:

  1. 你好,請問你之後有將bcm2835的程式放到Preempt RT kernel上使用嗎?我的在跑bcm2835_delayMicroseconds()後就停了...

    回覆刪除
    回覆
    1. 有的,我用的版本是4.1.12+ 4.1.12 RT patch,沒有任何問題。

      刪除
    2. 哦?我用的是4.1.13-rt15啊。
      我是跟著這個教學做的:http://www.frank-durr.de/?p=203
      請問你在設定kernel時,除了CONFIG_PREEMPT_RT_FULL這個外,還有沒有改了甚麼?

      刪除
    3. 印象中patch完改CONFIG_PREEMPT_RT_FULL後,就照一般compile kernel的步驟跑就好了阿,我沒另外改啥。需要的話可以給我你的code,我可以在我的pi上試一下。

      刪除
    4. 我第一次運行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之類?

      刪除
    5. bcm2835_delayMicroseconds 本身使用的成本就要100-200us,12us 太小囉

      刪除
    6. 你至少要改到450us看看...

      刪除
    7. 不是吧... 其實我是在做這個,這教學說usleep不夠精準,說要用BCM2835的...

      http://itpro.nikkeibp.co.jp/atcl/column/14/093000080/093000002/?ST=oss&P=1

      不過就算12us太少,也不至於會掛掉跑不到啊

      刪除
    8. 剛試了450us,也是跑不到
      我本來對電子、Linux和C也不太熟習,希望你不要介意指教

      刪除
    9. bcm2835_delayMicroseconds使用的是nanosleep,理論上會比usleep準,可是有使用成本的問題。

      刪除
    10. 等於這個clock_nanosleep()嗎?
      https://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO

      刪除
    11. 如果要做到12us,linux可以做到嗎?如果不能,要用甚麼做呢?

      刪除
    12. 12us理論上nanosleep做不太到,你可能要用software pwm,google pigpio

      刪除
    13. 我是指你如果只是要讓他每12us切換狀態的話。再不然就用busy waiting (while loop直到時間到)

      刪除
    14. 剛看了一下airspayce,原來你說的100-200us成本在changelog有說,那不怪得一直以來訊號也不準確啊...... 好,我先再看一下pigpio。

      再請問一下,你用的OS,和BCM2835版本是甚麼?

      刪除
    15. 我用的就是raspbian+bcm2835 1.48

      刪除
    16. 太好了,這困擾了我數星期了,實在感謝你啊!!

      刪除
    17. 不用客氣,以後多交流。

      刪除
    18. 你好,自從上一次留言後,我找了好幾個方法,大致上也是不能處理這麼短的廷時。
      就算是documentation寫可以的,也是用busy-loop方法,最終結果並不準確。
      最後,我的解決方法是改用Arduino :D
      因為這次我才接觸Arduino,我覺得Arduion在控制硬件上好像比Raspberry好。
      我看你這網站上的玩意,你好像愛用Raspberry?

      刪除
    19. Arduino畢竟是microcontroller,它只要照你寫的程式操作就好,不需要維持整個作業系統。

      我並沒有說特別偏愛哪個,只是想挑戰自己,Arduino拿來做四軸也不是不行。

      刪除
    20. 我想起汽車安全氣袋那例子,好像用Raspberry來控制四軸會比較不「即時反應」。我現在會想用Raspberry做中央控制,Arduino就控制獨立組件。

      刪除
    21. 這就要看你對「即時反應」的要求如何。
      我的Raspberry pi 四軸可以做到最大反應延遲為1ms左右(控制週期為4ms)不需要額外用arduino(當然我還是用arduino當遙控器就是了)。

      刪除
    22. 嗯,你對,ms做單位其實也很夠用!
      今次真學了不少,謝謝你

      刪除
    23. 不用客氣,有空多交流。

      刪除
  2. 作者已經移除這則留言。

    回覆刪除

Google Code Prettify