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

Рейтинг:  4 / 5

Звезда активнаЗвезда активнаЗвезда активнаЗвезда активнаЗвезда не активна
 

Отличие этого проекта от представленного ранее(на ATmega8) состоит в том, что в данной схеме применен микроконтроллер ATmega48, который тактируется от внешнего кварца частотой 16МГц, тем самым была увеличена частота ШИМ импульсов. Для регулировки частоты вращения двигателя используется потенциометр, подключенный к входу ADC3. Переменная speed хранит значение АЦП. При вращении ручки потенциометра, если минимальный порог START_PWM будет превышен, двигатель начнет вращение и можно увеличивать обороты, при обратном вращении ручки двигатель будет снижать обороты и при снижении минимального порога START_PWM двигатель остановится.

Схема устройства

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

Исходный текст программы:

// Управление бесколлекторным двигателем постоянного тока без датчиков на ATmega48
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/wdt.h>

// Фаза U(Верхнее плечо)
#define UH_ON	TCCR2A |=  (1 << COM2A1);
#define UH_OFF	TCCR2A &= ~(1 << COM2A1);

// Фаза U(Нижнее плечо)
#define UL_ON	PORTB |=  (1 << PB5);
#define UL_OFF	PORTB &= ~(1 << PB5);

// Фаза V(Верхнее плечо)
#define VH_ON	TCCR1A |=  (1 << COM1B1);
#define VH_OFF	TCCR1A &= ~(1 << COM1B1);

// Фаза V(Нижнее плечо)
#define VL_ON	PORTB |=  (1 << PB4);
#define VL_OFF	PORTB &= ~(1 << PB4);

// Фаза W(Верхнее плечо)
#define WH_ON	TCCR1A |=  (1 << COM1A1);
#define WH_OFF	TCCR1A &= ~(1 << COM1A1);

// Фаза W(Нижнее плечо)
#define WL_ON	PORTB |=  (1 << PB0);
#define WL_OFF	PORTB &= ~(1 << PB0);

#define PHASE_ALL_OFF   UH_OFF;UL_OFF;VH_OFF;VL_OFF;WH_OFF;WL_OFF;
 
#define SENSE_U     ADMUX = 0; // Вход обратной ЭДС фазы U
#define SENSE_V     ADMUX = 1; // Вход обратной ЭДС фазы V
#define SENSE_W     ADMUX = 2; // Вход обратной ЭДС фазы W
 
#define SENSE_UVW   (ACSR&(1 << ACO)) // Выход компаратора
 
#define START_PWM   50 // Минимальный ШИМ при запуске

unsigned char position, speed;
volatile unsigned char commutation_step = 0;
volatile unsigned char rotor_run = 0; // Счетчик импульсов обратной ЭДС

// Крутим по часовой стрелке
void commutation(char startup)
{
	switch (commutation_step)
	{
		case (0):
			if(!SENSE_UVW || startup) 
			{
				UH_ON; // На фазе U - ШИМ
				WH_OFF; // Фаза W отключена
				SENSE_W; // Активируем вход фазы W
				commutation_step = 1; // Следующий шаг
				TCNT0 = 0; // Обнуляем счетчик T1
			}
			break;

		case (1):
			if(SENSE_UVW || startup)
			{
				VL_OFF; // На фазе V - лог. 0
				WL_ON;  // На Фазе W - лог. 1
				SENSE_V; // Активируем вход фазы V
				commutation_step = 2;
				TCNT0 = 0; // Обнуляем счетчик T1
			}
			break;

		case (2):
			if(!SENSE_UVW || startup)
			{
				UH_OFF; // Фаза U отключена
				VH_ON;  // На фазе V - ШИМ
				SENSE_U; // Активируем вход фазы U
				commutation_step = 3;
				TCNT0 = 0; // Обнуляем счетчик T1
			}
			break;
	
		case (3):
			if(SENSE_UVW || startup)
			{
				UL_ON;  // На фазе U - лог. 1
				WL_OFF; // На Фаза W - лог. 0
				SENSE_W; // Активируем вход фазы W
				commutation_step = 4;
				TCNT0 = 0; // Обнуляем счетчик T1
			}
			break;

		case (4):
			if(!SENSE_UVW || startup)
			{
				VH_OFF;  // Фаза V отключена
				WH_ON;   // На фазе W - ШИМ
				SENSE_V; // Активируем вход фазы V
				commutation_step = 5;
				TCNT0 = 0; // Обнуляем счетчик T1
			}
			break;

		case (5):
			if(SENSE_UVW || startup)
			{
				UL_OFF; // На фазе U - лог. 0
				VL_ON;  // На Фазе V - лог. 1
				SENSE_U; // Активируем вход фазы U
				commutation_step = 0;
				TCNT0 = 0; // Обнуляем счетчик T1
			}
			break;
	}
}

// Обработчик прерывания по компаратору. Детектор обратной ЭДС
ISR(ANALOG_COMP_vect)
{
if(rotor_run == 200) commutation(0);
rotor_run++;
if(rotor_run > 200)
{
rotor_run = 200;
wdt_reset();
}
}

// Обработчик прерывания по переполнению Т0. Работа двигателя без сигналов обратной ЭДС
ISR(TIMER0_OVF_vect)
{  
commutation(1); // Если сработало прерывание, есть пропуски импульсов обратной ЭДС
rotor_run = 0;  // Сбрасываем счетчик импульсов
OCR1A = START_PWM; // ШИМ минимум
OCR1B = START_PWM;
OCR2A = START_PWM;
}

int main( void )
{
//Watchdog on
wdt_enable(WDTO_1S);

// Порты ввода/вывода
DDRB = 0xFF; // Порт B - выход
PORTB = 0x00; 

// T0 - для старта и работы двигателя без сигналов обратной ЭДС
TCCR0A = 0;
TCCR0B = 0;
TCCR0B |= (1 << CS02)|(1 << CS00); // Предделитель на 1024
TIMSK0 |= (1 << TOIE0); // Разрешаем прерывание по переполнению T0

// T1 и T2 ШИМ
TCCR1A |= (1 << WGM10);  // Режим Fast PWM, 8-bit
TCCR1B |= (1 << CS10)|(1 << WGM12); // Без предделителя

TCCR2A |= (1 << COM2A1)| // Сброс вывода OC2A при совпадении
          (1 << WGM21)|(1 << WGM20);   // Режим Fast PWM
TCCR2B |= (1 << CS20); // Без предделителя

PHASE_ALL_OFF; // Выключаем все фазы

ADCSRB |= (1 << ACME); // Отрицательный вход компаратора подключаем к выходу мультиплексора АЦП
DIDR1 |= (1 << AIN0D);

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

while(1)
{
cli();
position = ADMUX; // Сохраняем позицию ротора в буфер
ADMUX = (1 << MUX1)|(1 << MUX0); // Вход ADC3  
ADCSRA |= (1 << ADEN) | (1 << ADPS1)|(1 << ADPS0); // Разрешаем АЦП, предделитель на 8
ADCSRA |= (1 << ADSC); // Запускаем преобразование АЦП
while(ADCSRA & (1 << ADSC)){}; // Ждем окончания преобразования
speed = ADC/4;
ADCSRA = 0; // Выключаем АЦП
ADCSRB = 0;
ADCSRB |= (1 << ACME); // Отрицательный вход компаратора подключаем к выходу мультиплексора АЦП
ADMUX = position;
sei();

if(speed > START_PWM)
{
ACSR |= (1 << ACIE); // Разрешаем прерывание от компаратора
TIMSK0 |= (1 << TOIE0); // Разрешаем прерывание по переполнению T0
  
  if(rotor_run == 200)
  { // Если импульсы обратной ЭДС присутствуют, крутим наполную
  OCR1A = speed;
  OCR1B = speed; // Изменяем ШИМ
  OCR2A = speed;
  }
}
else
{
PHASE_ALL_OFF; // Все фазы выключены
ACSR &= ~(1 << ACIE); // Запрещаем прерывание от компаратора
TIMSK0 &= ~(1 << TOIE0); // Запрещаем прерывание по переполнению T0
}

}
}

Видео работы устройства


Архив для статьи "Управление бесколлекторным двигателем постоянного тока без датчиков на ATmega48"
Описание:

Проект AVRStudio4, макет печатной платы DipTrace

Размер файла: 54.28 KB Количество загрузок: 112 Скачать

Метки: ATmega48, Бесколлекторный двигатель, IR2101

Печать E-mail

Комментарии  

0 #1 gsaorion 27.09.2018 22:47
Здравствуйте AntonChip! можно получить ваш адрес эл. почты?
Сообщить модератору
0 #2 AntonChip 28.09.2018 08:05
Цитирую gsaorion:
Здравствуйте AntonChip! можно получить ваш адрес эл. почты?

Здравствуйте, все данные в разделе "Контакты"
Сообщить модератору

Авторизация