Бесколлекторные двигатели с датчиками Холла(Sensored brushless motors) применяются как тяговые, в электроприводах, где нужен высокий крутящий момент при низких оборотах. Переключение обмоток двигателя происходит по сигналу датчиков. Обычно они встроены в корпус двигателя. В зависимости от типа они могут быть аналоговыми или цифровыми, это следует учесть при написании программы. В моем двигателе датчики цифровые.
Силовая часть схемы остается прежней. Вместо сигналов обратной ЭДС мы будем обрабатывать сигналы с датчиков Холла. В большинстве случаев датчики Холла подключают к выводам внешних прерываний микроконтроллера. В этом примере мы используем контроллер ATmega48, так как у него внешние прерывания можно организовать на всех портах, в отличие от Atmega8. Тактирование осуществляется от внешнего кварца частотой 8МГц. Ниже показана схема контроллера:
Регулировку частоты вращения вала двигателя сделаем при помощи переменного резистора, т.е. используем АЦП микроконтроллера. Потенциометр подключается к выводу ADC3. Результат преобразования напряжения записываем в регистры сравнения OCR0A, OCR0B и OCR2B, тем самым меняя значение ШИМ на выходе. Переключение обмоток двигателя происходит в обработчике внешнего прерывания. При считывании датчиков их значения записываются в переменную position, исходя из этого какая позиция будет записана в эту переменную, происходит переключение выходов согласно таблице ниже:
На схеме не показаны светодиоды(подключены к PC2..0), которые сигнализируют о состоянии каждого датчика, но в программе они задействованы.
// Подключение бесколлекторного двигателя к AVR(с датчиками Холла) #include <avr/io.h> #include <avr/interrupt.h> // Фаза U(Верхнее плечо) #define UH_ON TCCR0A |= (1 << COM0A1); #define UH_OFF TCCR0A &= ~(1 << COM0A1); // Фаза U(Нижнее плечо) #define UL_ON PORTD |= (1 << PD7); #define UL_OFF PORTD &= ~(1 << PD7); // Фаза V(Верхнее плечо) #define VH_ON TCCR0A |= (1 << COM0B1); #define VH_OFF TCCR0A &= ~(1 << COM0B1); // Фаза V(Нижнее плечо) #define VL_ON PORTD |= (1 << PD4); #define VL_OFF PORTD &= ~(1 << PD4); // Фаза W(Верхнее плечо) #define WH_ON TCCR2A |= (1 << COM2B1); #define WH_OFF TCCR2A &= ~(1 << COM2B1); // Фаза W(Нижнее плечо) #define WL_ON PORTD |= (1 << PD2); #define WL_OFF PORTD &= ~(1 << PD2); unsigned char speed; // Обработчик внешнего прерывания ISR(PCINT0_vect) { unsigned char position; // Считываем значения датчиков position = (PINB & ((1 << PB2)|(1 << PB1)|(1 << PB0))); switch(position) // Переключаем обмотки в зависимости от положения датчиков { case 0b001: UH_OFF; UL_ON; VH_OFF; VL_OFF; WH_ON; WL_OFF; break; case 0b010: UH_OFF; UL_OFF; VH_ON; VL_OFF; WH_OFF; WL_ON; break; case 0b011: UH_OFF; UL_ON; VH_ON; VL_OFF; WH_OFF; WL_OFF; break; case 0b100: UH_ON; UL_OFF; VH_OFF; VL_ON; WH_OFF; WL_OFF; break; case 0b101: UH_OFF; UL_OFF; VH_OFF; VL_ON; WH_ON; WL_OFF; break; case 0b110: UH_ON; UL_OFF; VH_OFF; VL_OFF; WH_OFF; WL_ON; break; } PORTC = position; // Индикация положения датчиков } // Функция изменения скорости static void set_speed(unsigned char speed) { TIFR0 = TIFR0; // Очищаем флаг прерывания TC0 while( !(TIFR0 & (1<<TOV0))); // Ждем переполнения таймера cli(); OCR0A = speed; // Изменяем ШИМ OCR0B = speed; OCR2B = speed; sei(); } int main(void) { // Настройка портов ввода/вывода DDRC |= (1 << PC2)|(1 << PC1)|(1 << PC0); // Порт С - выход(светодиоды) PORTC &= ~(1 << PC2)|(1 << PC1)|(1 << PC0); DDRD = 0xFF; // Порт D - выход // Настройка таймера 0,2 - ШИМ TCCR0A |= (1 << COM0A1)|(0 << COM0A0)| // Сброс вывода OC0A при совпадении (1 << COM0B1)|(0 << COM0B0)| // Сброс вывода OC0B при совпадении (1 << WGM01)|(1 << WGM00); // Режим Fast PWM TCCR0B |= (1 << CS00); // Предделитель CLK/1 TCCR2A |= (1 << COM2B1)|(0 << COM2B0)| // Сброс вывода OC2B при совпадении (1 << WGM01)|(1 << WGM00); // Режим Fast PWM TCCR2B |= (1 << CS20); // // Предделитель CLK/1 // Настройка внешних прерываний PCMSK0 |= (1 << PCINT2)|(1 << PCINT1)|(1 << PCINT0); // Активируем входы внешних прерываний PCICR |= (1 << PCIE0); // Разрешаем прерывание по изменению состояния порта B // Настройка АЦП ADMUX |= (1 << REFS0) // Опорное напряжение AVcc с конденсатором на выводе Aref |(1 << ADLAR) // Выравнивание результата влево, читаем только ADCH |(1 << MUX1)|(1 << MUX0); // Вход ADC3 ADCSRA |= (1 << ADEN) | (1 << ADPS1); // Разрешаем АЦП, предделитель на 4 // Настройка датчиков Холла DDRB |= (1 << PB2)|(1 << PB1)|(1 << PB0); // Кратковреммено подаем лог.1 на входы датчиков PORTB |= (1 << PB2)|(1 << PB1)|(1 << PB0); // для первоначального запуска двигателя PORTB &= ~(1 << PB2)|(1 << PB1)|(1 << PB0); DDRB = 0x00; // Порт B - вход sei(); // Глобально разрешаем прерывания while(1) { ADCSRA |= (1 << ADSC); // Запускаем преобразование АЦП while ( ADCSRA & (1 << ADSC) ); // Ждем окончания преобразования speed = ADCH; // Считываем АЦП set_speed(speed); // Изменяем скорость } }
Обсуждение статьи на форуме
Архив для статьи "Управление бесколлекторным двигателем постоянного тока с датчиками Холла" | |
Описание: Проект AVRStudio4 | |
Размер файла: 13.65 KB Количество загрузок: 1 725 | Скачать |
Комментарии
на форуме проект с готовой прошивкой, проверял все работает
Нумерация согласно таблице приведенной выше