From eea082635e07c462584c4ac58d411743431aaa52 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Thu, 20 Sep 2007 22:54:11 +0200 Subject: [PATCH] init --- .gitignore | 6 ++ Makefile | 64 +++++++++++++++ blmc.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++ blmc.h | 47 +++++++++++ i2c-slave.c | 130 ++++++++++++++++++++++++++++++ main.c | 114 ++++++++++++++++++++++++++ main.h | 12 +++ 7 files changed, 599 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 blmc.c create mode 100644 blmc.h create mode 100644 i2c-slave.c create mode 100644 main.c create mode 100644 main.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d36148 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +*.elf +*.bin +*.hex +*.lst +*.map diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d7e3aaa --- /dev/null +++ b/Makefile @@ -0,0 +1,64 @@ +PRG = bl_test +OBJ = blmc.o i2c-slave.o main.o +MCU_TARGET = atmega8 +OPTIMIZE = -Os + +DEFS = +LIBS = + +# You should not have to change anything below here. + +CC = avr-gcc + +# Override is only needed by avr-lib build system. + +override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) +override LDFLAGS = -Wl,-Map,$(PRG).map + +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size + +all: $(PRG).elf lst text eeprom + $(SIZE) -x -A $(PRG).elf + +$(PRG).elf: $(OBJ) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + rm -rf *.o *.lst *.map $(PRG).elf *.hex *.bin + +lst: $(PRG).lst + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +# Rules for building the .text rom images + +text: hex bin + +hex: $(PRG).hex +bin: $(PRG).bin + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ + +# Rules for building the .eeprom rom images + +eeprom: ehex ebin + +ehex: $(PRG)_eeprom.hex +ebin: $(PRG)_eeprom.bin + +%_eeprom.hex: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ + +%_eeprom.bin: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ + +install: text + uisp -dprog=avr910 -dserial=/dev/ttyS0 -dspeed=115200 -dpart=M8 --erase --upload if=$(PRG).hex +# avrdude -p m8 -c butterfly -b 19200 -P /dev/ttyUSB0 -u -e -V -U flash:w:$(PRG).hex diff --git a/blmc.c b/blmc.c new file mode 100644 index 0000000..d1ee713 --- /dev/null +++ b/blmc.c @@ -0,0 +1,226 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#include +#include + +#include "main.h" +#include "blmc.h" + +struct blmc_ blmc; + +static uint8_t next_sense; + +void trigger_adc(uint8_t channel) +{ + /* Disable Analog Comperator */ + ACSR &= ~(1< 50) { + next_phase(); + + uint16_t i; + for (i = 0; i < time; i++) + _delay_us(25); + + time -= (time / 24 +1); + } + + blmc.flags = FLAG_PWM_SPINUP | FLAG_COM_NORMAL; + next_phase(); + + for (time = 0; time < 10; time++) + _delay_ms(20); + + blmc.flags = FLAG_PWM_NORMAL | FLAG_COM_NORMAL; +} + +void setpwm(uint8_t pwm) +{ + + if (pwm >= 8) { + if (blmc.pwm == 0) + blmc.flags = FLAG_PWM_SPINUP | FLAG_COM_SPINUP; + + blmc.pwm = pwm; + + } else { + blmc.flags = 0x00; + blmc.pwm = 0; + } + + if (blmc.flags & FLAG_PWM_SPINUP) + pwm = 0x0f; + else + pwm = blmc.pwm; + + if (blmc.current > 120) + blmc.pwm_limit++; + + else if (blmc.pwm_limit > 0) + blmc.pwm_limit--; + + if (blmc.pwm_limit > pwm) + blmc.pwm_limit = pwm; + + pwm -= blmc.pwm_limit; + OCR1A = pwm; + OCR1B = pwm; + OCR2 = pwm; +} + +ISR(ANA_COMP_vect) +{ + next_phase(); +} + +ISR(ADC_vect) +{ + static uint16_t current_tmp, voltage_tmp; + static uint8_t current_cnt, voltage_cnt; + + uint8_t channel = ADMUX & 0x0F; + uint16_t value = ADCW; + + /* restore channel */ + ADMUX = next_sense; + + /* turn off ADC, disable interrupt */ + ADCSRA = 0x00; + + /* enable Analog Comparator with Interrupts */ + if (blmc.flags & FLAG_COM_NORMAL) + ACSR |= (1< + +#define PHASE_A_H (1< +#include +#include + +#include "main.h" +#include "blmc.h" + +extern struct blmc_ blmc; + +#define CMD_NONE 0x00 +#define CMD_SETPWM 0x10 +#define CMD_GETSTAT 0x20 +#define CMD_REBOOT 0x80 + +ISR(TWI_vect) +{ + static uint8_t cmd = CMD_NONE; + + switch (TWSR & 0xF8) { + /* SLA + W received, ACK returned -> receive Data and ACK */ + case 0x60: + cmd = CMD_NONE; + TWCR |= (1< receive Data and ACK */ + case 0x80: + switch (cmd & 0xF0) { + /* First bytes -> Command */ + case CMD_NONE: + cmd = TWDR; + break; + + /* set pwm */ + case CMD_SETPWM: + setpwm(TWDR); + cmd = CMD_NONE; + break; + + /* set parameters */ + case CMD_REBOOT: + if (TWDR == 0x42) + wdt_enable(WDTO_15MS); + cmd = CMD_NONE; + break; + + /* rest invalid */ + default: + cmd = CMD_NONE; + break; + } + + TWCR |= (1< send data */ + case 0xA8: + /* prev. SLA+R, data sent, ACK returned -> send data */ + case 0xB8: + switch (cmd & 0xF0) { + /* get Current */ + case CMD_GETSTAT: + switch (cmd++ & 0x0F) { + case 0: TWDR = blmc.pwm - blmc.pwm_limit; + break; + + case 1: TWDR = blmc.pwm; + break; + + case 2: TWDR = (blmc.rpm >> 8); + break; + + case 3: TWDR = (blmc.rpm & 0xFF); + break; + + case 4: TWDR = (blmc.current >> 8); + break; + + case 5: TWDR = (blmc.current & 0xFF); + break; + + case 6: TWDR = (blmc.voltage >> 8); + break; + + case 7: TWDR = (blmc.voltage & 0xFF); + cmd = CMD_NONE; + break; + } + break; + + /* rest invalid */ + default: + cmd = CMD_NONE; + break; + } + + TWCR |= (1< reset Hardware */ + case 0xF8: + TWCR |= (1< motor stop + * LED_GN on -> motor running + * LED_GN on & LED_RT blinking -> pwm soft limit + * LED_GN off & LED_RT blinking -> current to high / undervoltage + * + * startup: + * - selftest + * + * cmdloop: + * - set motor (pwm) + * - get status (motor speed, voltage, current) + * - reboot (with cookie) + */ + +#include +#include + +#include "main.h" +#include "blmc.h" + +extern struct blmc_ blmc; + +ISR(TIMER0_OVF_vect) +{ + static uint8_t timer0_cnt = 0; + static uint8_t adc_chan = SENSE_CURRENT; + + /* Come back in 20ms */ + TCNT0 = 0xFF - 156; + + /* current-limiting */ + setpwm(blmc.pwm); + + uint16_t diff = blmc.rpm_tmp - blmc.rpm_tmp2; + blmc.rpm_tmp2 = blmc.rpm_tmp; + + /* too low rpm while running -> do a spinup */ + if (diff < 0x8 && blmc.flags == (FLAG_PWM_NORMAL | FLAG_COM_NORMAL)) + blmc.flags = FLAG_PWM_SPINUP | FLAG_COM_SPINUP; + + timer0_cnt++; + if (timer0_cnt == 50) { + timer0_cnt = 0; + + 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; + } +} + +int main(void) +{ + DDRB = PHASE_H_MASK | LED_RT | LED_GN; + DDRD = PHASE_L_MASK; + + PORTB = LED_GN; + PORTD = 0x00; + + /* timer0: running with F_CPU/1024 */ + TCCR0 = (1< + +#define F_CPU 8000000 +#include + +#define LED_RT (1<