AVR based brushless motor controller
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.

262 lines
6.3 KiB

14 years ago
14 years ago
14 years ago
14 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
13 years ago
14 years ago
14 years ago
13 years ago
14 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
13 years ago
14 years ago
14 years ago
14 years ago
14 years ago
  1. /***************************************************************************
  2. * Copyright (C) 09/2007 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License, *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <avr/io.h>
  20. #include <avr/interrupt.h>
  21. #include "main.h"
  22. #include "blmc.h"
  23. #include "eeprom.h"
  24. extern struct ee_param params;
  25. struct blmc_ blmc;
  26. /* Analog Comparator Channel */
  27. static uint8_t next_sense;
  28. void trigger_adc(uint8_t channel)
  29. {
  30. /* Disable Analog Comperator */
  31. ACSR &= ~(1<<ACIE);
  32. /* set channel (Internal reference, 2.56V) */
  33. ADMUX = (1<<REFS1) | (1<<REFS0) | channel;
  34. /* turn on ADC with interrupts, start conversion with 1/32 of F_CPU */
  35. ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADIE) | (1<<ADIF)| (1<<ADPS2) | (1<<ADPS0);
  36. }
  37. void next_phase(void)
  38. {
  39. static uint8_t phase;
  40. static uint8_t phase_adc;
  41. /* Disable Analog Comperator */
  42. ACSR &= ~(1<<ACIE);
  43. TCNT1 = 0x00;
  44. TCNT2 = 0x00;
  45. switch (phase) {
  46. case 0: PORTD = (PORTD & ~PHASE_L_MASK) | PHASE_B_L;
  47. TCCR1A = (TCCR1A & ~(1<<COM1B1)) | (1<<COM1A1);
  48. TCCR2 &= ~(1<<COM21);
  49. ACSR = (1<<ACIS1);
  50. next_sense = SENSE_C;
  51. break;
  52. case 1: PORTD = (PORTD & ~PHASE_L_MASK) | PHASE_B_L;
  53. TCCR1A &= ~((1<<COM1A1) | (1<<COM1B1));
  54. TCCR2 |= (1<<COM21);
  55. ACSR = (1<<ACIS1) | (1<<ACIS0);
  56. next_sense = SENSE_A;
  57. break;
  58. case 2: PORTD = (PORTD & ~PHASE_L_MASK) | PHASE_A_L;
  59. TCCR1A &= ~((1<<COM1A1) | (1<<COM1B1));
  60. TCCR2 |= (1<<COM21);
  61. ACSR = (1<<ACIS1);
  62. next_sense = SENSE_B;
  63. break;
  64. case 3: PORTD = (PORTD & ~PHASE_L_MASK) | PHASE_A_L;
  65. TCCR1A = (TCCR1A & ~(1<<COM1A1)) | (1<<COM1B1);
  66. TCCR2 &= ~(1<<COM21);
  67. ACSR = (1<<ACIS1) | (1<<ACIS0);
  68. next_sense = SENSE_C;
  69. break;
  70. case 4: PORTD = (PORTD & ~PHASE_L_MASK) | PHASE_C_L;
  71. TCCR1A = (TCCR1A & ~(1<<COM1A1)) | (1<<COM1B1);
  72. TCCR2 &= ~(1<<COM21);
  73. ACSR = (1<<ACIS1);
  74. next_sense = SENSE_A;
  75. break;
  76. case 5: PORTD = (PORTD & ~PHASE_L_MASK) | PHASE_C_L;
  77. TCCR1A = (TCCR1A & ~(1<<COM1B1)) | (1<<COM1A1);
  78. TCCR2 &= ~(1<<COM21);
  79. ACSR = (1<<ACIS1) | (1<<ACIS0);
  80. next_sense = SENSE_B;
  81. break;
  82. }
  83. if (phase == (phase_adc & 0x0F)) {
  84. if (phase_adc & 0x10)
  85. trigger_adc(SENSE_VOLTAGE);
  86. else
  87. trigger_adc(SENSE_CURRENT);
  88. phase_adc--;
  89. if (phase_adc == 0xff)
  90. phase_adc = 0x15;
  91. else if (phase_adc == 0x0f)
  92. phase_adc = 0x05;
  93. } else {
  94. /* restore channel */
  95. ADMUX = next_sense;
  96. /* enable Analog Comparator with Interrupts */
  97. if (blmc.flags & FLAG_COM_NORMAL)
  98. ACSR |= (1<<ACIE) | (1<<ACI);
  99. }
  100. phase++;
  101. if (phase == 6)
  102. phase = 0;
  103. blmc.rpm_tmp++;
  104. }
  105. /*
  106. * starts motor, must not run from interrupt
  107. */
  108. void spinup(void)
  109. {
  110. /* see util/delay.h for details.. */
  111. uint16_t tick = (((uint16_t)(F_CPU / 3e6)) << 8) * (params.spinup_tick & 0x3F);
  112. uint16_t time = params.spinup_ticks;
  113. while (time > 50) {
  114. next_phase();
  115. uint16_t i;
  116. for (i = 0; i < time; i++)
  117. _delay_loop_1(tick >> 8);
  118. time -= (time / params.spinup_step +1);
  119. }
  120. /* manual spinup complete, analog comperator takes control */
  121. blmc.flags &= ~(FLAG_RUN_MASK);
  122. blmc.flags |= FLAG_PWM_SPINUP | FLAG_COM_NORMAL;
  123. next_phase();
  124. for (time = 0; time < params.spinup_wait; time++)
  125. _delay_ms(20);
  126. /* switch to desired pwm value */
  127. blmc.flags &= ~(FLAG_RUN_MASK);
  128. blmc.flags |= FLAG_PWM_NORMAL | FLAG_COM_NORMAL;
  129. }
  130. /*
  131. * sets new pwm value
  132. * called from i2c-slave (set new value) and from timer (recalc current limit)
  133. */
  134. void setpwm(uint8_t pwm)
  135. {
  136. /* run motor *only* if there are no hard errors */
  137. if (pwm >= params.pwm_min && !(blmc.flags & FLAG_HARDERR_MASK)) {
  138. /* do a spinup */
  139. if (blmc.pwm == 0) {
  140. blmc.flags &= ~(FLAG_RUN_MASK);
  141. blmc.flags |= FLAG_PWM_SPINUP | FLAG_COM_SPINUP;
  142. }
  143. } else {
  144. blmc.flags &= ~FLAG_RUN_MASK;
  145. pwm = 0;
  146. }
  147. /* save pwm value */
  148. blmc.pwm = pwm;
  149. /* do spinup with small pwm */
  150. if (blmc.flags & FLAG_PWM_SPINUP)
  151. pwm = params.spinup_pwm;
  152. /* raise current-limit, set flag */
  153. if (blmc.current > params.current_limit) {
  154. blmc.flags |= FLAG_CURRENT_LIMIT;
  155. blmc.pwm_limit++;
  156. /* lower current-limit */
  157. } else if (blmc.pwm_limit > 0) {
  158. blmc.pwm_limit--;
  159. } else if (blmc.pwm_limit == 0) {
  160. blmc.flags &= ~FLAG_CURRENT_LIMIT;
  161. }
  162. /* prevent overflow */
  163. if (blmc.pwm_limit > pwm)
  164. blmc.pwm_limit = pwm;
  165. /* set new value */
  166. pwm -= blmc.pwm_limit;
  167. /* limit pwm */
  168. if (pwm > params.pwm_max)
  169. pwm = params.pwm_max;
  170. OCR1A = pwm;
  171. OCR1B = pwm;
  172. OCR2 = pwm;
  173. }
  174. ISR(ANA_COMP_vect)
  175. {
  176. next_phase();
  177. }
  178. ISR(ADC_vect)
  179. {
  180. static uint16_t current_tmp, voltage_tmp;
  181. static uint8_t current_cnt, voltage_cnt;
  182. uint8_t channel = ADMUX & 0x0F;
  183. uint16_t value = ADCW;
  184. /* restore channel */
  185. ADMUX = next_sense;
  186. /* turn off ADC, disable interrupt */
  187. ADCSRA = 0x00;
  188. /* enable Analog Comparator with Interrupts */
  189. if (blmc.flags & FLAG_COM_NORMAL)
  190. ACSR |= (1<<ACIE) | (1<<ACI);
  191. if (channel == SENSE_CURRENT) {
  192. current_tmp += value;
  193. current_cnt++;
  194. if (current_cnt == 6) {
  195. blmc.current = current_tmp;
  196. current_tmp = 0;
  197. current_cnt = 0;
  198. }
  199. if (value > params.current_max)
  200. blmc.flags |= FLAG_OVERCURRENT;
  201. } else {
  202. voltage_tmp += value;
  203. voltage_cnt++;
  204. if (voltage_cnt == 6) {
  205. blmc.voltage = voltage_tmp;
  206. voltage_tmp = 0;
  207. voltage_cnt = 0;
  208. if (blmc.voltage < params.voltage_min)
  209. blmc.flags |= FLAG_UNDERVOLTAGE;
  210. }
  211. }
  212. }