Бесколлекторные двигатели с датчиками Холла(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 815 | Скачать |




Комментарии
на форуме проект с готовой прошивкой, проверял все работает
Нумерация согласно таблице приведенной выше