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:
--> Die LED blinkt sehr schnellCode: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){} }
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?







Zitieren


Lesezeichen