ARM7 based quadrocopter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

265 lines
9.1KB

  1. /***************************************************************************
  2. * sam7fc - Flight Control *
  3. * *
  4. * Copyright (C) 03/2008 by Olaf Rempel *
  5. * razzor@kopf-tisch.de *
  6. * *
  7. * This program is free software; you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation; version 2 of the License *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with this program; if not, write to the *
  18. * Free Software Foundation, Inc., *
  19. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  20. ***************************************************************************/
  21. #include <stdio.h>
  22. #include <stdlib.h> /* abs() */
  23. #include "AT91SAM7S256.h"
  24. #include "board.h"
  25. #include <at91_adc.h>
  26. #include <at91_pitc.h>
  27. #include <at91_tc1.h>
  28. #include <at91_twi.h>
  29. #include <telemetrie.h>
  30. #include <pidctrl.h>
  31. static uint32_t global_state;
  32. #define MOTOR_RUNNING 0x0001
  33. #define MOTOR_MIXER_ENABLE 0x0002
  34. #define STICK_CALIBRATION 0x0004
  35. #define STICK_CALIBRATION_COMPLETE 0x0008
  36. static struct pid_data pid_nick = {
  37. .kp = 1,
  38. .ki = 0,
  39. .err_sum_max = +1024,
  40. .err_sum_min = -1024,
  41. .out_max = +256,
  42. .out_min = -256,
  43. };
  44. TDC_PTR(pid_nick_ki, &pid_nick.ki, "flctrl: pid nick ki", int32_t, TDC_SIGNED);
  45. TDC_PTR(pid_nick_errsum, &pid_nick.err_sum, "flctrl: pid nick errsum", int32_t, TDC_SIGNED | TDC_READONLY);
  46. static struct pid_data pid_roll = {
  47. .kp = 1,
  48. .ki = 0,
  49. .err_sum_max = +1024,
  50. .err_sum_min = -1024,
  51. .out_max = +256,
  52. .out_min = -256,
  53. };
  54. TDC_PTR(pid_roll_ki, &pid_roll.ki, "flctrl: pid roll ki", int32_t, TDC_SIGNED);
  55. TDC_PTR(pid_roll_errsum, &pid_roll.err_sum, "flctrl: pid roll errsum", int32_t, TDC_SIGNED | TDC_READONLY);
  56. static struct pid_data pid_gier = {
  57. .kp = 1,
  58. .ki = 0,
  59. .err_sum_max = +1024,
  60. .err_sum_min = -1024,
  61. .out_max = +256,
  62. .out_min = -256,
  63. };
  64. TDC_PTR(pid_gier_ki, &pid_gier.ki, "flctrl: pid gier ki", int32_t, TDC_SIGNED);
  65. TDC_PTR(pid_gier_errsum, &pid_gier.err_sum, "flctrl: pid gier errsum", int32_t, TDC_SIGNED | TDC_READONLY);
  66. static void motor_mixer(int32_t gas, int32_t nick, int32_t roll, int32_t gier)
  67. {
  68. static uint8_t pwm[4];
  69. TDC_VALUE(pwm0, pwm[0], "Motor PWM 1", uint8_t, TDC_UNSIGNED | TDC_READONLY);
  70. TDC_VALUE(pwm1, pwm[1], "Motor PWM 2", uint8_t, TDC_UNSIGNED | TDC_READONLY);
  71. TDC_VALUE(pwm2, pwm[2], "Motor PWM 3", uint8_t, TDC_UNSIGNED | TDC_READONLY);
  72. TDC_VALUE(pwm3, pwm[3], "Motor PWM 4", uint8_t, TDC_UNSIGNED | TDC_READONLY);
  73. pwm[0] = LIMIT((gas - nick + gier), 0x0F, 0xFF);
  74. pwm[1] = LIMIT((gas + nick + gier), 0x0F, 0xFF);
  75. pwm[2] = LIMIT((gas + roll - gier), 0x0F, 0xFF);
  76. pwm[3] = LIMIT((gas - roll - gier), 0x0F, 0xFF);
  77. if (!(global_state & MOTOR_RUNNING)) {
  78. pwm[0] = 0x00;
  79. pwm[1] = 0x00;
  80. pwm[2] = 0x00;
  81. pwm[3] = 0x00;
  82. } else if (!(global_state & MOTOR_MIXER_ENABLE)) {
  83. pwm[0] = 0x0F;
  84. pwm[1] = 0x0F;
  85. pwm[2] = 0x0F;
  86. pwm[3] = 0x0F;
  87. }
  88. twi_setpwm(pwm);
  89. }
  90. static uint32_t base_ctrl_cb(struct pitc_timer *timer)
  91. {
  92. if (global_state & STICK_CALIBRATION)
  93. global_state |= STICK_CALIBRATION_COMPLETE;
  94. return PITC_REMOVE_TIMER;
  95. }
  96. static struct pitc_timer base_ctrl_timer = {
  97. .func = base_ctrl_cb,
  98. };
  99. void base_ctrl(void)
  100. {
  101. static int32_t nick_integral, roll_integral, gier_integral;
  102. /* get stick switches & values */
  103. struct rc_values rc_sw;
  104. uint32_t count = rcontrol_getswitches(&rc_sw);
  105. if (count < 4) {
  106. global_state &= ~MOTOR_RUNNING;
  107. } else if (global_state & STICK_CALIBRATION_COMPLETE) {
  108. // rcontrol_calibrate(RC_CAL_END);
  109. // rcontrol_calibrate(RC_CAL_SAVE);
  110. rcontrol_print_cal();
  111. global_state &= ~(STICK_CALIBRATION | STICK_CALIBRATION_COMPLETE);
  112. } else if (global_state & STICK_CALIBRATION) {
  113. /* do nothing during calibration */
  114. } else if (count >= 4) {
  115. /* Motor stop */
  116. if (rc_sw.chan[2] < 0 && rc_sw.chan[3] > 0)
  117. global_state &= ~MOTOR_RUNNING;
  118. /* Motor start */
  119. if (rc_sw.chan[2] < 0 && rc_sw.chan[3] < 0)
  120. global_state |= MOTOR_RUNNING;
  121. /* Gyro calibration */
  122. if (rc_sw.chan[2] > 0 && rc_sw.chan[3] > 0)
  123. adc_calibrate(ADC_CAL_GYRO);
  124. /* ACC + Stick calibration */
  125. if (rc_sw.chan[2] > 0 && rc_sw.chan[3] < 0) {
  126. adc_calibrate(ADC_CAL_ACC);
  127. // rcontrol_calibrate(RC_CAL_START);
  128. global_state |= STICK_CALIBRATION;
  129. base_ctrl_timer.interval = 1000;
  130. pitc_schedule_timer(&base_ctrl_timer);
  131. }
  132. }
  133. struct rc_values rc;
  134. rcontrol_getvalues(&rc);
  135. if (rc.chan[2] < 15) {
  136. global_state &= ~MOTOR_MIXER_ENABLE;
  137. /* reset integrals */
  138. nick_integral = roll_integral = gier_integral = 0;
  139. pid_nick.err_sum = pid_roll.err_sum = pid_gier.err_sum = 0;
  140. } else {
  141. global_state |= MOTOR_MIXER_ENABLE;
  142. }
  143. /* get adc results */
  144. static int16_t adc_result[7];
  145. TDC_PTR(adc_result0, &adc_result[ADC_GYRO_NICK], "ADC_GYRO_NICK", int16_t, TDC_SIGNED | TDC_READONLY);
  146. TDC_PTR(adc_result1, &adc_result[ADC_GYRO_ROLL], "ADC_GYRO_ROLL", int16_t, TDC_SIGNED | TDC_READONLY);
  147. TDC_PTR(adc_result2, &adc_result[ADC_GYRO_GIER], "ADC_GYRO_GIER", int16_t, TDC_SIGNED | TDC_READONLY);
  148. TDC_PTR(adc_result3, &adc_result[ADC_ACC_NICK], "ADC_ACC_NICK", int16_t, TDC_SIGNED | TDC_READONLY);
  149. TDC_PTR(adc_result4, &adc_result[ADC_ACC_ROLL], "ADC_ACC_ROLL", int16_t, TDC_SIGNED | TDC_READONLY);
  150. TDC_PTR(adc_result5, &adc_result[ADC_ACC_GIER], "ADC_ACC_GIER", int16_t, TDC_SIGNED | TDC_READONLY);
  151. TDC_PTR(adc_result6, &adc_result[ADC_VOLTAGE], "ADC_VOLTAGE", int16_t, TDC_SIGNED | TDC_READONLY);
  152. adc_get_results(adc_result);
  153. if (count != 0 && adc_result[ADC_VOLTAGE] > 960)
  154. *AT91C_PIOA_CODR = LED_GREEN;
  155. else
  156. *AT91C_PIOA_SODR = LED_GREEN;
  157. nick_integral += adc_result[ADC_GYRO_NICK];
  158. TDC_INT32(nick_integral, "flctrl: Base Integral Nick");
  159. roll_integral += adc_result[ADC_GYRO_ROLL];
  160. TDC_INT32(roll_integral, "flctrl: Base Integral Roll");
  161. gier_integral += adc_result[ADC_GYRO_GIER];
  162. TDC_INT32(gier_integral, "flctrl: Base Integral Gier");
  163. static int32_t integral_gyro_mix = 1;
  164. TDC_INT32(integral_gyro_mix, "flctrl: Mix Integral/ACC (0-1024)");
  165. static int32_t acc_faktor = 300;
  166. TDC_INT32(acc_faktor, "flctrl: Mix Faktor");
  167. /*
  168. * 90° -> ADC_ACC_* ~210
  169. * 90° -> Integral ~60000
  170. */
  171. int32_t mix_integral = 1024 - integral_gyro_mix;
  172. int32_t mix_acc = integral_gyro_mix * acc_faktor;
  173. nick_integral = ((nick_integral * mix_integral) + (adc_result[ADC_ACC_NICK] * mix_acc)) / 1024;
  174. roll_integral = ((roll_integral * mix_integral) + (adc_result[ADC_ACC_ROLL] * mix_acc)) / 1024;
  175. /*
  176. * hoher gyro_faktor -> bessere stabilität, aber langsames zurückkehren nach vollausschlag
  177. * niedriger integral_faktor -> geringere abweichungbei einseitigem anheben, aber schwingungsanfälliger
  178. */
  179. static int32_t integral_faktor = 256;
  180. static int32_t gyro_faktor = 4;
  181. TDC_INT32(integral_faktor, "flctrl: Integral Divisior");
  182. TDC_INT32(gyro_faktor, "flctrl: Integral Gyro Faktor /16");
  183. static int32_t nick;
  184. static int32_t roll;
  185. static int32_t gier;
  186. nick = (nick_integral / integral_faktor) + (adc_result[ADC_GYRO_NICK] * gyro_faktor) / 16;
  187. roll = (roll_integral / integral_faktor) + (adc_result[ADC_GYRO_ROLL] * gyro_faktor) / 16;
  188. gier = (gier_integral / integral_faktor) + (adc_result[ADC_GYRO_GIER] * gyro_faktor) / 16;
  189. TDC_INT32_RO(nick, "flctrl: Integral + Gyro Nick");
  190. TDC_INT32_RO(roll, "flctrl: Integral + Gyro Roll");
  191. TDC_INT32_RO(gier, "flctrl: Integral + Gyro Gier");
  192. static int32_t stick_kp = 8;
  193. TDC_INT32(stick_kp, "flctrl: Stick-P /16");
  194. static int32_t stick_gas, stick_nick, stick_roll, stick_gier;
  195. stick_gas = rc.chan[2];
  196. stick_nick = (rc.chan[0] * stick_kp) / 16;
  197. stick_roll = (rc.chan[1] * stick_kp) / 16;
  198. stick_gier = rc.chan[3] / 4;
  199. TDC_INT32_RO(stick_gas, "Stick Gas");
  200. TDC_INT32_RO(stick_nick, "Stick Nick");
  201. TDC_INT32_RO(stick_roll, "Stick Roll");
  202. TDC_INT32_RO(stick_gier, "Stick Gier");
  203. static int32_t gier_kp = 32;
  204. TDC_INT32(gier_kp, "flctrl: Gier-P (/256)");
  205. gier_integral -= gier_kp * stick_gier * abs(stick_gier) / 256;
  206. static int32_t mixer_gas, mixer_nick, mixer_roll, mixer_gier;
  207. mixer_gas = stick_gas;
  208. mixer_nick = pid_ctrl(&pid_nick, stick_nick - nick);
  209. mixer_roll = pid_ctrl(&pid_roll, stick_roll - roll);
  210. mixer_gier = pid_ctrl(&pid_gier, stick_gier - gier);
  211. /* mix gas/nick/roll/gier -> 4 motors */
  212. motor_mixer(mixer_gas, mixer_nick, mixer_roll, mixer_gier);
  213. TDC_INT32_RO(mixer_gas, "Mixer Gas");
  214. TDC_INT32_RO(mixer_nick, "Mixer Nick");
  215. TDC_INT32_RO(mixer_roll, "Mixer Roll");
  216. TDC_INT32_RO(mixer_gier, "Mixer Gier");
  217. }