Подключение бесколлекторного двигателя с датчиками Холла к AVR

Модератор: boogyman

Ответить
Аватара пользователя
AntonChip
Администратор
Сообщения: 221
Зарегистрирован: 24 дек 2011, 22:11
Откуда: Киров
Контактная информация:

Подключение бесколлекторного двигателя с датчиками Холла к AVR

#1

Сообщение AntonChip » 26 дек 2018, 10:22

Здравствуйте. По просьбам читателей решил дополнить управляющую программу драйвера бесколлекторного двигателя с датчиками Холла.
Оригинал статьи здесь https://radioparty.ru/programming/avr/c ... all-sensor
Изменил источник опорного напряжения на внутренний (1,1V), лучше подходит для измерения тока, поэтому потенциометр подключил через делитель напряжения. Так как в дальнейшем планируется измерение тока каналы измерения меняются в обработчике прерывания от АЦП, а само прерывание происходит от переполнения таймера. Переменная start_speed содержит значение при котором начинается запуск двигателя.
Реверс двигателя осуществляется переключателем S1 при полной остановке двигателя.
Выходы на светодиоды "Реверс" и "Макс. ток" в коде пока не использовал, а также переменную current.

Код: Выделить всё

#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);

#define PHASE_ALL_OFF	UH_OFF;UL_OFF;VH_OFF;VL_OFF;WH_OFF;WL_OFF;

#define start_speed 2

char start;
volatile uint16_t current;
volatile uint8_t speed;
volatile char direction, channel = 3;

// Обработчик внешнего прерывания
ISR(PCINT0_vect)
{
uint8_t position;
// Считываем значения датчиков
position = (PINB & ((1 << PB2)|(1 << PB1)|(1 << PB0)));
  if(direction) // Если по часовой
  {
    switch(position) // Переключаем обмотки
    {
    case 0b101: UH_OFF; UL_ON; VH_ON; VL_OFF; WH_OFF; WL_OFF; break;
    case 0b001: UH_OFF; UL_ON; VH_OFF; VL_OFF; WH_ON; WL_OFF; break;
    case 0b011: UH_OFF; UL_OFF; VH_OFF; VL_ON; WH_ON; WL_OFF; break;
    case 0b010: UH_ON; UL_OFF; VH_OFF; VL_ON; WH_OFF; WL_OFF; break;
    case 0b110: UH_ON; UL_OFF; VH_OFF; VL_OFF; WH_OFF; WL_ON; break;
    case 0b100: UH_OFF; UL_OFF; VH_ON; VL_OFF; WH_OFF; WL_ON; break;
    }
  }
  else // иначе против часовой
  {
    switch(position) // Переключаем обмотки
    {
    case 0b101: UH_ON; UL_OFF; VH_OFF; VL_ON; WH_OFF; WL_OFF; break;
    case 0b001: UH_ON; UL_OFF; VH_OFF; VL_OFF; WH_OFF; WL_ON; break;
    case 0b011: UH_OFF; UL_OFF; VH_ON; VL_OFF; WH_OFF; WL_ON; break;
    case 0b010: UH_OFF; UL_ON; VH_ON; VL_OFF; WH_OFF; WL_OFF; break;
    case 0b110: UH_OFF; UL_ON; VH_OFF; VL_OFF; WH_ON; WL_OFF; break;
    case 0b100: UH_OFF; UL_OFF; VH_OFF; VL_ON; WH_ON; WL_OFF; break;
    }
  }
}

ISR(ADC_vect)
{
  switch(channel)
  {
  case 3:
    ADMUX = (1 << REFS1)|(1 << REFS0)|(1 << MUX2);
    speed = ADC/4;
	channel = 4;
	break;
  case 4:
    ADMUX = (1 << REFS1)|(1 << REFS0)|(1 << MUX1)|(1 << MUX0);
    current = ADC;
	channel = 3;
    break;
  }
  TIFR0 = (1 << TOV0);
}


// Функция изменения скорости
static void set_speed(uint8_t speed)
{
TIFR2 = TIFR2;    // Очищаем флаг прерывания T0
while(!(TIFR2 & (1<<TOV2)));  // Ждем переполнения таймера
cli();
OCR0A = speed; // Изменяем ШИМ
OCR0B = speed;
OCR2B = speed;
sei();
}

int main(void)
{
TCCR0A |= (1 << WGM01)|(1 << WGM00); // Режим Fast PWM
TCCR0B |= (1 << CS00); // Предделитель CLK/1

TCCR2A |= (1 << WGM01)|(1 << WGM00); // Режим Fast PWM
TCCR2B |= (1 << CS20); // Предделитель CLK/1

PCMSK0 |= (1 << PCINT2)|(1 << PCINT1)|(1 << PCINT0); // Активируем входы внешних прерываний
PCICR |= (1 << PCIE0);    // Разрешаем прерывание по изменению состояния порта B

ADMUX = (1 << REFS1)|(1 << REFS0) // Внутренний ИОН 1,1V
         |(1 << MUX1)|(1 << MUX0); // Вход ADC3
ADCSRA = (1 << ADEN) // Разрешаем ADC
        |(1 << ADSC) // Запускаем преобразование
		|(1 << ADATE) // Непрерывный режим преобразования 
		|(1 << ADIF) // Очищаем флаг прерывания
		|(1 << ADIE) // Разрешаем прерывание ADC
		|(1 << ADPS1); // Предделитель 4
ADCSRB = (1 << ADTS2); // Запуск преобразования по переполнению Т0

DDRC &= ~(1 << PC5); // Переключатель направления вращения
PORTC |= (1 << PC5); // Вкл. внутренний подтягивающий резистор

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

DDRD = 0xFF; // Порт D - выход 

while(1)
{
  if(speed > start_speed) // Если значение скорости больше скорости запуска 
  {
	// Режим запуска
	if(start) // Если пуск разрешен, запускаем двигатель
	{
	  if(PINC&(1 << PC5))        direction = 1; // По часовой
	  if((PINC&(1 << PC5)) == 0) direction = 0; // Против часовой
    PCICR |= (1 << PCIE0);    // Разрешаем прерывание по изменению состояния порта B
	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 - вход
    start = 0; // Запрещаем запуск
	}
    // Рабочий режим
	set_speed(speed); // Изменяем скорость
  }
  else
  {
  start = 1; // Разрешаем запуск
  speed = 0;
  PCICR &= ~(1 << PCIE0); // Запрещаем прерывание по изменению состояния порта B
  PHASE_ALL_OFF; // Выключаем выхода на двигатель
  }

}
}
Схема с датчиками Холла.gif
Вложения
bldc_holl_atmega48.rar
(16.64 КБ) 84 скачивания

Аватара пользователя
Elektron855568
Новичок
Сообщения: 3
Зарегистрирован: 24 янв 2019, 10:50
Откуда: Георгиевск

Re: Подключение бесколлекторного двигателя с датчиками Холла к AVR

#2

Сообщение Elektron855568 » 11 май 2019, 10:03

Здравствуйте Антон. Не могу написать в комментариях к статье https://radioparty.ru/programming/avr/c ... sensorless поэтому пишу сюда. Собрал данное устройство с двигателем от hdd, после включения двигатель чуть подергивается и начинают греться нижние ключи. В чём может быть проблема.

Аватара пользователя
AntonChip
Администратор
Сообщения: 221
Зарегистрирован: 24 дек 2011, 22:11
Откуда: Киров
Контактная информация:

Re: Подключение бесколлекторного двигателя с датчиками Холла к AVR

#3

Сообщение AntonChip » 11 май 2019, 17:57

Приветствую, проблем может быть несколько, от неправильно установленных битов конфигурации МК до бракованных IR2101, осциллограф вам в помощь.

Аватара пользователя
Elektron855568
Новичок
Сообщения: 3
Зарегистрирован: 24 янв 2019, 10:50
Откуда: Георгиевск

Re: Подключение бесколлекторного двигателя с датчиками Холла к AVR

#4

Сообщение Elektron855568 » 12 май 2019, 09:34

Уточню, первый вариант драйвера, без 2101.https://radioparty.ru/prog-avr/program-c/611-lesso Установил две пары полевиков, верхние ключи P-канал, нижние N-канал. Биты конфигурации установлены верно. Меандр на всех транзисторах присутствует. Но после нажатия на пуск, начинают греться нижние N-канальные транзисторы, верхние остаются холодными.

Аватара пользователя
AntonChip
Администратор
Сообщения: 221
Зарегистрирован: 24 дек 2011, 22:11
Откуда: Киров
Контактная информация:

Re: Подключение бесколлекторного двигателя с датчиками Холла к AVR

#5

Сообщение AntonChip » 12 май 2019, 11:25

Какая марка N канальных транзисторов?

Аватара пользователя
Elektron855568
Новичок
Сообщения: 3
Зарегистрирован: 24 янв 2019, 10:50
Откуда: Георгиевск

Re: Подключение бесколлекторного двигателя с датчиками Холла к AVR

#6

Сообщение Elektron855568 » 12 май 2019, 19:21

Спасибо. Разобрался. В печатке накосячил, сам рисовал.

Ответить