Запуск бесколлекторного двигателя от hdd.
- Войдите на сайт для отправки комментариев
Сб, 06/08/2016 - 15:46
Пробую раскрутить двигатель от жёсткого диска с помощью arduino. После долгих попыток оно закрутилось, но очень медленно, при разгоне дальше ротор стопорится на одном месте. Схема вот такая, только для всех трёх обмоток (извиняюсь за paint, но так было быстрее, чем скачивать специальный софт):
Пробовал подавать импульсы последовательно(даже через регистры портов не помогает), что-то вроде синусоиды и всё равно не крутится. Вот этот код http://arrduinolab.blogspot.com/2014/09/blog-post.html даёт примерно такой же результат. Кто знает, в чём может быть проблема?
Мосфеты IRFS640A.
P.S. без оптронов тоже самое.
почитайте http://www.avislab.com/blog/brushless02/ + ссылки на статьи внизу
Такому мотору 6 ключей необходимо и правильное переключение обмоток (в том числе и по времени)
То что написано в http://arrduinolab.blogspot.ru/2014/09/blog-post.html - будет крутить, но медленно... И так синусойду для таких двигателей не формируют... для синусоидального управления ардуины не хватит.
Это мой код (на SPI и LED можете не заморачиваться, это из проекта в целом)
#include <SPI.h> #define CLEAR_ALL_TIMER1_INT_FLAGS (TIFR1 = TIFR1) #define DISABLE_ALL_TIMER1_INTS (TIMSK1 = 0) #define SET_TIMER1_INT_COMMUTATION (TIMSK1 = (1 << OCIE1A)) #define SET_TIMER1_INT_HOLDOFF (TIMSK1 = (1 << OCIE1B)) #define EDGE_FALLING 1 #define EDGE_RISING 0 #define COMMUTATION_CORRECTION 50 #define COMMUTATION_TIMING_IIR_COEFF_A 1 #define COMMUTATION_TIMING_IIR_COEFF_B 7 #define ZC_DETECTION_HOLDOFF_TIME_US (filteredTimeSinceCommutation / 2) #define ADC_MUX_U 0x0 #define ADC_MUX_V 0x1 #define ADC_MUX_W 0x2 #define ADC_MID_P 0x3 #define ADC_RES_ALIGNMENT_BEMF (1 << ADLAR) #define ADC_REF_CHANNEL ((0 << REFS1) | (1 << REFS0)) #define ADMUX_U (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MUX_U) #define ADMUX_V (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MUX_V) #define ADMUX_W (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MUX_W) #define ADMUX_MID_P (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MID_P) #define ADC_PRESCALER_4 ((0 << ADPS2) | (1 << ADPS1) | (0 << ADPS0)) #define ADC_PRESCALER_8 ((0 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)) #define ADC_PRESCALER_16 ((1 << ADPS2) | (0 << ADPS1) | (0 << ADPS0)) #define TICKS_PER_SECOND 2000000UL #define TICKS_PER_MINUTE (TICKS_PER_SECOND * 60) //-------------------------------------------------------- #define UH PB0 #define UL PB1 #define VH PD4 #define VL PD5 #define WH PD7 #define WL PD6 #define LED_G PB2 #define LED_R PB3 #define LED_B PB4 /* #define UH_ON PORTB |= (1 << UH) #define VH_ON PORTD |= (1 << VH) #define WH_ON PORTD |= (1 << WH) #define UH_OFF PORTB &= ~(1 << UH) #define VH_OFF PORTD &= ~(1 << VH) #define WH_OFF PORTD &= ~(1 << WH) */ #define UH_OFF PORTB |= (1 << UH) #define VH_OFF PORTD |= (1 << VH) #define WH_OFF PORTD |= (1 << WH) #define UH_ON PORTB &= ~(1 << UH) #define VH_ON PORTD &= ~(1 << VH) #define WH_ON PORTD &= ~(1 << WH) #define UL_ON PORTB |= (1 << UL) #define VL_ON PORTD |= (1 << VL) #define WL_ON PORTD |= (1 << WL) #define UL_OFF PORTB &= ~(1 << UL) #define VL_OFF PORTD &= ~(1 << VL) #define WL_OFF PORTD &= ~(1 << WL) #define LED_G_ON PORTB |= (1 << LED_G) #define LED_G_OFF PORTB &= ~(1 << LED_G) #define LED_R_ON PORTB |= (1 << LED_R) #define LED_R_OFF PORTB &= ~(1 << LED_R) #define LED_B_ON PORTB |= (1 << LED_B) #define LED_B_OFF PORTB &= ~(1 << LED_B) //-------------------------------------------------------- volatile unsigned char nextDrivePattern; volatile unsigned char zcPolarity; volatile unsigned char nextCommutationStep; volatile unsigned char currentADMUX; volatile unsigned int filteredTimeSinceCommutation; volatile unsigned long ms_time = 0; volatile byte zc_detection; volatile unsigned int a_time; volatile unsigned int b_time; volatile unsigned int c_time; volatile byte massive_led; byte massive[128]; byte massive_1[128]; byte massive_2[128]; byte color; #define LAT 10 static void InitPorts(void) { DDRD |= (1 << VL) | (1 << VH) | (1 << WL) | (1 << WH); DDRB |= (1 << UH) | (1 << UL) | (1 << LED_G) | (1 << LED_R) | (1 << LED_B); DIDR0 = (1 << ADC5D) | (1 << ADC4D) | (1 << ADC3D) | (1 << ADC2D) | (1 << ADC1D) | (1 << ADC0D); } static void InitTimers(void) { TCCR0A = (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0) | (1 << WGM01) | (0 << WGM00); TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (1 << CS00); TCCR2A = (0 << COM2A1) | (0 << COM2A0) | (1 << COM2B1) | (1 << COM2B0) | (0 << WGM21) | (1 << WGM20); TCCR2B = (0 << WGM22) | (0 << CS22) | (0 << CS21) | (1 << CS20); zc_detection = 0; TIFR2 = TIFR2; TIMSK2 |= (1 << TOIE2); TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0) | (0 << WGM21) | (0 << WGM20); TCCR1B = (0 << CS12) | (1 << CS11) | (0 << CS10); } static void InitADC(void) { ADCSRA = (1 << ADEN) | (0 << ADSC) | (0 << ADATE) | (0 << ADIF) | (0 << ADIE) | ADC_PRESCALER_4; } void motorStep(byte CommutationStep) { switch (CommutationStep) { case 0: UH_OFF; VH_ON; WH_OFF; UL_ON; VL_OFF; WL_OFF; currentADMUX = ADMUX_W; break; case 1: UH_OFF; VH_OFF; WH_ON; UL_ON; VL_OFF; WL_OFF; currentADMUX = ADMUX_V; break; case 2: UH_OFF; VH_OFF; WH_ON; UL_OFF; VL_ON; WL_OFF; currentADMUX = ADMUX_U; break; case 3: UH_ON; VH_OFF; WH_OFF; UL_OFF; VL_ON; WL_OFF; currentADMUX = ADMUX_W; break; case 4: UH_ON; VH_OFF; WH_OFF; UL_OFF; VL_OFF; WL_ON; currentADMUX = ADMUX_V; break; case 5: UH_OFF; VH_ON; WH_OFF; UL_OFF; VL_OFF; WL_ON; currentADMUX = ADMUX_U; break; } zcPolarity = CommutationStep & 0x01; } void nextStepReadData(void) { nextCommutationStep++; if (nextCommutationStep >= 6) nextCommutationStep = 0; } ISR (TIMER2_OVF_vect) { if (zc_detection == 1) { unsigned char temp; unsigned char voltageMidPoint; ADMUX = ADMUX_MID_P; ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)); voltageMidPoint = ADCH; ADMUX = currentADMUX; ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)); temp = ADCH; if (((zcPolarity == EDGE_RISING) && (temp > voltageMidPoint)) || ((zcPolarity == EDGE_FALLING) && (temp < voltageMidPoint))) { unsigned int timeSinceCommutation; timeSinceCommutation = TCNT1; TCNT1 = COMMUTATION_CORRECTION; filteredTimeSinceCommutation = (COMMUTATION_TIMING_IIR_COEFF_A * timeSinceCommutation + COMMUTATION_TIMING_IIR_COEFF_B * filteredTimeSinceCommutation) / (COMMUTATION_TIMING_IIR_COEFF_A + COMMUTATION_TIMING_IIR_COEFF_B); OCR1A = filteredTimeSinceCommutation; SET_TIMER1_INT_COMMUTATION; CLEAR_ALL_TIMER1_INT_FLAGS; zc_detection = 0; } } ++a_time; ++c_time; if (c_time == 64) { ++b_time; c_time = 0; } } ISR(TIMER1_COMPA_vect) { motorStep(nextCommutationStep); nextStepReadData(); TCNT1 = 0; CLEAR_ALL_TIMER1_INT_FLAGS; SET_TIMER1_INT_HOLDOFF; OCR1B = ZC_DETECTION_HOLDOFF_TIME_US; } ISR(TIMER1_COMPB_vect) { CLEAR_ALL_TIMER1_INT_FLAGS; DISABLE_ALL_TIMER1_INTS; zc_detection = 1; } void start_motor(void) { InitTimers(); InitADC(); InitPorts(); nextCommutationStep = 3; motorStep(nextCommutationStep); filteredTimeSinceCommutation = 10000; TCNT1 = 0; TIMSK1 = (1 << OCIE1A); } ISR (TIMER0_COMPA_vect) { if (massive_led < 128){ //128) { //led_on(massive_led/16); //if (massive[massive_led]) led_on(color); //else led_off(); //led_on(massive[massive_led]); if (massive_led > 16) { SPI.transfer(B00000000); digitalWrite(10, HIGH); digitalWrite(10, LOW); } ++massive_led; } else led_off(); } void holl(void) { unsigned int temp; static unsigned int b_time; if (a_time < 32) return; //неизвестный баг :) cli(); temp = a_time; a_time = 0; TCNT0 = 0; TIFR0 = TIFR0; sei(); b_time = (temp + 7 * b_time) / 8; OCR0A = b_time / 16; //- 1; //led_on(massive[0]); //if (massive[0]) led_on(color); //else led_off(); SPI.transfer(B11111111); digitalWrite(10, HIGH); digitalWrite(10, LOW); massive_led = 1; } void led_on(byte c) { switch (c) { case 0: LED_R_OFF; LED_G_OFF; LED_B_OFF; break; case 1: LED_R_ON; LED_G_OFF; LED_B_OFF; break; case 2: LED_R_ON; LED_G_ON; LED_B_OFF; break; case 3: LED_R_OFF; LED_G_ON; LED_B_OFF; break; case 4: LED_R_OFF; LED_G_ON; LED_B_ON; break; case 5: LED_R_OFF; LED_G_OFF; LED_B_ON; break; case 6: LED_R_ON; LED_G_OFF; LED_B_ON; break; case 7: LED_R_ON; LED_G_ON; LED_B_ON; break; default: LED_R_OFF; LED_G_OFF; LED_B_OFF; break; } } void led_off() { LED_R_OFF; LED_G_OFF; LED_B_OFF; } void setup() { //massive = massive; start_motor(); for (int i = 0; i < 128; ++i) { massive[i] = 0; } Serial.begin(115200); Serial.println("START"); color = 0; pinMode(3, OUTPUT); pinMode(2, INPUT_PULLUP); //pinMode(13, OUTPUT); pinMode(LAT, OUTPUT); digitalWrite(LAT, LOW); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV2); SPI.setBitOrder(MSBFIRST); attachInterrupt(0, holl, FALLING); TIMSK0 |= (1 << OCIE0A); //digitalWrite(3, LOW); //OCR2B = 255; //delay_ms(1000); OCR2B = 96; for (int i = 0; i < 128; ++i) { massive_1[i] = i / 16; } SPI.transfer(B00000001); digitalWrite(10, HIGH); digitalWrite(10, LOW); } void delay_ms(unsigned int t) { unsigned int temp = b_time; while (temp + t > b_time); } void led_off_all(void) { for (int i = 0; i < 128; ++i) { massive_1[i] = 7; } } void loop() { /* for (int i = 0; i < 128; ++i) { led_off_all(); massive[i+1] = 0; massive[i] = 3; massive[i-1] = 0; massive[0] = 1; massive[63] = 5; delay_ms(10); //Serial.println(*massive()); } */ /* SPI.transfer(B00000001); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); SPI.transfer(B00000010); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); SPI.transfer(B00000100); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); SPI.transfer(B00001000); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); SPI.transfer(B00010000); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); SPI.transfer(B00100000); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); SPI.transfer(B01000000); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); SPI.transfer(B10000000); digitalWrite(10, HIGH); digitalWrite(10, LOW); delay_ms(300); */ //digitalWrite(13, !digitalRead(13)); //delay_ms(500); /* for (int i = 0; i < 128; ++i) { for (int j = 0; j < 128; ++j) { massive[j] = 0; } massive[i] = 1; massive[127 - i] = 1; massive[0] = 1; massive[127 / 2] = 1; delay_ms(5); } ++color; if (color == 8) color = 0; */ }6 ключей как раз сегодня реализовал, но то ли я неправильно переключаю, то ли хз вообще что, результат тот же, не разгоняется. Спасибо, поизучаю.
Ну так надо детекитрование 0 обеспечить.
Также, мосфетам верхнего плеча неплохо было бы драйверы поставить. Ну или N канальные поставить.
У меня сейчас в схеме верхние плечи на N канальные, нижние P канальные. Питание 5В (что бы с драйвером не заморачиваться, управляю сразу с ардуины). Крутиться до 3000 об\мин. Выше мне не надо было.
Раньше делал верхнее плечо с инвертирующим транзистором с подключением к 12В - крутил до 12 000 - 13 000 (чуть не улетел :) ), вместе с установленными блинами.
Сейчас схема вот такая:
А код такой:
#define O1 2 // + на обмотку #define O2 3 #define O3 4 #define I1 5 // - на обмотку #define I2 6 #define I3 7 void setPosition(int pos); void setup() { pinMode(O1, OUTPUT); pinMode(O2, OUTPUT); pinMode(O3, OUTPUT); pinMode(I1, OUTPUT); pinMode(I2, OUTPUT); pinMode(I3, OUTPUT); } int pause = 200; int position = 0; void loop() { setPosition(position++); if (position > 5) position = 0; delay(pause); pause-=1; if (pause < 10) pause = 10; } void setPosition(int pos) { switch (pos) { case 0: PORTD &= B00000011; PORTD |= B01000100; /*digitalWrite(O1, HIGH); digitalWrite(O2, LOW); digitalWrite(O3, LOW); digitalWrite(I1, LOW); digitalWrite(I2, HIGH); digitalWrite(I3, LOW);*/ break; case 1: PORTD &= B00000011; PORTD |= B10000100; /*digitalWrite(O1, HIGH); digitalWrite(O2, LOW); digitalWrite(O3, LOW); digitalWrite(I1, LOW); digitalWrite(I2, LOW); digitalWrite(I3, HIGH);*/ break; case 2: PORTD &= B00000011; PORTD |= B10001000; /*digitalWrite(O1, LOW); digitalWrite(O2, HIGH); digitalWrite(O3, LOW); digitalWrite(I1, LOW); digitalWrite(I2, LOW); digitalWrite(I3, HIGH);*/ break; case 3: PORTD &= B00000011; PORTD |= B00101000; /*digitalWrite(O1, LOW); digitalWrite(O2, HIGH); digitalWrite(O3, LOW); digitalWrite(I1, HIGH); digitalWrite(I2, LOW); digitalWrite(I3, LOW);*/ break; case 4: PORTD &= B00000011; PORTD |= B00110000; /*digitalWrite(O1, LOW); digitalWrite(O2, LOW); digitalWrite(O3, HIGH); digitalWrite(I1, HIGH); digitalWrite(I2, LOW); digitalWrite(I3, LOW);*/ break; case 5: PORTD &= B00000011; PORTD |= B01010000; /*digitalWrite(O1, LOW); digitalWrite(O2, LOW); digitalWrite(O3, HIGH); digitalWrite(I1, LOW); digitalWrite(I2, HIGH); digitalWrite(I3, LOW);*/ break; default: digitalWrite(O1, LOW); digitalWrite(O2, LOW); digitalWrite(O3, LOW); digitalWrite(I1, LOW); digitalWrite(I2, LOW); digitalWrite(I3, LOW); break; } }Но не работает.
Специально проект свой подчистил.
Схема и код. Работает от 5В. Если надо 12В, то на верхние плечи надо согласующий транзистор ставить + добавить делитель на детектор 0, дабы аналоговый порт Ардуины не спалить. Если надо еще больше, то надо ставить драйверы полевиков.
При наличие у мотора средней точки, AD3 подключается напрямую к средней точке, без R36-38
Схема (транзисторы указаны условно). Обязательно в верхнем плече P канальные, в нижнем N канальные. Иначе - ставить драйверы.
Код
#define CLEAR_ALL_TIMER1_INT_FLAGS (TIFR1 = TIFR1) #define DISABLE_ALL_TIMER1_INTS (TIMSK1 = 0) #define SET_TIMER1_INT_COMMUTATION (TIMSK1 = (1 << OCIE1A)) #define SET_TIMER1_INT_HOLDOFF (TIMSK1 = (1 << OCIE1B)) #define EDGE_FALLING 1 #define EDGE_RISING 0 #define COMMUTATION_CORRECTION 50 #define COMMUTATION_TIMING_IIR_COEFF_A 1 #define COMMUTATION_TIMING_IIR_COEFF_B 3 #define ZC_DETECTION_HOLDOFF_TIME_US (filteredTimeSinceCommutation / 2) #define ADC_MUX_U 0x0 #define ADC_MUX_V 0x1 #define ADC_MUX_W 0x2 #define ADC_MID_P 0x3 #define ADC_RES_ALIGNMENT_BEMF (1 << ADLAR) #define ADC_REF_CHANNEL ((0 << REFS1) | (1 << REFS0)) #define ADMUX_U (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MUX_U) #define ADMUX_V (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MUX_V) #define ADMUX_W (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MUX_W) #define ADMUX_MID_P (ADC_REF_CHANNEL | ADC_RES_ALIGNMENT_BEMF | ADC_MID_P) #define ADC_PRESCALER_8 ((0 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)) //-------------------------------------------------------- #define UH PB0 #define UL PB1 #define VH PB2 #define VL PB3 #define WH PB4 #define WL PB5 /* #define UH_ON PORTB |= (1 << UH) #define VH_ON PORTD |= (1 << VH) #define WH_ON PORTD |= (1 << WH) #define UH_OFF PORTB &= ~(1 << UH) #define VH_OFF PORTD &= ~(1 << VH) #define WH_OFF PORTD &= ~(1 << WH) */ #define UH_OFF PORTB |= (1 << UH) #define VH_OFF PORTB |= (1 << VH) #define WH_OFF PORTB |= (1 << WH) #define UH_ON PORTB &= ~(1 << UH) #define VH_ON PORTB &= ~(1 << VH) #define WH_ON PORTB &= ~(1 << WH) #define UL_ON PORTB |= (1 << UL) #define VL_ON PORTB |= (1 << VL) #define WL_ON PORTB |= (1 << WL) #define UL_OFF PORTB &= ~(1 << UL) #define VL_OFF PORTB &= ~(1 << VL) #define WL_OFF PORTB &= ~(1 << WL) //-------------------------------------------------------- volatile unsigned char nextDrivePattern; volatile unsigned char zcPolarity; volatile unsigned char nextCommutationStep; volatile unsigned char currentADMUX; volatile unsigned int filteredTimeSinceCommutation; volatile byte zc_detection; static void InitPorts(void) { DDRB |= (1 << UL) | (1 << UH) | (1 << VL) | (1 << VH) | (1 << WL) | (1 << WH); DIDR0 = (1 << ADC4D) | (1 << ADC3D) | (1 << ADC2D) | (1 << ADC1D) | (1 << ADC0D); } static void InitTimers(void) { TCCR2A = (0 << COM2A1) | (0 << COM2A0) | (0 << COM2B1) | (0 << COM2B0) | (0 << WGM21) | (1 << WGM20); TCCR2B = (0 << WGM22) | (0 << CS22) | (0 << CS21) | (1 << CS20); TIFR2 = TIFR2; zc_detection = 0; TIMSK2 |= (1 << TOIE2); TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0) | (0 << WGM21) | (0 << WGM20); TCCR1B = (0 << CS12) | (1 << CS11) | (0 << CS10); } static void InitADC(void) { ADCSRA = (1 << ADEN) | (0 << ADSC) | (0 << ADATE) | (0 << ADIF) | (0 << ADIE) | ADC_PRESCALER_8; } void motorStep(byte CommutationStep) { switch (CommutationStep) { case 0: UH_OFF; VH_ON; WH_OFF; UL_ON; VL_OFF; WL_OFF; currentADMUX = ADMUX_W; break; case 1: UH_OFF; VH_OFF; WH_ON; UL_ON; VL_OFF; WL_OFF; currentADMUX = ADMUX_V; break; case 2: UH_OFF; VH_OFF; WH_ON; UL_OFF; VL_ON; WL_OFF; currentADMUX = ADMUX_U; break; case 3: UH_ON; VH_OFF; WH_OFF; UL_OFF; VL_ON; WL_OFF; currentADMUX = ADMUX_W; break; case 4: UH_ON; VH_OFF; WH_OFF; UL_OFF; VL_OFF; WL_ON; currentADMUX = ADMUX_V; break; case 5: UH_OFF; VH_ON; WH_OFF; UL_OFF; VL_OFF; WL_ON; currentADMUX = ADMUX_U; break; } } void nextStepReadData(void) { zcPolarity = nextCommutationStep & 0x01; nextCommutationStep++; if (nextCommutationStep >= 6) nextCommutationStep = 0; } ISR (TIMER2_OVF_vect) { if (zc_detection == 1) { unsigned char temp; unsigned char voltageMidPoint; ADMUX = ADMUX_MID_P; ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)); voltageMidPoint = ADCH; ADMUX = currentADMUX; ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)); temp = ADCH; if (((zcPolarity == EDGE_RISING) && (temp > voltageMidPoint)) || ((zcPolarity == EDGE_FALLING) && (temp < voltageMidPoint))) { unsigned int timeSinceCommutation; timeSinceCommutation = TCNT1; TCNT1 = COMMUTATION_CORRECTION; filteredTimeSinceCommutation = (COMMUTATION_TIMING_IIR_COEFF_A * timeSinceCommutation + COMMUTATION_TIMING_IIR_COEFF_B * filteredTimeSinceCommutation) / (COMMUTATION_TIMING_IIR_COEFF_A + COMMUTATION_TIMING_IIR_COEFF_B); OCR1A = filteredTimeSinceCommutation; SET_TIMER1_INT_COMMUTATION; CLEAR_ALL_TIMER1_INT_FLAGS; zc_detection = 0; } } } ISR(TIMER1_COMPA_vect) { motorStep(nextCommutationStep); nextStepReadData(); TCNT1 = 0; CLEAR_ALL_TIMER1_INT_FLAGS; SET_TIMER1_INT_HOLDOFF; OCR1B = ZC_DETECTION_HOLDOFF_TIME_US; } ISR(TIMER1_COMPB_vect) { CLEAR_ALL_TIMER1_INT_FLAGS; DISABLE_ALL_TIMER1_INTS; zc_detection = 1; } void start_motor(void) { InitTimers(); InitADC(); InitPorts(); nextCommutationStep = 0; motorStep(nextCommutationStep); filteredTimeSinceCommutation = 10000; TCNT1 = 0; TIMSK1 = (1 << OCIE1A); } void setup() { start_motor(); } void loop() { }