查看: 148214|回复: 6

[5月赛] 【麒麟传说】 [麒麟座开发板试用体验]+之OnePilot飞控

  [复制链接]

3

主题

4

帖子

22

积分

新手上路

Rank: 1

积分
22
发表于 2017-5-11 02:24:24 | 显示全部楼层 |阅读模式
【参赛类别】:麒麟传说
【正文】


  大家好,我叫徐珂靖,住在冰城,是个爱捣鼓板子的宅男。当然,今天要介绍的主角依然不是我。。本宝宝是大伙儿的熟人,就不详细介绍了,以下省略一百字。。
  我们直入正题吧。管理员:因为本帖有的图片叉烧包了,所以大家可以看这期微信:https://mp.weixin.qq.com/s?__biz ... 14fb419a25909ca3#rd


  OnePilot飞控是在OneNetMini板子的基础上设计的,上面跑的是我改写过的PaparazziUAV飞控的代码

  PaparazziUAV飞控是个开源项目,简称PPZ,包含了飞控硬件和软件项目。历代PPZ飞控硬件可以参考官方网站的介绍http://wiki.paparazziuav.org/wiki/Category:Autopilots 。软件代码可以去Github下载,地址为https://github.com/paparazzi/paparazzi 。PPZ程序支持的硬件很多,除了官方公布的几个硬件版本以外,还支持NAZE32、CC3D、和PX4等。支持的硬件可以在源码上查阅到https://github.com/paparazzi/paparazzi/tree/master/sw/airborne/boards
  
  我们要尽量只走那些别人没走过的路,所以,千万别重新从底层再写一遍硬件驱动或是控制算法了哦。

  虽然PPZ支持的硬件很多,但是PPZ的代码没有对OneNetMini做过适配。
  
  然而,需求还是有的,小伙伴们还是想拿OneNetMini控一下无人机,对不对?

  因此,我做了这个设计,基于OneNetMini开发了OnePilot飞控的硬件,然后对PPZ飞控固件的代码做了修改,使其可以运行在OnePilot上。
  
1 OnePilot飞控简介

OnePilot硬件的基本特性如下:
  STM32F103CBT6 微处理器
  MPU6050陀螺仪、加速度计
  HMC5883L 磁力计
  MS5611气压传感器
  Ublox 6m GPS
  一路电池电压采集
  两路UART
  一路I2C
  一路PPM信号输入
  四路PWM信号输出
  板载4颗LED用于飞控状态显示


  硬件上确实已经接入了磁力计和气压计。然而实际使用时发现如果要加上它们,正好少了1kb空间,导致代码无法正常烧入。  目前的算法是这样的,海拔只从GPS获取,不对气压数据做融合;机头方向通过GPS航向获得,然后输入航姿系统。

  虽然麒麟座的mcu弱了点,但至少还是能把基本的该有的功能都实现,比如航姿、自稳、导航。
  
  下面,贴出几张实物照片给大伙儿看看成果。
  第一张图是在地面站上把飞控程序调通时候截取的。这次先被测试编译的是个控制四旋翼的程序。编译过程无报错、无警告。




  传感器使用了GY-86,它包含了3轴陀螺仪、3轴磁场计、3轴加速度计和气压计。


  
  飞控正在运行。可以看到从左往右第3个绿灯是亮着的。它是AHRS算法的指示灯,板子上电后闪烁,姿态解算成功后常亮。


  如果把传感器板向左滚转,电脑上的PFD显示飞机的姿态,地面(褐色)在左边,天空(蓝色)在右边。PFD叫做主飞行显示器。

  上图中大片黑色的是飞机位置在地图上的显示,类似高德导航那样的。
  之所以显示黑色,只是因为谷歌地图的图像暂时没下载到。
  这个不影响的,因为对飞控来说,只要有经纬度坐标数据就行了。
  飞行路线上的控制点称为航点,如下图:


  如果把传感器板向右滚转,电脑上的PFD显示如下


  如果使传感器板低头,电脑上的PFD已经看不到天空了(蓝色),视野里面全是大地(褐色)。


  如果把传感器板扬起头,电脑上的PFD显示如下,



  通过上面的介绍,大伙儿一定也想亲手DIY一个飞控了吧。
  好,我们继续。

2 飞控板引脚规划



  因为要往OneNetMini板子上连接的外置装置很多,所以,在写程序前,我们先要做一下引脚规划。
   
我们需要以下接口:
  一个数字IO输入,用于PPM信号解码。
  串口1,用于数传。
  串口2,用于GPS。
  I2C,与传感器模块通讯。
  4路PWM输出。
  1路ADC,测量电池电压。

   
  我们先看一下OneNet的原理图
  注意那个12M晶振(不是8M),写板子配置文件的时候要注意。


  我们发现板子上的B6到B9已经被用了,分别接了不同颜色的LED。
  那我们就把这4个端口用于飞控状态指示吧,也省得再自己焊LED了。
   
  我规划了一下端口,结果如下表所示,定时器编号和通道编号我也写上了,这样可以在后续写飞控板的头文件时候做参考。

  A1是ppm信号输入
  A2和A3是串口2,接到GPS
  A3用于电池电压测量,接到1K和10K电阻组成的分压电路。
  A6、A7、B0和B1这4个分别用于PWM输出。
  A9和A10是串口1,接到数传
  B10和B11是I2C2,接到传感器模块上
  B6到B9四盏LED灯。

  

3飞控板的头文件



  接下来,按上一节那个引脚规划表格写一下飞控板的头文件

  头文件取名叫onenetmini.h,完整的代码如下

  1. #ifndef CONFIG_ONENETMINI_H
  2. #define CONFIG_ONENETMINI_H

  3. /* OneNetMini has a 12MHz external clock and 72MHz internal. */
  4. #define EXT_CLK 12000000
  5. #define AHB_CLK 72000000

  6. /*
  7. * Onboard LEDs
  8. * LED2 PB6
  9. * LED3 PB7
  10. * LED4 PB8
  11. * LED5 PB9
  12. */

  13. /* led2, on PB6 */
  14. #ifndef USE_LED_2
  15. #define USE_LED_2 1
  16. #endif
  17. #define LED_2_GPIO GPIOB
  18. #define LED_2_GPIO_PIN GPIO6
  19. #define LED_2_GPIO_ON gpio_clear
  20. #define LED_2_GPIO_OFF gpio_set
  21. #define LED_2_AFIO_REMAP {                            \
  22.     rcc_periph_clock_enable(RCC_AFIO);                  \
  23.     AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;  \
  24.   }


  25. /* led3, on PB7 */
  26. #ifndef USE_LED_3
  27. #define USE_LED_3 1
  28. #endif
  29. #define LED_3_GPIO GPIOB
  30. #define LED_3_GPIO_PIN GPIO7
  31. #define LED_3_GPIO_ON gpio_clear
  32. #define LED_3_GPIO_OFF gpio_set
  33. #define LED_3_AFIO_REMAP ((void)0)

  34. /* led4, on PB8 */
  35. #ifndef USE_LED_4
  36. #define USE_LED_4 1
  37. #endif
  38. #define LED_4_GPIO GPIOB
  39. #define LED_4_GPIO_PIN GPIO8
  40. #define LED_4_GPIO_ON gpio_clear
  41. #define LED_4_GPIO_OFF gpio_set
  42. #define LED_4_AFIO_REMAP ((void)0)

  43. /* led5, on PB9 */
  44. #ifndef USE_LED_5
  45. #define USE_LED_5 1
  46. #endif
  47. #define LED_5_GPIO GPIOB
  48. #define LED_5_GPIO_PIN GPIO8
  49. #define LED_5_GPIO_ON gpio_clear
  50. #define LED_5_GPIO_OFF gpio_set
  51. #define LED_5_AFIO_REMAP ((void)0)



  52. /*
  53. * UART pin configuration
  54. * TX1 (PA9), RX1 (PA10)
  55. * TX2 (PA2), RX2 (PA3)
  56. */
  57. /* UART1 on main port, TX (PA9)TIM1 CH2, RX (PA10)TIM1 CH3 */
  58. #define UART1_GPIO_AF 0
  59. #define UART1_GPIO_PORT_RX GPIO_BANK_USART1_RX
  60. #define UART1_GPIO_RX GPIO_USART1_RX
  61. #define UART1_GPIO_PORT_TX GPIO_BANK_USART1_TX
  62. #define UART1_GPIO_TX GPIO_USART1_TX

  63. /* UART2 on RC I/O, TX (PA2) TIM2 CH3, RX (PA3)TIM2 CH4 */
  64. #define UART2_GPIO_AF 0
  65. #define UART2_GPIO_PORT_RX GPIO_BANK_USART2_RX
  66. #define UART2_GPIO_RX GPIO_USART2_RX
  67. #define UART2_GPIO_PORT_TX GPIO_BANK_USART2_TX
  68. #define UART2_GPIO_TX GPIO_USART2_TX




  69. /* PPM
  70. *
  71. * Default is PPM config 2, input on GPIOA1
  72. */
  73. #if PPM_CONFIG
  74. #undef PPM_CONFIG
  75. #endif
  76. #define PPM_CONFIG 2

  77. #if PPM_CONFIG == 2
  78. /* input on PA1 TIM2 CH2 */
  79. #define USE_PPM_TIM2 1
  80. #define PPM_CHANNEL         TIM_IC2
  81. #define PPM_TIMER_INPUT     TIM_IC_IN_TI2
  82. #define PPM_IRQ             NVIC_TIM2_IRQ
  83. // Capture/Compare InteruptEnable and InterruptFlag
  84. #define PPM_CC_IE           TIM_DIER_CC2IE
  85. #define PPM_CC_IF           TIM_SR_CC2IF
  86. #define PPM_GPIO_PORT       GPIOA
  87. #define PPM_GPIO_PIN        GPIO1
  88. #define PPM_GPIO_AF         0

  89. // Move default ADC timer
  90. #if USE_AD_TIM2
  91. #undef USE_AD_TIM2
  92. #endif
  93. #define USE_AD_TIM1 1

  94. #else
  95. #error "Unknown PPM config"
  96. #endif // PPM_CONFIG


  97. /*
  98. * ADC
  99. */
  100. // Internal ADC for battery enabled by default
  101. #ifndef USE_ADC_4
  102. #define USE_ADC_4 1
  103. #endif
  104. #if USE_ADC_4
  105. #define AD1_4_CHANNEL 4
  106. #define ADC_4 AD1_4
  107. #define ADC_4_GPIO_PORT GPIOA
  108. #define ADC_4_GPIO_PIN GPIO4
  109. #endif

  110. /* allow to define ADC_CHANNEL_VSUPPLY in the airframe file*/
  111. #ifndef ADC_CHANNEL_VSUPPLY
  112. #define ADC_CHANNEL_VSUPPLY ADC_4
  113. #endif

  114. /* 10k/1k resistor divider, 11 * 3.3V / 4096 */
  115. #define DefaultVoltageOfAdc(adc) (0.008862*adc)



  116. /*
  117. * I2C
  118. */
  119. /* port */
  120. #define I2C2_GPIO_PORT GPIOB
  121. #define I2C2_GPIO_SCL GPIO10
  122. #define I2C2_GPIO_SDA GPIO11


  123. /*
  124. * PWM
  125. * only servos 1-4 enabled for now
  126. */
  127. /* servos 1-4 */
  128. #define PWM_USE_TIM3 1
  129. #define USE_PWM1 1
  130. #define USE_PWM2 1
  131. #define USE_PWM3 1
  132. #define USE_PWM4 1

  133. #define PWM_USE_TIM1 0

  134. /* servo 5 */

  135. #define USE_PWM5 0
  136. /* servo 6 */
  137. #define PWM_USE_TIM2 0
  138. #define USE_PWM6 0

  139. #define ACTUATORS_PWM_NB 4



  140. // PWM_SERVO_x is the index of the servo in the actuators_pwm_values array
  141. #if USE_PWM1
  142. #define PWM_SERVO_1 0
  143. #define PWM_SERVO_1_TIMER TIM3
  144. #define PWM_SERVO_1_GPIO GPIOA
  145. #define PWM_SERVO_1_PIN GPIO6
  146. #define PWM_SERVO_1_AF 0
  147. #define PWM_SERVO_1_OC TIM_OC1
  148. #define PWM_SERVO_1_OC_BIT (1<<0)
  149. #else
  150. #define PWM_SERVO_1_OC_BIT 0
  151. #endif

  152. #if USE_PWM2
  153. #define PWM_SERVO_2 1
  154. #define PWM_SERVO_2_TIMER TIM3
  155. #define PWM_SERVO_2_GPIO GPIOA
  156. #define PWM_SERVO_2_PIN GPIO7
  157. #define PWM_SERVO_2_AF 0
  158. #define PWM_SERVO_2_OC TIM_OC2
  159. #define PWM_SERVO_2_OC_BIT (1<<1)
  160. #else
  161. #define PWM_SERVO_2_OC_BIT 0
  162. #endif

  163. #if USE_PWM3
  164. #define PWM_SERVO_3 2
  165. #define PWM_SERVO_3_TIMER TIM3
  166. #define PWM_SERVO_3_GPIO GPIOB
  167. #define PWM_SERVO_3_PIN GPIO0
  168. #define PWM_SERVO_3_AF 0
  169. #define PWM_SERVO_3_OC TIM_OC3
  170. #define PWM_SERVO_3_OC_BIT (1<<2)
  171. #else
  172. #define PWM_SERVO_3_OC_BIT 0
  173. #endif

  174. #if USE_PWM4
  175. #define PWM_SERVO_4 3
  176. #define PWM_SERVO_4_TIMER TIM3
  177. #define PWM_SERVO_4_GPIO GPIOB
  178. #define PWM_SERVO_4_PIN GPIO1
  179. #define PWM_SERVO_4_AF 0
  180. #define PWM_SERVO_4_OC TIM_OC4
  181. #define PWM_SERVO_4_OC_BIT (1<<3)
  182. #else
  183. #define PWM_SERVO_4_OC_BIT 0
  184. #endif

  185. /* servos 1-4 on TIM3 */
  186. #define PWM_TIM3_CHAN_MASK (PWM_SERVO_1_OC_BIT|PWM_SERVO_2_OC_BIT|PWM_SERVO_3_OC_BIT|PWM_SERVO_4_OC_BIT)

  187. /* Default actuators driver */
  188. #define DEFAULT_ACTUATORS "subsystems/actuators/actuators_pwm.h"
  189. #define ActuatorDefaultSet(_x,_y) ActuatorPwmSet(_x,_y)
  190. #define ActuatorsDefaultInit() ActuatorsPwmInit()
  191. #define ActuatorsDefaultCommit() ActuatorsPwmCommit()

  192. #endif /* CONFIG_ONENETMINI_H */
复制代码

  是不是有些长?  小明同学表示他已经学不下去了。
  
  别急,我慢慢给大家讲解。

  我们来分段解释一下这个“飞流直下三千尺”的头文件。

  先定义板子的外部晶振12M,内部频率72M

  1. #ifndef CONFIG_ONENETMINI_H
  2. #define CONFIG_ONENETMINI_H

  3. /* OneNetMini has a 12MHz external clock and 72MHz internal. */
  4. #define EXT_CLK 12000000
  5. #define AHB_CLK 72000000
复制代码

  然后定义四个LED的管脚,B6到B9
  1. /*
  2. * Onboard LEDs
  3. * LED2 PB6
  4. * LED3 PB7
  5. * LED4 PB8
  6. * LED5 PB9
  7. */

  8. /* led2, on PB6 */
  9. #ifndef USE_LED_2
  10. #define USE_LED_2 1
  11. #endif
  12. #define LED_2_GPIO GPIOB
  13. #define LED_2_GPIO_PIN GPIO6
  14. #define LED_2_GPIO_ON gpio_clear
  15. #define LED_2_GPIO_OFF gpio_set
  16. #define LED_2_AFIO_REMAP {                            \
  17.     rcc_periph_clock_enable(RCC_AFIO);                  \
  18.     AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;  \
  19.   }


  20. /* led3, on PB7 */
  21. #ifndef USE_LED_3
  22. #define USE_LED_3 1
  23. #endif
  24. #define LED_3_GPIO GPIOB
  25. #define LED_3_GPIO_PIN GPIO7
  26. #define LED_3_GPIO_ON gpio_clear
  27. #define LED_3_GPIO_OFF gpio_set
  28. #define LED_3_AFIO_REMAP ((void)0)

  29. /* led4, on PB8 */
  30. #ifndef USE_LED_4
  31. #define USE_LED_4 1
  32. #endif
  33. #define LED_4_GPIO GPIOB
  34. #define LED_4_GPIO_PIN GPIO8
  35. #define LED_4_GPIO_ON gpio_clear
  36. #define LED_4_GPIO_OFF gpio_set
  37. #define LED_4_AFIO_REMAP ((void)0)

  38. /* led5, on PB9 */
  39. #ifndef USE_LED_5
  40. #define USE_LED_5 1
  41. #endif
  42. #define LED_5_GPIO GPIOB
  43. #define LED_5_GPIO_PIN GPIO8
  44. #define LED_5_GPIO_ON gpio_clear
  45. #define LED_5_GPIO_OFF gpio_set
  46. #define LED_5_AFIO_REMAP ((void)0)
复制代码

  接着,定义两组串口,USART1和USART2。
  大家一定也发现了,我这次写的代码,注释都非常详细,简直像教科书一样。
  这都是为了方便大家阅读啊!!!!!
  1. /*
  2. * UART pin configuration
  3. * TX1 (PA9), RX1 (PA10)
  4. * TX2 (PA2), RX2 (PA3)
  5. */
  6. /* UART1 on main port, TX (PA9)TIM1 CH2, RX (PA10)TIM1 CH3 */
  7. #define UART1_GPIO_AF 0
  8. #define UART1_GPIO_PORT_RX GPIO_BANK_USART1_RX
  9. #define UART1_GPIO_RX GPIO_USART1_RX
  10. #define UART1_GPIO_PORT_TX GPIO_BANK_USART1_TX
  11. #define UART1_GPIO_TX GPIO_USART1_TX

  12. /* UART2 on RC I/O, TX (PA2) TIM2 CH3, RX (PA3)TIM2 CH4 */
  13. #define UART2_GPIO_AF 0
  14. #define UART2_GPIO_PORT_RX GPIO_BANK_USART2_RX
  15. #define UART2_GPIO_RX GPIO_USART2_RX
  16. #define UART2_GPIO_PORT_TX GPIO_BANK_USART2_TX
  17. #define UART2_GPIO_TX GPIO_USART2_TX
复制代码

  PPM输入使用A1,定时器2,通道2
  1. /* PPM
  2. *
  3. * Default is PPM config 2, input on GPIOA1
  4. */
  5. #if PPM_CONFIG
  6. #undef PPM_CONFIG
  7. #endif
  8. #define PPM_CONFIG 2

  9. #if PPM_CONFIG == 2
  10. /* input on PA1 TIM2 CH2 */
  11. #define USE_PPM_TIM2 1
  12. #define PPM_CHANNEL         TIM_IC2
  13. #define PPM_TIMER_INPUT     TIM_IC_IN_TI2
  14. #define PPM_IRQ             NVIC_TIM2_IRQ
  15. // Capture/Compare InteruptEnable and InterruptFlag
  16. #define PPM_CC_IE           TIM_DIER_CC2IE
  17. #define PPM_CC_IF           TIM_SR_CC2IF
  18. #define PPM_GPIO_PORT       GPIOA
  19. #define PPM_GPIO_PIN        GPIO1
  20. #define PPM_GPIO_AF         0
复制代码

  电池电压监测,ADC脚A4。使用10k和1K电阻分压采集电池电压
  1. // Move default ADC timer
  2. #if USE_AD_TIM2
  3. #undef USE_AD_TIM2
  4. #endif
  5. #define USE_AD_TIM1 1

  6. #else
  7. #error "Unknown PPM config"
  8. #endif // PPM_CONFIG


  9. /*
  10. * ADC
  11. */
  12. // Internal ADC for battery enabled by default
  13. #ifndef USE_ADC_4
  14. #define USE_ADC_4 1
  15. #endif
  16. #if USE_ADC_4
  17. #define AD1_4_CHANNEL 4
  18. #define ADC_4 AD1_4
  19. #define ADC_4_GPIO_PORT GPIOA
  20. #define ADC_4_GPIO_PIN GPIO4
  21. #endif

  22. /* allow to define ADC_CHANNEL_VSUPPLY in the airframe file*/
  23. #ifndef ADC_CHANNEL_VSUPPLY
  24. #define ADC_CHANNEL_VSUPPLY ADC_4
  25. #endif

  26. /* 10k/1k resistor divider, 11 * 3.3V / 4096 */
  27. #define DefaultVoltageOfAdc(adc) (0.008862*adc)
复制代码

  I2C2接口的引脚定义,我们使用I2C2
  1. /*
  2. * I2C
  3. */
  4. /* port */
  5. #define I2C2_GPIO_PORT GPIOB
  6. #define I2C2_GPIO_SCL GPIO10
  7. #define I2C2_GPIO_SDA GPIO11
复制代码

  初步定义一下PWM。
  1. /*
  2. * PWM
  3. * only servos 1-4 enabled for now
  4. */
  5. /* servos 1-4 */
  6. #define PWM_USE_TIM3 1
  7. #define USE_PWM1 1
  8. #define USE_PWM2 1
  9. #define USE_PWM3 1
  10. #define USE_PWM4 1

  11. #define PWM_USE_TIM1 0

  12. /* servo 5 */

  13. #define USE_PWM5 0
  14. /* servo 6 */
  15. #define PWM_USE_TIM2 0
  16. #define USE_PWM6 0

  17. #define ACTUATORS_PWM_NB 4
复制代码

  详细地定义这4个PWM输出通道,注意定时器号和通道号千万别写错了。
  1. // PWM_SERVO_x is the index of the servo in the actuators_pwm_values array
  2. #if USE_PWM1
  3. #define PWM_SERVO_1 0
  4. #define PWM_SERVO_1_TIMER TIM3
  5. #define PWM_SERVO_1_GPIO GPIOA
  6. #define PWM_SERVO_1_PIN GPIO6
  7. #define PWM_SERVO_1_AF 0
  8. #define PWM_SERVO_1_OC TIM_OC1
  9. #define PWM_SERVO_1_OC_BIT (1<<0)
  10. #else
  11. #define PWM_SERVO_1_OC_BIT 0
  12. #endif

  13. #if USE_PWM2
  14. #define PWM_SERVO_2 1
  15. #define PWM_SERVO_2_TIMER TIM3
  16. #define PWM_SERVO_2_GPIO GPIOA
  17. #define PWM_SERVO_2_PIN GPIO7
  18. #define PWM_SERVO_2_AF 0
  19. #define PWM_SERVO_2_OC TIM_OC2
  20. #define PWM_SERVO_2_OC_BIT (1<<1)
  21. #else
  22. #define PWM_SERVO_2_OC_BIT 0
  23. #endif

  24. #if USE_PWM3
  25. #define PWM_SERVO_3 2
  26. #define PWM_SERVO_3_TIMER TIM3
  27. #define PWM_SERVO_3_GPIO GPIOB
  28. #define PWM_SERVO_3_PIN GPIO0
  29. #define PWM_SERVO_3_AF 0
  30. #define PWM_SERVO_3_OC TIM_OC3
  31. #define PWM_SERVO_3_OC_BIT (1<<2)
  32. #else
  33. #define PWM_SERVO_3_OC_BIT 0
  34. #endif

  35. #if USE_PWM4
  36. #define PWM_SERVO_4 3
  37. #define PWM_SERVO_4_TIMER TIM3
  38. #define PWM_SERVO_4_GPIO GPIOB
  39. #define PWM_SERVO_4_PIN GPIO1
  40. #define PWM_SERVO_4_AF 0
  41. #define PWM_SERVO_4_OC TIM_OC4
  42. #define PWM_SERVO_4_OC_BIT (1<<3)
  43. #else
  44. #define PWM_SERVO_4_OC_BIT 0
  45. #endif

  46. /* servos 1-4 on TIM3 */
  47. #define PWM_TIM3_CHAN_MASK (PWM_SERVO_1_OC_BIT|PWM_SERVO_2_OC_BIT|PWM_SERVO_3_OC_BIT|PWM_SERVO_4_OC_BIT)

复制代码

  最后,定义一下PWM驱动,并把头文件结束

  1. /* Default actuators driver */
  2. #define DEFAULT_ACTUATORS "subsystems/actuators/actuators_pwm.h"
  3. #define ActuatorDefaultSet(_x,_y) ActuatorPwmSet(_x,_y)
  4. #define ActuatorsDefaultInit() ActuatorsPwmInit()
  5. #define ActuatorsDefaultCommit() ActuatorsPwmCommit()
  6. #endif /* CONFIG_ONENETMINI_H */
复制代码

  把这个头文件放到如下目录
  ~/paparazzi/sw/airborne/boards/onenetmini.h

  另外,在 ~/paparazzi/sw/airborne/arch/stm32下面新建个onenetmini.ld文件,定义一下mcu,主要是RAM和ROM
  1. /* Linker script for OneNetMini (STM32F103CBT6, 128K flash, 20K RAM). */

  2. /* Define memory regions. */
  3. MEMORY
  4. {
  5.         ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
  6.         /* Leaving 2k of space at the end of rom for stored settings */
  7.         rom (rx) : ORIGIN = 0x08000000, LENGTH = 126K
  8. }

  9. /* Include the common ld script. */
  10. INCLUDE libopencm3_stm32f1.ld
复制代码

  这样,OnePilot飞控板的基本信息就已经输入完毕了。
4飞控板的makefile文件


  makefile文件目录 ~/paparazzi/conf/boards/onenetmini.makefile

  先是大概地介绍这个板子的基本信息
  1. BOARD=onenetmini
  2. BOARD_CFG=\"boards/$(BOARD).h\"

  3. ARCH=stm32
  4. $(TARGET).ARCHDIR = $(ARCH)
  5. $(TARGET).LDSCRIPT=$(SRC_ARCH)/onenetmini.ld
复制代码

  接着是烧写方式
  1. # default flash mode is via SWD
  2. # other possibilities: DFU-UTIL, JTAG, SWD, STLINK, SERIAL
  3. FLASH_MODE ?= STLINK
复制代码

  4个LED用来指示什么,现在可以定义了。LED3指示PPM信号输入(来自遥控器),LED4指示姿态解算是否正常,LED5指示GPS是否搜到星并定位,LED2是系统运行灯。
  1. #
  2. # default LED configuration
  3. #
  4. RADIO_CONTROL_LED  ?= 3
  5. BARO_LED           ?= none
  6. AHRS_ALIGNER_LED   ?= 4
  7. GPS_LED            ?= 5
  8. SYS_TIME_LED       ?= 2
复制代码

  串口1作为数传,串口2用于GPS模块间的通讯
  1. #
  2. # default uart configuration
  3. #

  4. MODEM_PORT ?= UART1
  5. MODEM_BAUD ?= B57600

  6. GPS_PORT ?= UART2
  7. GPS_BAUD ?= B38400
复制代码

  PPM设置,我们要使用的是PA01
  1. #
  2. # default PPM input is on PA01
  3. #
  4. RADIO_CONTROL_PPM_PIN ?= PA01
  5. ifeq ($(RADIO_CONTROL_PPM_PIN),$(filter $(RADIO_CONTROL_PPM_PIN),PB_06 PB06 PB6))
  6.   PPM_CONFIG=1
  7. else ifeq ($(RADIO_CONTROL_PPM_PIN),$(filter $(RADIO_CONTROL_PPM_PIN),PA_01 PA01 PA1))
  8.   PPM_CONFIG=2
  9. else
  10. $(error Unknown RADIO_CONTROL_PPM_PIN, configure it to either PA01, PB06)
  11. endif
复制代码

  定义舵机驱动或电调的信号,使用PWM信号
  1. ACTUATORS ?= actuators_pwm
复制代码

  最后,我给出完整的makefile文件,如下所示:
  1. # Hey Emacs, this is a -*- makefile -*-
  2. #
  3. # onenetmini.makefile
  4. #
  5. # http://open.iot.10086.cn/
  6. #

  7. BOARD=onenetmini
  8. BOARD_CFG=\"boards/$(BOARD).h\"

  9. ARCH=stm32
  10. $(TARGET).ARCHDIR = $(ARCH)
  11. $(TARGET).LDSCRIPT=$(SRC_ARCH)/onenetmini.ld

  12. # -----------------------------------------------------------------------

  13. # default flash mode is via SWD
  14. # other possibilities: DFU-UTIL, JTAG, SWD, STLINK, SERIAL
  15. FLASH_MODE ?= STLINK

  16. #
  17. #
  18. # some default values shared between different firmwares
  19. #
  20. #


  21. #
  22. # default LED configuration
  23. #
  24. RADIO_CONTROL_LED  ?= 3
  25. BARO_LED           ?= none
  26. AHRS_ALIGNER_LED   ?= 4
  27. GPS_LED            ?= 5
  28. SYS_TIME_LED       ?= 2


  29. #
  30. # default uart configuration
  31. #

  32. MODEM_PORT ?= UART1
  33. MODEM_BAUD ?= B57600

  34. GPS_PORT ?= UART2
  35. GPS_BAUD ?= B38400

  36. #
  37. # default PPM input is on PA01
  38. #
  39. RADIO_CONTROL_PPM_PIN ?= PA01
  40. ifeq ($(RADIO_CONTROL_PPM_PIN),$(filter $(RADIO_CONTROL_PPM_PIN),PB_06 PB06 PB6))
  41.   PPM_CONFIG=1
  42. else ifeq ($(RADIO_CONTROL_PPM_PIN),$(filter $(RADIO_CONTROL_PPM_PIN),PA_01 PA01 PA1))
  43.   PPM_CONFIG=2
  44. else
  45. $(error Unknown RADIO_CONTROL_PPM_PIN, configure it to either PA01, PB06)
  46. endif

  47. #
  48. # default actuator configuration
  49. #
  50. # you can use different actuators by adding a configure option to your firmware section
  51. # e.g. <configure name="ACTUATORS" value="actuators_ppm/>
  52. # and by setting the correct "driver" attribute in servo section
  53. # e.g. <servo driver="Ppm">
  54. #
  55. ACTUATORS ?= actuators_pwm
复制代码

5 烧写模式设置文件


  在上一节的makefile文件里,有个flash模式的值,定义的是程序烧写方式。

  这个值必须是在飞控地面站的编译配置文件里配置过的,不然地面站编译飞控代码时候会报错。

  地面站有个xml文件,该文件定义了每一种飞控板有几种烧写模式,
  这个文件是~/paparazzi/conf/flash_modes.xml

  其中的一段关于stlink下载器的,需要修改一下。
  
  在STLink模块那段里添加一个board name值,等于onenetmini。如下所示。这样地面站就能给OnePilot下载固件了。
  1. <mode name="STLink (SWD)">
  2.     <variable name="FLASH_MODE" value="STLINK"/>
  3.     <boards>
  4.       <board name="apogee_.*"/>
  5.       <board name="stm32f4_discovery"/>
  6.       <board name="hyper_x"/>
  7.       <board name="onenetmini"/>
  8.       <board name="li[s]?a_mx_.*"/>
  9.       <board name="cc3d"/>
  10.       <board name="elle*"/>
  11.       <board name="naze32*"/>
  12.     </boards>
  13.   </mode>
复制代码

  完整的flash_modes.xml文件如下,替换原来的文件。
  1. <?xml version="1.0"?>

  2. <flash_modes>
  3.   <mode name="SERIAL (ISP)">
  4.     <variable name="FLASH_MODE" value="ISP"/>
  5.     <boards>
  6.       <board name="booz_.*"/>
  7.       <board name="classix"/>
  8.       <board name="hb_.*"/>
  9.       <board name="logom_.*"/>
  10.       <board name="navgo_.*"/>
  11.       <board name="sdlog_.*"/>
  12.       <board name="tiny_.*"/>
  13.       <board name="twog_.*"/>
  14.       <board name="umarim_.*"/>
  15.       <board name="yapa_.*"/>
  16.     </boards>
  17.   </mode>
  18.   <mode name="SERIAL (stm32)">
  19.     <variable name="FLASH_MODE" value="SERIAL"/>
  20.     <boards>
  21.       <board name="krooz_sd"/>
  22.       <board name="lia_.*"/>
  23.       <board name="lisa_[ms]_.*"/>
  24.       <board name="elle*"/>
  25.       <board name="naze32*"/>
  26.     </boards>
  27.   </mode>
  28.   <mode name="USB (IAP)">
  29.     <variable name="FLASH_MODE" value="IAP"/>
  30.     <boards>
  31.       <board name="booz_.*"/>
  32.       <board name="classix"/>
  33.       <board name="hb_.*"/>
  34.       <board name="logom_.*"/>
  35.       <board name="navgo_.*"/>
  36.       <board name="sdlog_.*"/>
  37.       <board name="tiny_.*"/>
  38.       <board name="twog_*"/>
  39.       <board name="umarim_.*"/>
  40.       <board name="yapa_.*"/>
  41.     </boards>
  42.   </mode>
  43.   <mode name="USB DFU (stm32_mem)">
  44.     <variable name="FLASH_MODE" value="DFU"/>
  45.     <boards>
  46.       <board name="krooz_sd"/>
  47.       <board name="li[s]?a_[m]?_.*"/>
  48.       <board name="li[s]?a_mx_.*"/>
  49.       <board name="px4fmu_.*"/>
  50.       <board name="elle*"/>
  51.     </boards>
  52.   </mode>
  53.   <mode name="USB DFU-UTIL">
  54.     <variable name="FLASH_MODE" value="DFU-UTIL"/>
  55.     <boards>
  56.       <board name="apogee_.*"/>
  57.       <board name="stm32f4_discovery"/>
  58.       <board name="hyper_x"/>
  59.       <board name="li[s]?a_mx_.*"/>
  60.       <board name="navstik_.*"/>
  61.       <board name="elle*"/>
  62.     </boards>
  63.   </mode>
  64.   <mode name="STLink (SWD)">
  65.     <variable name="FLASH_MODE" value="STLINK"/>
  66.     <boards>
  67.       <board name="apogee_.*"/>
  68.       <board name="stm32f4_discovery"/>
  69.       <board name="hyper_x"/>
  70.       <board name="onenetmini"/>
  71.       <board name="li[s]?a_mx_.*"/>
  72.       <board name="cc3d"/>
  73.       <board name="elle*"/>
  74.       <board name="naze32*"/>
  75.     </boards>
  76.   </mode>
  77.   <mode name="BlackMagic Probe (SWD)">
  78.     <variable name="FLASH_MODE" value="SWD"/>
  79.     <boards>
  80.       <board name="apogee_.*"/>
  81.       <board name="stm32f4_discovery"/>
  82.       <board name="hyper_x"/>
  83.       <board name="li[s]?a_[ms]?_.*"/>
  84.       <board name="li[s]?a_mx_.*"/>
  85.       <board name="px4fmu_.*"/>
  86.       <board name="cc3d"/>
  87.       <board name="elle*"/>
  88.       <board name="naze32*"/>
  89.       <board name="cjmcu*"/>
  90.     </boards>
  91.   </mode>
  92.   <mode name="BlackMagic Probe (JTAG)">
  93.     <variable name="FLASH_MODE" value="JTAG_BMP"/>
  94.     <boards>
  95.       <board name="apogee_*"/>
  96.       <board name="stm32f4_discovery"/>
  97.       <board name="hyper_x"/>
  98.       <board name="li[s]?a_[ms]?_.*"/>
  99.       <board name="li[s]?a_mx_.*"/>
  100.       <board name="px4fmu_.*"/>
  101.       <board name="elle*"/>
  102.     </boards>
  103.   </mode>
  104.     <mode name="Px4 bootloader">
  105.     <variable name="FLASH_MODE" value="PX4_BOOTLOADER"/>
  106.     <boards>
  107.       <board name="px4fmu_.*"/>
  108.       <board name="px4io_.*"/>
  109.     </boards>
  110.   </mode>
  111.   <mode name="JTAG (OpenOCD)">
  112.     <variable name="FLASH_MODE" value="JTAG"/>
  113.     <boards>
  114.       <board name="krooz_sd"/>
  115.       <board name="li[s]?a_[lm]?_.*"/>
  116.       <board name="navstik_.*"/>
  117.       <board name="elle*"/>
  118.     </boards>
  119.   </mode>
  120. </flash_modes>
复制代码

6 机体配置文件


  在编译飞控固件前,还有一个关键的步骤——机体配置

  机体配置文件是XML格式的,该文件用于飞控程序编译时候连接各个子模块。
  
  前面第4小节里,我们写了飞控板的makefile文件,该文件只是对OnePilot飞控板的核心板OneNetMini做了最基本的编译设置。  
  飞控要完成一个完整的任务,除了底板还需要连接各种算法模块和传感器模块。

  一个飞控底板,可以使用不同的传感器,不同的航姿算法、不同的自稳算法、不同的惯导和导航算法。
  当使用不同的机身时候,因为动力学特性不一样,即使是相同的算法,参数也是不同的。

  
  所以,我们还需要一个机体配置文件(或者叫机身配置文件),英文名叫airframe configuration file,文件格式XML。

  我们一起来写一下机体配置文件。

  先定义飞机的名字。随便取个名字叫onetttt
  1. <airframe name="onetttt">
复制代码

  接着,定义飞机类型,四旋翼飞行器,英文名rotocraft
  1. <firmware name="rotorcraft">
复制代码

  下一步就是定义你的飞控板的核心板。我们前面写板子头文件和makefile文件,目的就是完成飞控核心板OneNetMini的编译设置。现在可以把onenetmini这个飞控底板加到机体配置文件里了。
  我们要做一个飞控(autopilot简称ap),飞控用的核心板是onenetmini,可以如下这么写:
  1. <target name="ap" board="onenetmini">
  2.     </target>
复制代码

  每个自动驾驶仪都具有特定的子系统(subsystem),这些子系统都需要配置正确。
  
  遥控输入信号,使用ppm信号
  1. <subsystem name="radio_control" type="ppm">
  2.     </subsystem>
复制代码

  因为是多旋翼,所以要对多个电机的转速做混控。
  1. <subsystem name="motor_mixing"/>
复制代码

  执行器是电调,飞控使用PWM信号控制电调给电机调速。电调的速度很快,PWM频率可以高一点,400赫兹。
  1. <subsystem name="actuators"     type="pwm">
  2.       <define name="SERVO_HZ" value="400"/>
  3.     </subsystem>
复制代码

  飞控与上位机通讯的方式,使用串口透传
  1. <subsystem name="telemetry"     type="transparent"/>
复制代码

  稳定和姿态控制子系统,基于四元数。是个PID控制器。  PID是个老司机,开飞机很稳,不会翻的。
  四元素系统相对于欧拉角系统,没有奇异点的问题,非常适合做飞机的姿态解算。
  1. <subsystem name="stabilization" type="int_quat"/>
复制代码

  GPS模块,我使用Ublox 6M,所以使用ublox协议通讯
  1. <subsystem name="gps"           type="ublox"/>
复制代码

  飞控测量飞行姿态的传感器叫做惯性测量单元,英文名叫Inertial Measurement Unit,简称IMU。
  我所使用的传感器模块叫做GY-86。该模块连接到OneNetMini的i2c2。
  GY-86集成了一个3轴磁场HMC5883L传感器,一个3轴加速度和3轴陀螺仪传感器MPU6050,和一个气压计MS5611 。
  由于STM32F103RB的flash比较小,只有128KB,飞控本身的算法又挺复杂的,如果磁场传感器也加上的话,flash还差1KB空间,所以这儿只使用MPU6050,而不是整个10DOF。
  1. <subsystem name="imu" type="mpu60x0_i2c">
  2.       <configure name="IMU_MPU60X0_I2C_DEV" value="i2c2"/>
  3.       </subsystem>
复制代码

  然后是航姿参考系统,该系统用于姿态解算,英文名Attitude and Heading Reference System,简称AHRS。
  还是因为MCU的性能原因,卡尔曼滤波(英文名Multiplicative Linearized Kalman Filter in quaternion formulation.)固然很好,但是不适合没有硬件浮点FPU的stm32f103。
  我们使用基于四元数的互补滤波方法。
  另外,因为没有磁场计确定方向,我们使用GPS轨迹来估计飞机机头指向。
  1. <subsystem name="ahrs"          type="int_cmpl_quat">
  2.       <define name="AHRS_USE_GPS_HEADING" value="TRUE"/>
  3.       <define name="AHRS_GRAVITY_HEURISTIC_FACTOR" value="30"/>
  4.     </subsystem>
复制代码

  
  惯性导航系统,英文名Inertial Navigation System,简称INS。
  惯导INS是一种估计飞行器位置和速度的技术,当他与航姿系统AHRS一起使用时,就可以估计飞机实时的姿态、速度和位置。
  因为GPS系统对于水平的位置的分辨率较高但对垂直方向的精度比较低,所以又有很多方法来对飞行器海拔位置做估计。
  常用的有两种:
  1、2状态卡尔曼滤波,融合GPS和气压计数据,估计垂直方向的位置和速度
  2、4状态卡尔曼滤波来估计垂直位置、垂直速度、加速度计偏差和气压补偿


  然而,对于性能局限的stm32f103CB,我们用个稍微简单的方法确定位置和高度。
  直接使用GPS的位置和速度给飞机导航,垂直速度和加速度偏差用个滤波器来估计。
  方法虽然简单粗暴,但是对于移动缓慢的多旋翼飞行器来说也还凑活。
  1. <subsystem name="ins"/>
复制代码

  然后,别忘了把程序里的磁场计接口关掉,因为我们的程序不用它。
  1. <!-- does not use a mag -->
  2.     <configure name="USE_MAGNETOMETER" value="FALSE"/>
  3.     <!-- compress trig tables so it fits in board -->
  4.     <define name="PPRZ_TRIG_INT_COMPR_FLASH"/>
  5.     <define name="PPRZ_TRIG_INT_COMPR_LOW"/>
复制代码

  
  接下来是对各个子模块进行设置
  
  先是程序主循环频率,每秒循环512次
  1. <modules main_freq="512">
  2.   </modules>
复制代码

  然后把4个PWM输出依次对应到4个电调
  1. <servos driver="Pwm">
  2.     <servo name="FL"   no="0" min="1000" neutral="1100" max="2000"/>
  3.     <servo name="FR"   no="1" min="1000" neutral="1100" max="2000"/>
  4.     <servo name="BR"   no="2" min="1000" neutral="1100" max="2000"/>
  5.     <servo name="BL"   no="3" min="1000" neutral="1100" max="2000"/>
  6.   </servos>
复制代码

  定义PWM混控输出方法
  1. <section name="MIXING" prefix="MOTOR_MIXING_">
  2.     <!-- front left (CW), front right (CCW), back right (CW), back left (CCW) -->
  3.     <define name="TYPE" value="QUAD_X"/>
  4.   </section>

  5.   <commands>
  6.     <axis name="PITCH"  failsafe_value="0"/>
  7.     <axis name="ROLL"   failsafe_value="0"/>
  8.     <axis name="YAW"    failsafe_value="0"/>
  9.     <axis name="THRUST" failsafe_value="0"/>
  10.   </commands>

  11.   <command_laws>
  12.     <call fun="motor_mixing_run(autopilot_motors_on,FALSE,values)"/>
  13.     <set servo="FL" value="motor_mixing.commands[MOTOR_FRONT_LEFT]"/>
  14.     <set servo="FR" value="motor_mixing.commands[MOTOR_FRONT_RIGHT]"/>
  15.     <set servo="BR" value="motor_mixing.commands[MOTOR_BACK_RIGHT]"/>
  16.     <set servo="BL" value="motor_mixing.commands[MOTOR_BACK_LEFT]"/>
  17.   </command_laws>
复制代码

  IMU安装角,还有AHRS和INS的参数设置
  1.   <section name="IMU" prefix="IMU_">
  2.     <define name="BODY_TO_IMU_PHI"   value="180." unit="deg"/>
  3.     <define name="BODY_TO_IMU_THETA" value="0." unit="deg"/>
  4.     <define name="BODY_TO_IMU_PSI"   value="-90." unit="deg"/>
  5.   </section>

  6.   <section name="AHRS" prefix="AHRS_">
  7.     <define name="H_X" value="0.3770441"/>
  8.     <define name="H_Y" value="0.0193986"/>
  9.     <define name="H_Z" value="0.9259921"/>
  10.   </section>

  11.   <section name="INS" prefix="INS_">
  12.   </section>
复制代码

  姿态控制参数,角速度限制和姿态稳定PID参数
  这些参数只是刚开始测试时候的初始值,保证飞机能飞起来。
  1. <section name="STABILIZATION_ATTITUDE" prefix="STABILIZATION_ATTITUDE_">
  2.     <!-- setpoints -->
  3.     <define name="SP_MAX_PHI"     value="60." unit="deg"/>
  4.     <define name="SP_MAX_THETA"   value="60." unit="deg"/>
  5.     <define name="SP_MAX_R"       value="90." unit="deg/s"/>
  6.     <define name="DEADBAND_A"     value="0"/>
  7.     <define name="DEADBAND_E"     value="0"/>
  8.     <define name="DEADBAND_R"     value="250"/>

  9.     <!-- reference -->
  10.     <define name="REF_OMEGA_P"  value="400" unit="deg/s"/>
  11.     <define name="REF_ZETA_P"   value="0.85"/>
  12.     <define name="REF_MAX_P"    value="400." unit="deg/s"/>
  13.     <define name="REF_MAX_PDOT" value="RadOfDeg(8000.)"/>

  14.     <define name="REF_OMEGA_Q"  value="400" unit="deg/s"/>
  15.     <define name="REF_ZETA_Q"   value="0.85"/>
  16.     <define name="REF_MAX_Q"    value="400." unit="deg/s"/>
  17.     <define name="REF_MAX_QDOT" value="RadOfDeg(8000.)"/>

  18.     <define name="REF_OMEGA_R"  value="250" unit="deg/s"/>
  19.     <define name="REF_ZETA_R"   value="0.85"/>
  20.     <define name="REF_MAX_R"    value="180." unit="deg/s"/>
  21.     <define name="REF_MAX_RDOT" value="RadOfDeg(1800.)"/>

  22.     <!-- feedback -->
  23.     <define name="PHI_PGAIN"  value="1000"/>
  24.     <define name="PHI_DGAIN"  value="400"/>
  25.     <define name="PHI_IGAIN"  value="200"/>

  26.     <define name="THETA_PGAIN"  value="1000"/>
  27.     <define name="THETA_DGAIN"  value="400"/>
  28.     <define name="THETA_IGAIN"  value="200"/>

  29.     <define name="PSI_PGAIN"  value="500"/>
  30.     <define name="PSI_DGAIN"  value="300"/>
  31.     <define name="PSI_IGAIN"  value="10"/>

  32.     <!-- feedforward -->
  33.     <define name="PHI_DDGAIN"   value="300"/>
  34.     <define name="THETA_DDGAIN" value="300"/>
  35.     <define name="PSI_DDGAIN"   value="300"/>
  36.   </section>
复制代码

  导航PID参数,对垂直和水平方向使用不同的参数。
  1. <section name="GUIDANCE_V" prefix="GUIDANCE_V_">
  2.     <define name="HOVER_KP"    value="150"/>
  3.     <define name="HOVER_KD"    value="80"/>
  4.     <define name="HOVER_KI"    value="20"/>
  5.     <define name="NOMINAL_HOVER_THROTTLE" value="0.5"/>
  6.     <define name="ADAPT_THROTTLE_ENABLED" value="TRUE"/>
  7.   </section>

  8.   <section name="GUIDANCE_H" prefix="GUIDANCE_H_">
  9.     <define name="APPROX_FORCE_BY_THRUST" value="TRUE"/>
  10.     <define name="MAX_BANK" value="30" unit="deg"/>
  11.     <define name="USE_SPEED_REF" value="TRUE"/>
  12.     <define name="PGAIN" value="50"/>
  13.     <define name="DGAIN" value="100"/>
  14.     <define name="AGAIN" value="70"/>
  15.     <define name="IGAIN" value="20"/>
  16.   </section>
复制代码

  最后,贴出完整的XML文件

  1. <!-- this is a quadrotor frame with the  board:
  2.     * Autopilot:   
  3. -->

  4. <airframe name="onetttt">

  5.   <firmware name="rotorcraft">
  6.     <target name="ap" board="onenetmini">
  7.     </target>



  8.     <subsystem name="radio_control" type="ppm">
  9.     </subsystem>
  10.     <subsystem name="motor_mixing"/>
  11.     <subsystem name="actuators"     type="pwm">
  12.       <define name="SERVO_HZ" value="400"/>
  13.     </subsystem>
  14.     <subsystem name="telemetry"     type="transparent"/>
  15.     <subsystem name="stabilization" type="int_quat"/>
  16.     <subsystem name="gps"           type="ublox"/>
  17.     <subsystem name="imu" type="mpu60x0_i2c">
  18.       <configure name="IMU_MPU60X0_I2C_DEV" value="i2c2"/>
  19.       </subsystem>
  20.     <subsystem name="ahrs"          type="int_cmpl_quat">
  21.       <define name="AHRS_USE_GPS_HEADING" value="TRUE"/>
  22.       <define name="AHRS_GRAVITY_HEURISTIC_FACTOR" value="30"/>
  23.     </subsystem>
  24.     <subsystem name="ins"/>

  25.     <!-- does not use a mag -->
  26.     <configure name="USE_MAGNETOMETER" value="FALSE"/>
  27.     <!-- compress trig tables so it fits in board -->
  28.     <define name="PPRZ_TRIG_INT_COMPR_FLASH"/>
  29.     <define name="PPRZ_TRIG_INT_COMPR_LOW"/>
  30.   </firmware>

  31.   <firmware name="test_progs">
  32.     <target name="test_ahrs" board="onenetmini">
  33.       <subsystem name="imu" type="mpu60x0_i2c">
  34.       <configure name="IMU_MPU60X0_I2C_DEV" value="i2c2"/>
  35.       <configure name="USE_MAGNETOMETER" value="FALSE"/>
  36.       </subsystem>
  37.       <subsystem name="ahrs" type="int_cmpl_quat"/>
  38.     </target>
  39.     <target name="test_actuators_pwm" board="onenetmini"/>
  40.   </firmware>

  41.   <modules main_freq="512">
  42.   </modules>

  43.   <servos driver="Pwm">
  44.     <servo name="FL"   no="0" min="1000" neutral="1100" max="2000"/>
  45.     <servo name="FR"   no="1" min="1000" neutral="1100" max="2000"/>
  46.     <servo name="BR"   no="2" min="1000" neutral="1100" max="2000"/>
  47.     <servo name="BL"   no="3" min="1000" neutral="1100" max="2000"/>
  48.   </servos>

  49.   <section name="MIXING" prefix="MOTOR_MIXING_">
  50.     <!-- front left (CW), front right (CCW), back right (CW), back left (CCW) -->
  51.     <define name="TYPE" value="QUAD_X"/>
  52.   </section>

  53.   <commands>
  54.     <axis name="PITCH"  failsafe_value="0"/>
  55.     <axis name="ROLL"   failsafe_value="0"/>
  56.     <axis name="YAW"    failsafe_value="0"/>
  57.     <axis name="THRUST" failsafe_value="0"/>
  58.   </commands>

  59.   <command_laws>
  60.     <call fun="motor_mixing_run(autopilot_motors_on,FALSE,values)"/>
  61.     <set servo="FL" value="motor_mixing.commands[MOTOR_FRONT_LEFT]"/>
  62.     <set servo="FR" value="motor_mixing.commands[MOTOR_FRONT_RIGHT]"/>
  63.     <set servo="BR" value="motor_mixing.commands[MOTOR_BACK_RIGHT]"/>
  64.     <set servo="BL" value="motor_mixing.commands[MOTOR_BACK_LEFT]"/>
  65.   </command_laws>

  66.   <section name="IMU" prefix="IMU_">
  67.     <define name="MAG_X_NEUTRAL" value="22"/>
  68.     <define name="MAG_Y_NEUTRAL" value="-314"/>
  69.     <define name="MAG_Z_NEUTRAL" value="13"/>
  70.     <define name="MAG_X_SENS" value="3.68160078446" integer="16"/>
  71.     <define name="MAG_Y_SENS" value="3.6093630842" integer="16"/>
  72.     <define name="MAG_Z_SENS" value="3.48306842466" integer="16"/>

  73.     <define name="BODY_TO_IMU_PHI"   value="180." unit="deg"/>
  74.     <define name="BODY_TO_IMU_THETA" value="0." unit="deg"/>
  75.     <define name="BODY_TO_IMU_PSI"   value="-90." unit="deg"/>
  76.   </section>

  77.   <section name="AHRS" prefix="AHRS_">
  78.     <define name="H_X" value="0.3770441"/>
  79.     <define name="H_Y" value="0.0193986"/>
  80.     <define name="H_Z" value="0.9259921"/>
  81.   </section>

  82.   <section name="INS" prefix="INS_">
  83.   </section>



  84.   <section name="STABILIZATION_ATTITUDE" prefix="STABILIZATION_ATTITUDE_">
  85.     <!-- setpoints -->
  86.     <define name="SP_MAX_PHI"     value="60." unit="deg"/>
  87.     <define name="SP_MAX_THETA"   value="60." unit="deg"/>
  88.     <define name="SP_MAX_R"       value="90." unit="deg/s"/>
  89.     <define name="DEADBAND_A"     value="0"/>
  90.     <define name="DEADBAND_E"     value="0"/>
  91.     <define name="DEADBAND_R"     value="250"/>

  92.     <!-- reference -->
  93.     <define name="REF_OMEGA_P"  value="400" unit="deg/s"/>
  94.     <define name="REF_ZETA_P"   value="0.85"/>
  95.     <define name="REF_MAX_P"    value="400." unit="deg/s"/>
  96.     <define name="REF_MAX_PDOT" value="RadOfDeg(8000.)"/>

  97.     <define name="REF_OMEGA_Q"  value="400" unit="deg/s"/>
  98.     <define name="REF_ZETA_Q"   value="0.85"/>
  99.     <define name="REF_MAX_Q"    value="400." unit="deg/s"/>
  100.     <define name="REF_MAX_QDOT" value="RadOfDeg(8000.)"/>

  101.     <define name="REF_OMEGA_R"  value="250" unit="deg/s"/>
  102.     <define name="REF_ZETA_R"   value="0.85"/>
  103.     <define name="REF_MAX_R"    value="180." unit="deg/s"/>
  104.     <define name="REF_MAX_RDOT" value="RadOfDeg(1800.)"/>

  105.     <!-- feedback -->
  106.     <define name="PHI_PGAIN"  value="1000"/>
  107.     <define name="PHI_DGAIN"  value="400"/>
  108.     <define name="PHI_IGAIN"  value="200"/>

  109.     <define name="THETA_PGAIN"  value="1000"/>
  110.     <define name="THETA_DGAIN"  value="400"/>
  111.     <define name="THETA_IGAIN"  value="200"/>

  112.     <define name="PSI_PGAIN"  value="500"/>
  113.     <define name="PSI_DGAIN"  value="300"/>
  114.     <define name="PSI_IGAIN"  value="10"/>

  115.     <!-- feedforward -->
  116.     <define name="PHI_DDGAIN"   value="300"/>
  117.     <define name="THETA_DDGAIN" value="300"/>
  118.     <define name="PSI_DDGAIN"   value="300"/>
  119.   </section>

  120.   <section name="GUIDANCE_V" prefix="GUIDANCE_V_">
  121.     <define name="HOVER_KP"    value="150"/>
  122.     <define name="HOVER_KD"    value="80"/>
  123.     <define name="HOVER_KI"    value="20"/>
  124.     <define name="NOMINAL_HOVER_THROTTLE" value="0.5"/>
  125.     <define name="ADAPT_THROTTLE_ENABLED" value="TRUE"/>
  126.   </section>

  127.   <section name="GUIDANCE_H" prefix="GUIDANCE_H_">
  128.     <define name="APPROX_FORCE_BY_THRUST" value="TRUE"/>
  129.     <define name="MAX_BANK" value="30" unit="deg"/>
  130.     <define name="USE_SPEED_REF" value="TRUE"/>
  131.     <define name="PGAIN" value="50"/>
  132.     <define name="DGAIN" value="100"/>
  133.     <define name="AGAIN" value="70"/>
  134.     <define name="IGAIN" value="20"/>
  135.   </section>

  136.   <section name="SIMULATOR" prefix="NPS_">
  137.     <define name="ACTUATOR_NAMES" value="nw_motor, ne_motor, se_motor, sw_motor" type="string[]"/>
  138.     <define name="JSBSIM_MODEL" value="simple_x_quad_ccw" type="string"/>
  139.     <define name="SENSORS_PARAMS" value="nps_sensors_params_default.h" type="string"/>
  140.     <!-- mode switch on joystick channel 5 (axis numbering starting at zero) -->
  141.     <define name="JS_AXIS_MODE" value="4"/>
  142.   </section>

  143.   <section name="AUTOPILOT">
  144.     <define name="MODE_MANUAL" value="AP_MODE_ATTITUDE_DIRECT"/>
  145.     <define name="MODE_AUTO1"  value="AP_MODE_ATTITUDE_Z_HOLD"/>
  146.     <define name="MODE_AUTO2"  value="AP_MODE_NAV"/>
  147.   </section>

  148.   <section name="BAT">
  149.     <define name="CATASTROPHIC_BAT_LEVEL" value="9.3" unit="V"/>
  150.     <define name="CRITIC_BAT_LEVEL" value="9.6" unit="V"/>
  151.     <define name="LOW_BAT_LEVEL" value="9.7" unit="V"/>
  152.     <define name="MAX_BAT_LEVEL" value="12.4" unit="V"/>
  153.   </section>

  154. </airframe>
复制代码

7 环境搭建与固件编译


  前面第3到6节里写的飞控编译的文件可以当做补丁添加到官方源代码目录里。然后,Paparazzi飞控程序就可以支持OneNetMini板子了。
  
  我知道有个小伙伴没有耐心跟着帖子一步步写,所以整理了一下完整的补丁,下载地址
  http://pan.baidu.com/s/1hsPxYte
  解压后,把文件依次按相应路径放到从官方源码路径。

  为了方便大家入门。官方源代码和编译环境我已经在一个虚拟机里给大家配置好了。
  这是个ubuntu虚拟机。开发功能很全的,除了开发paparazzi,还能开发px4飞控呢。
  虚拟机的root密码是ppz。有个ppz用户,密码也是ppz。
  下载地址:
  https://pan.baidu.com/s/1eSLpZAM
  
  paparazzi源代码的目录在虚拟机里的 /home/ppz/paparazzi

  编译和烧写飞控板的方法:
  打开终端,输入su回车,然后输入密码ppz回车,进去管理员账号
  接着,再输入以下代码打开地面站软件
  1. cd /home/ppz/paparazzi
  2. ./paparazzi
复制代码

  打开地面站后,切换到项目MYAC。
  在左边Airframe选项里选择我们第5课提到的那个onettt.xml文件
  其他的诸如飞行计划flight plane,设置Settings,遥控通道配置Radio还有数传通信数据配置Telemetry的选项,如下图设置


  接着,把中间那个Target选项切换到ap,Flash mode选择STLink。
  然后点Clean按钮,
  再点Build按钮,
  如果编译过程没有显示error就可以继续点Upload, 把固件烧写进飞控板。
  至此,飞控程序编译烧写成功。

  其他说明:
  至2017年3月初,ppz最新的代码是5.10版。版本比我调试用的高。
  大家也可以试试最新版的ppz。
  如果要新建一个开发环境,可以在Ubuntu系统下用如下命令一步到位。
  1. sudo add-apt-repository -y ppa:paparazzi-uav/ppa && sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa && sudo apt-get update && \
  2. sudo apt-get -f -y install paparazzi-dev paparazzi-jsbsim gcc-arm-embedded && cd ~ && git clone --origin upstream https://github.com/paparazzi/paparazzi.git && \
  3. cd ~/paparazzi && git remote update -p && \
  4. git checkout -b v5.10 upstream/v5.10 && sudo cp conf/system/udev/rules/*.rules /etc/udev/rules.d/ && sudo udevadm control --reload-rules && \
  5. make && ./paparazzi
复制代码

  运行结束后会打开ppz的地面站。
  最后再打上本小节开头给的补丁即可。
8 OnePilot飞控开发小结

  OnePilot飞控的开发过程非常顺利。因为我并不是从头做一个飞控,而是在PPPZ的开源基础上修改完成的
  硬件上,我只负责做接口规划,然后把各个硬件模块连接起来

  我只是个默默无闻的海边玩耍的宝宝,拾到几个贝壳,然后串起来做了个项链。

  所以,请不要谢我。
  
  如果大家要感谢,请谢谢PPZ团队和中移团队。
  
  当然,我得感谢大家,感谢大家的支持!这篇文章略长,感谢大家的耐心阅读!

  
  来源:本文是原创,也是转载。OnePilot飞控开发最先连载在ickey,相关帖子可以在云汉论坛搜索用户名xukejing得到。








回复

举报

1

主题

5

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 2018-4-17 09:43:59 | 显示全部楼层
谢谢楼主精彩的分享,但下载地址:
  https://pan.baidu.com/s/1eSLpZAM   页面不存在,麻烦楼主再发一个下载地址,谢谢
  
  

2

主题

26

帖子

67

积分

注册会员

Rank: 2

积分
67
发表于 2018-3-6 22:18:17 | 显示全部楼层
厉害了,真棒
董科学

20

主题

858

帖子

1551

积分

金牌会员

Rank: 6Rank: 6

积分
1551
发表于 2017-5-11 09:05:53 | 显示全部楼层
天呐,LZ辛苦了。
厉害厉害,好东西

2

主题

7

帖子

40

积分

新手上路

Rank: 1

积分
40
发表于 2018-2-4 19:08:35 | 显示全部楼层
家具家居军军军军军军军军军

0

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2017-9-24 22:06:21 | 显示全部楼层
楼主辛苦了 精华呀 学习中 谢谢楼主

69

主题

372

帖子

1369

积分

金牌会员

Rank: 6Rank: 6

积分
1369
发表于 2017-5-11 14:11:53 | 显示全部楼层
灰常油菜花又很nice的楼主,做的东西也好棒,迷你板小身材大用处
1、麒麟座开发板交流QQ群:572063260
QQ群目前非常活跃,欢迎大家参与进来,交流,讨论,答疑,解惑~~
2、中移OneNET微信公众号:中移OneNET
关注中移OneNET官方公众号随时掌握最新资讯和活动信息
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表