Управление бесколлекторным двигателем постоянного тока с датчиками Холла

Бесколлекторные двигатели с датчиками Холла(Sensored brushless motors) применяются как тяговые, в электроприводах, где нужен высокий крутящий момент при низких оборотах. Переключение обмоток двигателя происходит по сигналу датчиков. Обычно они встроены в корпус двигателя. В зависимости от типа они могут быть аналоговыми или цифровыми, это следует учесть при написании программы. В моем двигателе датчики цифровые.

 Датчики Холла Двигатель в разобранном состоянии 

Силовая часть схемы остается прежней. Вместо сигналов обратной ЭДС мы будем обрабатывать сигналы с датчиков Холла. В большинстве случаев датчики Холла подключают к выводам внешних прерываний микроконтроллера. В этом примере мы используем контроллер Atmega48, так как у него внешние прерывания можно организовать на всех портах, в отличие от Atmega8. Тактирование осуществляется от внешнего кварца частотой 8МГц. Ниже показана схема контроллера:

Регулировку частоты вращения вала двигателя сделаем при помощи переменного резистора, т.е. используем АЦП микроконтроллера. Потенциометр подключается к выводу ADC3. Результат преобразования напряжения записываем в регистры сравнения OCR0A, OCR0B и OCR2B, тем самым меняя значение ШИМ на выходе. Переключение обмоток двигателя происходит в обработчике внешнего прерывания. При считывании датчиков их значения записываются в переменную position, исходя из этого какая позиция будет записана в эту переменную, происходит переключение выходов согласно таблице ниже:

На схеме не показаны светодиоды(подключены к PC0-PC2), которые сигнализируют о состоянии каждого датчика, но в программе они задействованы.

// Подключение бесколлекторного двигателя к 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);

// Обработчик внешнего прерывания
ISR(PCINT0_vect)
{
unsigned char position;
// Считываем значения датчиков
position = (PINB & ((1 << PB2)|(1 << PB1)|(1 << PB0)));
// Переключаем обмотки
switch(position)
  {
  case 5: UH_ON; UL_OFF; VH_OFF; VL_ON; WH_OFF; WL_OFF; break;
  case 1: UH_ON; UL_OFF; VH_OFF; VL_OFF; WH_OFF; WL_ON; break;
  case 3: UH_OFF; UL_OFF; VH_ON; VL_OFF; WH_OFF; WL_ON; break;
  case 2: UH_OFF; UL_ON; VH_ON; VL_OFF; WH_OFF; WL_OFF; break;
  case 6: UH_OFF; UL_ON; VH_OFF; VL_OFF; WH_ON; WL_OFF; break;
  case 4: UH_OFF; UL_OFF; VH_OFF; VL_ON; WH_ON; WL_OFF; 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 )
{
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 << MUX1)|(1 << MUX0); // Вход ADC3  
ADCSRA |= (1 << ADEN) | (1 << ADPS1); // Разрешаем АЦП, предделитель на 4

DDRB |=  (1 << PB2)|(1 << PB1)|(1 << PB0); // Блокируем датчики при запуске
PORTB |= (1 << PB2)|(1 << PB1)|(1 << PB0); 
DDRB &= ~(1 << PB2)|(1 << PB1)|(1 << PB0); // Входы датчиков
PORTB &= ~(1 << PB2)|(1 << PB1)|(1 << PB0); // Отключаем подтягивающие резисторы
DDRD = 0xFF; // Порт D - выход  

DDRC |= (1 << PC2)|(1 << PC1)|(1 << PC0); // Светодиоды  
PORTC &= ~(1 << PC2)|(1 << PC1)|(1 << PC0);

sei(); // Глобально разрешаем прерывания

unsigned char speed;

while(1)
{
ADCSRA |= (1 << ADSC); // Запускаем преобразование АЦП
while ( ADCSRA & (1 << ADSC) ); // Ждем окончания преобразования
speed = ADC/4; // Считываем АЦП
Set_Speed(speed); // Изменяем скорость
}
}

Архив для статьи "Управление бесколлекторным двигателем постоянного тока с датчиками Холла" HOT
Проект AVRStudio4
File Size 13.65 KB Download 100 Download

Печать

Комментарии  

0 #1 Tim 14.06.2017 23:17
Здравствуйте. Какой ещё микроконтроллер может существовать в этой схеме? 88, 168?
Сообщить модератору
0 #2 AntonChip 15.06.2017 06:17
Цитирую Tim:
Здравствуйте. Какой ещё микроконтроллер может существовать в этой схеме? 88, 168?

можно использовать 48,88,168,328
Сообщить модератору
0 #3 Tim 15.06.2017 12:43
:eek: А скорость вращения регулируется за счёт ШИМ-а?
Сообщить модератору
0 #4 AntonChip 15.06.2017 23:17
Цитирую Tim:
:eek: А скорость вращения регулируется за счёт ШИМ-а?

Да, ШИМом
Сообщить модератору
0 #5 Макс 08.08.2017 19:06
Ёмкости С1-С3 470пф или ?
Сообщить модератору
0 #6 AntonChip 08.08.2017 21:16
Цитирую Макс:
Ёмкости С1-С3 470пф или ?

470пФ
Сообщить модератору

Похожие материалы

Советуем посмотреть...

Авторизация