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.

215 lines
5.5 KiB

  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. /*
  20. * Status LED_GN LED_RT
  21. * No Error, Motor off ON -
  22. * No Error, Motor spinup FAST -
  23. * No Error, Motor running SLOW -
  24. * Current Limit F/S ON
  25. * i2c Timeout ON ON
  26. * Undervoltage OFF SLOW
  27. * Overcurrent (Hard Limit) OFF FAST
  28. * SELFTEST failed FAST FAST (not implemented yet)
  29. * EEPROM invalid SLOW SLOW
  30. */
  31. #include <avr/io.h>
  32. #include <avr/interrupt.h>
  33. #include <avr/sleep.h>
  34. #include "main.h"
  35. #include "blmc.h"
  36. #include "eeprom.h"
  37. #define LED_OFF 0x00
  38. #define LED_SLOW 0x01
  39. #define LED_FAST 0x10
  40. #define LED_ON 0x11
  41. extern struct blmc_ blmc;
  42. static uint8_t led[2];
  43. ISR(TIMER0_OVF_vect)
  44. {
  45. static uint8_t timer0_cnt = 0;
  46. static uint8_t adc_chan = SENSE_CURRENT;
  47. /* Come back in 20ms */
  48. TCNT0 = 0xFF - 156;
  49. /* commutations during last 20ms */
  50. uint16_t diff = blmc.rpm_tmp - blmc.rpm_tmp_old;
  51. blmc.rpm_tmp_old = blmc.rpm_tmp;
  52. if ((blmc.flags & FLAG_RUN_MASK) == (FLAG_PWM_NORMAL | FLAG_COM_NORMAL)) {
  53. /* too few commutations while running -> do a spinup */
  54. if (diff < 0x08) {
  55. blmc.flags &= ~(FLAG_RUN_MASK);
  56. blmc.flags |= FLAG_PWM_SPINUP | FLAG_COM_SPINUP;
  57. }
  58. /* no i2c cmd in the last 20ms */
  59. if (!(blmc.flags & FLAG_I2C_ACTIVE)) {
  60. /* already in i2c timeout, turn off motor */
  61. if (blmc.flags & FLAG_I2C_TIMEOUT)
  62. blmc.pwm = 0;
  63. blmc.flags |= FLAG_I2C_TIMEOUT;
  64. } else {
  65. blmc.flags &= ~FLAG_I2C_TIMEOUT;
  66. }
  67. blmc.flags &= ~FLAG_I2C_ACTIVE;
  68. }
  69. /* set pwm again (adjust current limit) */
  70. setpwm(blmc.pwm);
  71. /* calc rpm every second */
  72. timer0_cnt++;
  73. if (timer0_cnt == 50) {
  74. timer0_cnt = 0;
  75. blmc.rpm = blmc.rpm_tmp;
  76. blmc.rpm_tmp = 0;
  77. }
  78. /* trigger adc by hand when not running */
  79. if (!(blmc.flags & FLAG_COM_NORMAL)) {
  80. trigger_adc(adc_chan);
  81. if (adc_chan == SENSE_CURRENT)
  82. adc_chan = SENSE_VOLTAGE;
  83. else
  84. adc_chan = SENSE_CURRENT;
  85. }
  86. /* led blink timer */
  87. static uint8_t led_timer = 0;
  88. led_timer = (led_timer +1) & 0x1F;
  89. /* green LED */
  90. if (((led[0] == LED_SLOW) && (led_timer & 0x10)) ||
  91. (led[0] == LED_FAST && (led_timer & 0x04)) ||
  92. (led[0] == LED_ON)) {
  93. PORTB |= LED_GN;
  94. } else {
  95. PORTB &= ~LED_GN;
  96. }
  97. /* red LED */
  98. if (((led[1] == LED_SLOW) && !(led_timer & 0x10)) ||
  99. (led[1] == LED_FAST && !(led_timer & 0x04)) ||
  100. (led[1] == LED_ON)) {
  101. PORTB |= LED_RT;
  102. } else {
  103. PORTB &= ~LED_RT;
  104. }
  105. }
  106. int main(void)
  107. {
  108. DDRB = PHASE_H_MASK | LED_RT | LED_GN;
  109. DDRD = PHASE_L_MASK;
  110. PORTB = 0x00;
  111. PORTD = 0x00;
  112. /* timer0: running with F_CPU/1024 */
  113. TCCR0 = (1<<CS02) | (1<<CS00);
  114. /* timer1: running with F_CPU, 8bit Phase Correct PWM (16kHz) */
  115. TCCR1B = (1<<CS10);
  116. TCCR1A = (1<<WGM10);
  117. /* timer2: running with F_CPU, 8bit Phase Correct PWM (16kHz) */
  118. TCCR2 = (1<<WGM20) | (1<<CS20);
  119. /* enable Timer0 OVF Interrupt */
  120. TIMSK = (1<<TOIE0);
  121. /* Enable Analog Comparator Multiplexer */
  122. SFIOR |= (1<<ACME);
  123. /* I2C Init: keep Address from bootloader, Auto ACKs with Interrupts */
  124. TWCR = (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
  125. blmc.flags = 0x00;
  126. if (read_parameters())
  127. blmc.flags |= FLAG_INVALID_EEPROM;
  128. set_sleep_mode(SLEEP_MODE_IDLE);
  129. sei();
  130. while (1) {
  131. uint8_t ledX[2] = { 0x00, 0x00 };
  132. /* get motor status: spinup, running or off */
  133. if (blmc.flags & FLAG_RUN_MASK) {
  134. if (blmc.flags & (FLAG_COM_SPINUP | FLAG_PWM_SPINUP))
  135. ledX[0] = LED_FAST;
  136. else
  137. ledX[0] = LED_SLOW;
  138. } else {
  139. ledX[0] = LED_ON;
  140. }
  141. /* soft errors (current limit, i2c timeout) */
  142. if (blmc.flags & FLAG_SOFTERR_MASK)
  143. ledX[1] = LED_ON;
  144. /* hard errors */
  145. if (blmc.flags & FLAG_HARDERR_MASK) {
  146. if (blmc.flags & FLAG_CURRENT_LIMIT) {
  147. ledX[0] = LED_OFF;
  148. ledX[1] = LED_FAST;
  149. } else if (blmc.flags & FLAG_UNDERVOLTAGE) {
  150. ledX[0] = LED_OFF;
  151. ledX[1] = LED_SLOW;
  152. } else if (blmc.flags & FLAG_SELFTEST_FAILED) {
  153. ledX[0] = LED_FAST;
  154. ledX[1] = LED_FAST;
  155. } else if (blmc.flags & FLAG_INVALID_EEPROM) {
  156. ledX[0] = LED_SLOW;
  157. ledX[1] = LED_SLOW;
  158. }
  159. }
  160. if (!(blmc.flags & (FLAG_SOFTERR_MASK | FLAG_HARDERR_MASK)))
  161. ledX[1] = LED_OFF;
  162. led[0] = ledX[0];
  163. led[1] = ledX[1];
  164. /* do a spinup from main loop (blocking for > 200ms) */
  165. if (blmc.flags & FLAG_COM_SPINUP)
  166. spinup();
  167. sleep_mode();
  168. };
  169. return 0;
  170. }