blmc/main.c

224 lines
5.8 KiB
C
Raw Normal View History

2007-09-20 22:54:11 +02:00
/***************************************************************************
* Copyright (C) 09/2007 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License, *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*
2008-02-17 18:17:28 +01:00
* Status LED_GN LED_RT
* No Error, Motor off ON -
* No Error, Motor spinup FAST -
* No Error, Motor running SLOW -
2008-03-05 17:08:33 +01:00
* Current Limit F/S ON
* i2c Timeout ON ON
2008-02-19 14:52:02 +01:00
* Undervoltage OFF SLOW
* Overcurrent (Hard Limit) OFF FAST
* SELFTEST failed FAST FAST (not implemented yet)
* EEPROM invalid SLOW SLOW
2007-09-20 22:54:11 +02:00
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "main.h"
#include "blmc.h"
2008-02-17 21:38:56 +01:00
#include "eeprom.h"
#define LED_OFF 0x00
#define LED_SLOW 0x01
#define LED_FAST 0x10
#define LED_ON 0x11
2007-09-20 22:54:11 +02:00
extern struct blmc_ blmc;
2008-02-17 18:17:28 +01:00
static uint8_t led[2];
2008-06-21 14:34:57 +02:00
ISR(TIMER1_OVF_vect)
2007-09-20 22:54:11 +02:00
{
2008-06-21 14:34:57 +02:00
static uint8_t rpm_cnt = 0;
2007-09-20 22:54:11 +02:00
static uint8_t adc_chan = SENSE_CURRENT;
/* Come back in 20ms */
2008-06-21 14:34:57 +02:00
TCNT1 = (0xFFFF - 20000);
2007-09-20 22:54:11 +02:00
2008-02-17 18:17:28 +01:00
/* commutations during last 20ms */
uint16_t diff = blmc.rpm_tmp - blmc.rpm_tmp_old;
blmc.rpm_tmp_old = blmc.rpm_tmp;
2007-09-20 22:54:11 +02:00
2008-03-05 17:08:33 +01:00
if ((blmc.flags & FLAG_RUN_MASK) == (FLAG_PWM_NORMAL | FLAG_COM_NORMAL)) {
/* too few commutations while running -> do a spinup */
if (diff < 0x08) {
blmc.flags &= ~(FLAG_RUN_MASK);
blmc.flags |= FLAG_PWM_SPINUP | FLAG_COM_SPINUP;
}
/* no i2c cmd in the last 20ms */
if (!(blmc.flags & FLAG_I2C_ACTIVE)) {
/* already in i2c timeout, turn off motor */
if (blmc.flags & FLAG_I2C_TIMEOUT)
blmc.pwm = 0;
blmc.flags |= FLAG_I2C_TIMEOUT;
} else {
blmc.flags &= ~FLAG_I2C_TIMEOUT;
}
2008-06-21 14:34:57 +02:00
// TODO: currently disabled
// blmc.flags &= ~FLAG_I2C_ACTIVE;
2008-02-19 15:59:59 +01:00
}
2007-09-20 22:54:11 +02:00
2008-02-17 18:17:28 +01:00
/* set pwm again (adjust current limit) */
setpwm(blmc.pwm);
2008-02-17 15:54:43 +01:00
/* calc rpm every second */
2008-06-21 14:34:57 +02:00
rpm_cnt++;
if (rpm_cnt == 50) {
rpm_cnt = 0;
2007-09-20 22:54:11 +02:00
blmc.rpm = blmc.rpm_tmp;
blmc.rpm_tmp = 0;
}
/* trigger adc by hand when not running */
if (!(blmc.flags & FLAG_COM_NORMAL)) {
trigger_adc(adc_chan);
if (adc_chan == SENSE_CURRENT)
adc_chan = SENSE_VOLTAGE;
else
adc_chan = SENSE_CURRENT;
}
2008-02-17 18:17:28 +01:00
/* led blink timer */
static uint8_t led_timer = 0;
led_timer = (led_timer +1) & 0x1F;
/* green LED */
if (((led[0] == LED_SLOW) && (led_timer & 0x10)) ||
(led[0] == LED_FAST && (led_timer & 0x04)) ||
(led[0] == LED_ON)) {
PORTB |= LED_GN;
} else {
PORTB &= ~LED_GN;
}
/* red LED */
if (((led[1] == LED_SLOW) && !(led_timer & 0x10)) ||
(led[1] == LED_FAST && !(led_timer & 0x04)) ||
(led[1] == LED_ON)) {
PORTB |= LED_RT;
} else {
PORTB &= ~LED_RT;
}
2007-09-20 22:54:11 +02:00
}
2008-06-21 15:40:07 +02:00
/*
* For newer devices (mega88) the watchdog timer remains active even after a
* system reset. So disable it as soon as possible.
* automagically called on startup
*/
void get_mcusr(void) __attribute__((naked, section(".init3")));
void get_mcusr(void)
{
MCUSR = 0;
WDTCSR = (1<<WDCE) | (0<<WDE);
}
2007-09-20 22:54:11 +02:00
int main(void)
{
2008-06-21 14:34:57 +02:00
DDRB = PHASE_A_EN | PHASE_A_PWM | LED_RT | LED_GN;
DDRD = PHASE_B_EN | PHASE_B_PWM | PHASE_C_EN | PHASE_C_PWM;
2007-09-20 22:54:11 +02:00
2008-02-17 18:17:28 +01:00
PORTB = 0x00;
2007-09-20 22:54:11 +02:00
PORTD = 0x00;
2008-06-21 14:34:57 +02:00
/* timer0: running with F_CPU, 8bit Phase Correct PWM (16kHz) */
TCCR0A = (1<<WGM00);
TCCR0B = (1<<CS00);
2007-09-20 22:54:11 +02:00
2008-06-21 14:34:57 +02:00
/* timer1: running with F_CPU/8 */
TCCR1B = (1<<CS11);
2007-09-20 22:54:11 +02:00
2007-10-05 23:17:55 +02:00
/* timer2: running with F_CPU, 8bit Phase Correct PWM (16kHz) */
2008-06-21 14:34:57 +02:00
TCCR2A = (1<<WGM20);
TCCR2B = (1<<CS20);
2007-09-20 22:54:11 +02:00
2008-06-21 14:34:57 +02:00
/* enable Timer1 OVF Interrupt */
TIMSK1 = (1<<TOIE1);
2007-09-20 22:54:11 +02:00
/* Enable Analog Comparator Multiplexer */
2008-06-21 14:34:57 +02:00
ADCSRB |= (1<<ACME);
2007-09-20 22:54:11 +02:00
/* I2C Init: keep Address from bootloader, Auto ACKs with Interrupts */
TWCR = (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
2008-02-17 18:17:28 +01:00
blmc.flags = 0x00;
2008-02-19 14:52:02 +01:00
if (read_parameters())
2008-03-05 17:08:33 +01:00
blmc.flags |= FLAG_INVALID_EEPROM;
2008-02-17 18:17:28 +01:00
2007-09-20 22:54:11 +02:00
sei();
while (1) {
2008-02-19 14:52:02 +01:00
uint8_t ledX[2] = { 0x00, 0x00 };
2008-02-17 18:17:28 +01:00
/* get motor status: spinup, running or off */
if (blmc.flags & FLAG_RUN_MASK) {
if (blmc.flags & (FLAG_COM_SPINUP | FLAG_PWM_SPINUP))
2008-02-19 14:52:02 +01:00
ledX[0] = LED_FAST;
2008-02-17 18:17:28 +01:00
else
2008-02-19 14:52:02 +01:00
ledX[0] = LED_SLOW;
2008-02-17 18:17:28 +01:00
} else {
2008-02-19 14:52:02 +01:00
ledX[0] = LED_ON;
2008-02-17 18:17:28 +01:00
}
/* soft errors (current limit, i2c timeout) */
if (blmc.flags & FLAG_SOFTERR_MASK)
2008-02-19 14:52:02 +01:00
ledX[1] = LED_ON;
2008-02-17 18:17:28 +01:00
/* hard errors */
if (blmc.flags & FLAG_HARDERR_MASK) {
2008-03-05 17:08:33 +01:00
if (blmc.flags & FLAG_CURRENT_LIMIT) {
2008-02-19 14:52:02 +01:00
ledX[0] = LED_OFF;
ledX[1] = LED_FAST;
2008-02-17 18:17:28 +01:00
} else if (blmc.flags & FLAG_UNDERVOLTAGE) {
2008-02-19 14:52:02 +01:00
ledX[0] = LED_OFF;
ledX[1] = LED_SLOW;
2008-02-17 18:17:28 +01:00
2008-03-05 17:08:33 +01:00
} else if (blmc.flags & FLAG_SELFTEST_FAILED) {
2008-02-19 14:52:02 +01:00
ledX[0] = LED_FAST;
ledX[1] = LED_FAST;
2008-03-05 17:08:33 +01:00
} else if (blmc.flags & FLAG_INVALID_EEPROM) {
2008-02-19 14:52:02 +01:00
ledX[0] = LED_SLOW;
ledX[1] = LED_SLOW;
2008-02-17 18:17:28 +01:00
}
}
2008-02-17 21:38:56 +01:00
if (!(blmc.flags & (FLAG_SOFTERR_MASK | FLAG_HARDERR_MASK)))
2008-02-19 14:52:02 +01:00
ledX[1] = LED_OFF;
led[0] = ledX[0];
led[1] = ledX[1];
2008-02-17 21:38:56 +01:00
2008-02-17 18:17:28 +01:00
/* do a spinup from main loop (blocking for > 200ms) */
2007-09-20 22:54:11 +02:00
if (blmc.flags & FLAG_COM_SPINUP)
spinup();
};
return 0;
}