Перейти к содержанию

Помогите модифицировать программу управления бесколлекторным двигателем постоянного тока.


Рекомендуемые сообщения

Здравствуйте товарищи!

Прошу Вас помочь советом о модификации программы управления бесколлекторным двигателем постоянного тока.

Повторил следующую схему:

post-32116-0-41061500-1500409447_thumb.gif

Всё запустилось и отлично работает. Хочу теперь миниатюризировать плату и убрать лишний функционал в виде кнопки запуска и выбора стороны вращения. Опыта в программировании явно не достаёт.

Исходный код:

 

// Подключение бесколлекторного двигателя к AVR(без датчиков)

#include <avr interrupt.h="">

#include <avr io.h="">

#include <util delay.h="">

 

// Фаза U(Верхнее плечо)

#define UH_ON TCCR1A |= (1 << COM1A1);

#define UH_OFF TCCR1A &= ~(1 << COM1A1);

 

// Фаза U(Нижнее плечо)

#define UL_ON PORTB |= (1 << PB5);

#define UL_OFF PORTB &= ~(1 << PB5);

 

// Фаза V(Верхнее плечо)

#define VH_ON TCCR2 |= (1 << COM21);

#define VH_OFF TCCR2 &= ~(1 << COM21);

 

// Фаза V(Нижнее плечо)

#define VL_ON PORTB |= (1 << PB0);

#define VL_OFF PORTB &= ~(1 << PB0);

 

// Фаза W(Верхнее плечо)

#define WH_ON TCCR1A |= (1 << COM1B1);

#define WH_OFF TCCR1A &= ~(1 << COM1B1);

 

// Фаза W(Нижнее плечо)

#define WL_ON PORTB |= (1 << PB4);

#define WL_OFF PORTB &= ~(1 << PB4);

 

#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 10 // Минимальный ШИМ при запуске

#define WORK_PWM 100 // Рабочий уровень ШИМ

 

unsigned char start_stop = 0;

volatile unsigned char motor_pwm = WORK_PWM;

volatile unsigned char commutation_step = 0;

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

 

// Крутим по часовой стрелке

void commutation(unsigned 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; // Обнуляем счетчик T0

}

break;

 

case (1):

if(SENSE_UVW || startup)

{

VL_OFF; // На фазе V - лог. 0

WL_ON; // На Фазе W - лог. 1

SENSE_V; // Активируем вход фазы V

commutation_step = 2;

TCNT0 = 0; // Обнуляем счетчик T0

}

break;

 

case (2):

if(!SENSE_UVW || startup)

{

UH_OFF; // Фаза U отключена

VH_ON; // На фазе V - ШИМ

SENSE_U; // Активируем вход фазы U

commutation_step = 3;

TCNT0 = 0; // Обнуляем счетчик T0

}

break;

 

case (3):

if(SENSE_UVW || startup)

{

UL_ON; // На фазе U - лог. 1

WL_OFF; // На Фаза W - лог. 0

SENSE_W; // Активируем вход фазы W

commutation_step = 4;

TCNT0 = 0; // Обнуляем счетчик T0

}

break;

 

case (4):

if(!SENSE_UVW || startup)

{

VH_OFF; // Фаза V отключена

WH_ON; // На фазе W - ШИМ

SENSE_V; // Активируем вход фазы V

commutation_step = 5;

TCNT0 = 0; // Обнуляем счетчик T0

}

break;

 

case (5):

if(SENSE_UVW || startup)

{

UL_OFF; // На фазе U - лог. 0

VL_ON; // На Фазе V - лог. 1

SENSE_U; // Активируем вход фазы U

commutation_step = 0;

TCNT0 = 0; // Обнуляем счетчик T0

}

break;

}

}

// Обработчик прерывания по компаратору. Детектор обратной ЭДС

ISR(ANA_COMP_vect)

{

rotor_run++; // инкрементируем импульсы

if(rotor_run > 200) rotor_run = 200;

if(rotor_run == 200) // Если импульсы обратной ЭДС присутствуют, крутим наполную

commutation(0);

}

// Обработчик прерывания по переполнению Т0. Работа двигателя без сигналов обратной ЭДС

ISR(TIMER0_OVF_vect)

{

commutation(1); // Если сработало прерывание, есть пропуски импульсов обратной ЭДС

rotor_run = 0; // Сбрасываем счетчик импульсов

OCR1A = START_PWM; // ШИМ минимум

OCR1B = START_PWM;

OCR2 = START_PWM;

}

// Обработчик внешнего прерывания INT0. Энкодер

ISR(INT0_vect){

_delay_us(100);

if ((PIND & ( 1 << PD2)) == 0){

_delay_us(100);

// Крутим против часовой стрелки

if ((PIND & ( 1 << PD1)) == 0)

{

if(motor_pwm != START_PWM) motor_pwm -= 5; // Уменьшаем ШИМ

}

// Крутим по часовой стрелке

else

{

if(motor_pwm != 255) motor_pwm += 5; // Увеличиваем ШИМ

}

}

GIFR = (1 << INTF0); // Сбрасываем флаг внешнего прерывания

return;

}

 

int main (void)

{

// Порты ввода/вывода

DDRB = 0xFF;

PORTB = 0x00;

DDRD &= ~(1 << PD6)|(1 << PD2)|(1 << PD1)|(1 << PD0);

PORTD |= (1 << PD2)|(1 << PD1)|(1 << PD0);

PORTD &= ~(1 << PD6);

 

// T0 - для старта и работы двигателя без сигналов обратной ЭДС

TCCR0 |= (1 << CS02)|(1 << CS00); // Предделитель на 1024

TIMSK |= (1 << TOIE0); // Разрешаем прерывание по переполнению T0

// T1 и T2 ШИМ

TCCR1A |= (1 << COM1A1)|(1 << COM1B1)| // Clear OC1A/OC1B, set OC1A/OC1B at BOTTOM

(1 << WGM10); // Режим Fast PWM, 8-bit

TCCR1B |= (1 << CS10)|(1 << WGM12); // Без предделителя

TCCR2 |= (1 << COM21)| // Clear OC2, set OC2 at BOTTOM

(1 << WGM21)|(1 << WGM20)| // Режим Fast PWM

(1 << CS20); // Без предделителя

 

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

 

// Аналаговый компаратор

ADCSRA &= ~(1 << ADEN); // Выключаем АЦП

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

ACSR |= (1 << ACIE); // Разрешаем прерывания от компаратора

 

// Внешнее прерывание(Энкодер)

MCUCR |= (1 << ISC01); // Прерывание по заднему фронту INT0(по спаду импульса)

GIFR |= (1 << INTF0); // Очищаем флаг внешнего прерывания

GICR |= (1 << INT0); // Разрешаем внешние прерывания INT0

 

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

 

while(1)

{

if((PIND&(1 << PD0)) == 0) // Старт/Стоп

{

_delay_ms(20);

start_stop ^= 1; // Переключаем состояние

while((PIND&(1 << PD0)) == 0){}

}

 

if(start_stop)

{

ACSR |= (1 << ACIE); // Разрешаем прерывание от компаратора

TIMSK |= (1 << TOIE0); // Разрешаем прерывание по переполнению T0

GICR |= (1 << INT0); // Разрешаем внешние прерывания INT0

 

if(rotor_run == 200) // Если импульсы обратной ЭДС присутствуют, можем менять ШИМ

{

OCR1A = motor_pwm;

OCR1B = motor_pwm;

OCR2 = motor_pwm;

}

}

else

{

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

ACSR &= ~(1 << ACIE); // Запрещаем прерывание от компаратора

TIMSK &= ~(1 << TOIE0); // Запрещаем прерывание по переполнению T0

GICR &= ~(1 << INT0); // Запрещаем внешние прерывания INT0

}

 

}

}

 

 

Хочу, чтобы при подачи питания движок вращался сразу по часовой стрелке, без внешнего прерывания от кнопки. И даже примерно понимаю, что нужно изменить код где-то в этом блоке:

 

 

// Обработчик внешнего прерывания INT0. Энкодер

ISR(INT0_vect){

_delay_us(100);

if ((PIND & ( 1 << PD2)) == 0){

_delay_us(100);

// Крутим против часовой стрелки

if ((PIND & ( 1 << PD1)) == 0)

{

if(motor_pwm != START_PWM) motor_pwm -= 5; // Уменьшаем ШИМ

}

// Крутим по часовой стрелке

else

{

if(motor_pwm != 255) motor_pwm += 5; // Увеличиваем ШИМ

}

}

GIFR = (1 << INTF0); // Сбрасываем флаг внешнего прерывания

return;

}

 

 

 

Но, что именно и как понять не могу.

Изменено пользователем Wishmaster
Ссылка на комментарий
Поделиться на другие сайты

Добрый день, Дмитрий.

 

Попробуйте из этого куска

 

if((PIND&(1 << PD0)) == 0) // Старт/Стоп

{

_delay_ms(20);

start_stop ^= 1; // Переключаем состояние

while((PIND&(1 << PD0)) == 0){}

}

 

оставить только

 

start_stop = 1;

Изменено пользователем erbol
  • Я с тобой! 1
Ссылка на комментарий
Поделиться на другие сайты

+

... Хочу, чтобы при подачи питания движок вращался сразу по часовой стрелке, без внешнего прерывания от кнопки. ...

 if(rotor_run == 200) // Если импульсы обратной ЭДС присутствуют, можем менять ШИМ
 {
 OCR1A = motor_pwm;
 OCR1B = motor_pwm;
 OCR2 = motor_pwm;
 }

Если вам не нужна регулировка вращения, то в регистры PWM нужно будет забить какое то конкретное значение, в зависимости от необходимой скорости.

Изменено пользователем Sergiy_83
Ссылка на комментарий
Поделиться на другие сайты

  • 3 недели спустя...

Здравствуйте товарищи!

Прошу Вас помочь советом о модификации программы управления бесколлекторным двигателем постоянного тока.

 

 

Дмитрий, добрый день!

А можно попросить ссылку на первоисточник данной схемы. интересно посмотреть для каких целей и с какими движками она там применялась.

Для своих целей попробовать использовать.

Спасибо!

Ссылка на комментарий
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...