Ok hier mein erster Versuch:
Code:
#include <avr/interrupt.h>
#include <avr/io.h>
#define F_CPU 8000000UL //Fusebit auf interner 8 Mhz Oscillator gesetzt
#include <util/delay.h>
//PHASE1 (U)
#define U_PWM DDRB|=(1<<4);PORTB|=(1<<4);DDRB&=~(1<<5)
#define U_Floating DDRB|=(1<<4);PORTB&=~(1<<4)
#define U_HIGH DDRB|=(1<<4);PORTB|=(1<<4);DDRB|=(1<<5);PORTB|=(1<<5)
#define U_LOW DDRB|=(1<<4);PORTB|=(1<<4);DDRB|=(1<<5);PORTB&=~(1<<5)
//PHASE2 (V)
#define V_PWM DDRB|=(1<<2);PORTB|=(1<<2);DDRB&=~(1<<3)
#define V_Floating DDRB|=(1<<2);PORTB&=~(1<<2)
#define V_HIGH DDRB|=(1<<2);PORTB|=(1<<2);DDRB|=(1<<3);PORTB|=(1<<3)
#define V_LOW DDRB|=(1<<2);PORTB|=(1<<2);DDRB|=(1<<3);PORTB&=~(1<<3)
//PHASE3 (W)
#define W_PWM DDRB|=(1<<7);PORTB|=(1<<7);DDRB&=~(1<<6)
#define W_Floating DDRB|=(1<<7);PORTB&=~(1<<7)
#define W_HIGH DDRB|=(1<<7);PORTB|=(1<<7);DDRB|=(1<<6);PORTB|=(1<<6)
#define W_LOW DDRB|=(1<<7);PORTB|=(1<<7);DDRB|=(1<<6);PORTB&=~(1<<6)
#define SENSE_U ADMUX&=~((1<<MUX2)|(1<<MUX1)|(1<<MUX0));
#define SENSE_V ADMUX&=~((1<<MUX2)|(1<<MUX1)); ADMUX|=(1<<MUX0);
#define SENSE_W ADMUX&=~((1<<MUX2)|(1<<MUX0)); ADMUX|=(1<<MUX1);
volatile uint8_t rotor_state=1;
//setzt den übergebenen Status der Rotoren und setzt den Analog Komparator neu
void set_commutate_state(uint8_t state){
switch (state){
case 1:
U_PWM;
V_Floating;
W_LOW;
SENSE_V;
break;
case 2:
U_Floating;
V_PWM;
W_LOW;
SENSE_U;
break;
case 3:
U_LOW;
V_PWM;
W_Floating;
SENSE_W
break;
case 4:
U_LOW;
V_Floating;
W_PWM;
SENSE_V;
break;
case 5:
U_Floating;
V_LOW;
W_PWM;
SENSE_U;
break;
case 6:
U_PWM;
V_LOW;
W_Floating;
SENSE_W;
break;
}
}
ISR (ANA_COMP_vect)
{
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
}
void anlaufvorgang();
int main (void)
{
//PWM an Port PB1(OC1A) einstellen
TCCR1B |= (1<<CS10); //Prescaler 0; Takt des Timers1 = CPU-Takt
TCCR1A |= (1<<WGM10); // 8-Bit PWM Betriebsart aktivieren
TCCR1B |= (1<<WGM12); //Timer1 zählt bis zu einem Vergleichswert, definiert in OCR1AH/L
TCCR1A |= (1<<COM1A1); // nicht invertierter Modus
OCR1A = 128; // Verhältnis einstellen
DDRB |= (1<<PB1); // PB1 als Ausgang definieren, PWM wird aktiviert
DDRC=0x00; //ADC0-2 auf Eingang für Analog Komparator
PORTC=0x00;
DDRB=0xff;
PORTB=0x00;
//Analog Komparator Interrupt
ADCSRA&=~(1<<ADEN); //ADC ausgeschaltet
ACSR&=~(1<<ACD); //Komparator = ein
ACSR&=~(1<<ACBG); //externe Referenzspannug an AIN0
ACSR|=(1<<ACIE); //Komparator Interrupt = ein
ACSR&=~((1<<ACIS1)|(1<<ACIS0)); //löst Komparator bei jedem Flankenwechsel aus
SFIOR|=(1<<ACME); //aktiviert Multiplexer
anlaufvorgang();
U_Floating;
V_Floating;
W_Floating;
_delay_ms(10);
SENSE_U;
sei();
while(1){
}
}
void anlaufvorgang(){
for(uint16_t i=0;i<50;i++){
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
_delay_ms(5);
}
for(uint16_t i=0;i<100;i++){
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
_delay_ms(4);
}
for(uint16_t i=0;i<200;i++){
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
_delay_ms(3);
}
for(uint16_t i=0;i<300;i++){
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
_delay_ms(2);
}
for(uint16_t i=0;i<500;i++){
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
_delay_us(1500);
}
for(uint16_t i=0;i<1000;i++){
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
_delay_us(1250);
}
for(uint16_t i=0;i<1500;i++){
set_commutate_state(rotor_state);
rotor_state++;
(rotor_state==7)?(rotor_state=1):(rotor_state=rotor_state);
_delay_us(1100);
}
}
Der Anlaufvorgang funktioniert so wie er soll, er schaltet schrittweiße nach oben bis zur letzten Drehzahl. (nicht wundern über die komische Verfahrensweiße, für mich ists so fürn Anfang leichter gewesen)
Allerdings gibt der Festplattenmotor, nachdem er per Zwangskommutierung hochgedreht ist, nur ein Pfeifen von sich.
Folgendes habe ich bereits auf ihre Funktionsweiße überprüft:
Analog Komparator / Multiplexer:
Code:
ISR (ANA_COMP_vect)
{
DDRC|=(1<<PC5);
PORTC^=(1<<PC5); (LED an/ausschalten)
}
int main(){
// Hier Hochdrehen lassen; siehe Quelltext oben
// hier Analog Komparator und Multiplexer aktivieren; siehe Quelltext oben
SENSE_U;
sei();
while(1){}
}
--> Die LED blinkt sehr schnell
Daher weiß ich nicht was falsch sein sollte, von der Logik sollte es ja funktionieren?
->nach dem Hochdrehen SENSE auf U/V/W (ist egal?) setzen
->nichts machen (while(1)) und warten bis der Interrupt ausgelöst wird
->Phase setzen zb. U an, V Floating, W aus und SENSE auf V (also auf dasjenige das gerade eben auf FLOATING gesetzt wurde) //in der ISR wir die Methode set_commutate_state(); aufgerufen
->wieder warten bis der nächste Interrupt ausgelöst wird, usw.
Einen Timer fürs zeitverzögerte Auslösen hab ich noch nicht drin, die nächste Phase direkt nach dem Komparator-Interrupt zu schalten sollte auch funktionieren?
Lesezeichen