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

Комментарии  

0 #41 AntonChip 27.11.2018 08:09
Давайте создадим тему на форуме по этой переделке, напишите там ваше первое сообщение, отсюда я все удалю
Сообщить модератору
0 #42 Михаил---- 27.11.2018 15:30
У меня неполучаеться на форуме за регаться(как бы смешно это не звучало)можно хотябы ручку газа сделать чтоб работала и гдето ошибка есть в проге я R22 на землю посадил всеровну нет нет при нагрузке может воопще остановиться двигатель или как я писал обороты выростают сами по себе.получаетьс я защита воопще не работает.мне просто хочеться быстрей собрать и проверить чтоб дальше красить.я готов отказаться от огроничения по току.хотябы чтоб был реверс и ручка газа работала можно сделать? Спасибо за понемание
Сообщить модератору
0 #43 AntonChip 29.11.2018 19:36
Ответил на форуме radioparty.ru/forum/avr/1798
Сообщить модератору
0 #44 Михаил---- 25.12.2018 23:22
Здравствуйте,ск олько намучался с прошивкой компилировал не как не получаеться чтоб работало без глюков,можите просто добавить реверс.
Сообщить модератору
0 #45 Дениска 26.12.2018 15:02
Добрый, взялся за двигатель, и ума не приложу, почему нумерация "case" не по порядку?
Сообщить модератору
0 #46 AntonChip 26.12.2018 20:54
Цитирую Михаил----:
Здравствуйте,сколько намучался с прошивкой компилировал не как не получаеться чтоб работало без глюков,можите просто добавить реверс.

на форуме проект с готовой прошивкой, проверял все работает
Сообщить модератору
0 #47 AntonChip 26.12.2018 20:58
Цитирую Дениска:
Добрый, взялся за двигатель, и ума не приложу, почему нумерация "case" не по порядку?

Нумерация согласно таблице приведенной выше
Сообщить модератору