STM32 - BLDC Motor Control
Керування безколекторним двигуном постійного струму (BLDC) за допомогою STM32
У якості прикладу розглянемо керування трьохфазним безколекторним двигуном (BLDC Motor) з датчиками Холла. Про алгоритм керування безколекторним двигуном з датчиками Холла я раніше писав у статті Управление бесколлекторным двигателем с датчиками Холла (Sensored brushless motors). У цій статті ми розглянемо лише питання програмування мікроконтролера. Мається на увазі що ви знайомі з алгоритмом керування BLDC з датчиками Холла та розумієтесь на структурі регулятора, а силова частина обрана відповідно до потужності Вашого двигуна. Тому у статті не буде наведена принципова схема, розглядатиметься лише структурна схема з описом призначення виводів мікроконтролера.Загальна інформація
Цей простий приклад демонструє можливості мікроконтролера STM32, і основи керування BLDC двигуном з датчиками Холла. Цей приклад не є готовим рішенням. В ньому не реалізовані системи контролю чи стабілізації параметрів. Не реалізовані систем захисту. Це лише базовий приклад. Тому розглядаючи цей приклад Ви маєте усвідомлювати, що для використання у кінцевих виробах Вам доведеться над ним ґрунтовно попрацювати.Структурна схема підключення STM32
Силова частина, тобто драйвери ключів і самі ключі, використовувалися з попередніх проектів: Схема регулятора скорости бесколлекторного двигателя (ESC). Детальніше про силову частину і ключі можна прочитати тут: Силова частина регулятора BLDC двигунів. Опис силової частини виходить за межі цієї статті. У цій статті розглядається лише структурна схема регулятора і програмна реалізація керуванням BLDC з датчиками Холла за допомогою мікроконтролера STM32.Генерація вихідних сигналів
Перший таймер TIM1 у STM32 дуже потужний інструмент і може виконувати різні цікаві речі. Як я і обіцяв, коли писав про таймери загального призначення, ми розглянемо на практиці деякі можливості першого таймеру. Перший таймер буде генерувати PWM сигнали для 6 ключів силової частини регулятора BLDC. Особливість таймера TIM1 полягає у тому, що він має декілька пар комплементарних виходів. Тобто виходів які можуть працювати у парі. Ми будимо використовувати три пари, кожна пара буде формувати PWM сигнали для верхнього і нижнього ключів. Для верхніх ключів це сигнали UH, VH, WH. Для нижніх - UL, VL, WL. Кожна пара виходів таймера має формувати сигнали таким чином, щоб коли ввімкнутий верхній ключ, нижній був вимкнутий, коли верхній вимикається, вмикається нижній. Крім того, нам треба забезпечити Deadtime. Тобто, проміжок часу для того щоб ключ встиг закритися до того, як відкриється комплементарний ключ. Інакше може виникнути коротке замикання. Цим також буде опікуватися таймер TIM1.Вхідні сигнали
Сигнали від трьох датчиків Холла (H1, H2, H3) подаються на входи мікроконтролера. Комутація ключів відбувається в залежності від стану сигналів з датчиків Холла. Коли відбувається зміна стану датчиків Холла, виникає переривання. Обробник переривання змінює стан вихідних сигналів. Шпаруватість PWM задається потенціометром. Для зчитування даних з потенціометра використовується один з вхідних каналів ADC з використанням DMA. Для відключення вихідних сигналів у разі перевантаження по струму використовується вхід таймеру TIM1_BKIN. Передбачається що на вхід TIM1_BKIN буде подаватись дискретний сигнал з компаратора підключеного до датчика струму. Як бачите для аварійного відключення вихідних сигналів також використовуються ресурси першого таймеру. До того ж відключення відбувається на апаратному рівні. Це виключає виникнення навіть найменших затримок які можуть бути у випадках коли для цього використовується програмне рішення, наприклад використовуються переривання.Програмне забезпечення
Опис налаштувань у файлі bldc.h: BLDC_CHOPPER_PERIOD - задає частоту PWM. Частота PWM у герцах = 72000000/BLDC_CHOPPER_PERIOD Приклади:
#define BLDC_CHOPPER_PERIOD 9000 # - 8КГц
#define BLDC_CHOPPER_PERIOD 4500 # - 16КГц
#define BLDC_CHOPPER_PERIOD 3000 # - 24КГц
#define BLDC_CHOPPER_PERIOD 2250 # - 32КГц
#define BLDC_CHOPPER_PERIOD 1125 # - 64КГц
BLDC_NOL - задає Dead Time. Dead time = BLDC_NOL/72000000 (on 72MHz: 7 is 98ns)
Приклад:
#define BLDC_NOL 72
BLDC_PWMTOPKEYS - генерувати PWM лише на верхніх ключах
BLDC_PWMBOTTOMKEYS - генерувати PWM лише на нижніх ключах
BLDC_PWMTOPBOTTOMKEYS - генерувати PWM на верхніх і нижніх ключах
BLDC_PWMCOMPLEMENTARYMODE - генерувати PWM з використанням комплементарної роботи ключів.
Лише одна з цих опцій має бути ввімкнута.
Приклад:
//#define BLDC_PWMTOPKEYS
//#define BLDC_PWMBOTTOMKEYS
//#define BLDC_PWMTOPBOTTOMKEYS
#define BLDC_PWMCOMPLEMENTARYMODE
Далі йдуть налаштування ADC, тобто пороги спрацювань потенціометра. Нагадаю, показники ADC лежать у межах від 0 до 4096.
BLDC_ADC_START - задає нижній поріг нижче якого вважається мертвою зоною, двигун не запускається.
BLDC_ADC_STOP - задає поріг нижче якого відбувається вимкнення двигуна. Обов`язково має бути менше за BLDC_ADC_START.
BLDC_ADC_MAX - максимальний поріг ADC. Всі значення вище цього порога задають максимальні оберти.
Приклад:
#define BLDC_ADC_START 200
#define BLDC_ADC_STOP 50
#define BLDC_ADC_MAX 4000
Нижче графік, що пояснює як працюють пороги для ADC.
main.c
Дивимось main.c:
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_dma.h"
#include "misc.h"
#include "string.h"
#include "stdio.h"
#include "sysclk.h"
#include "adc_dma.h"
#include "bldc.h"
int main(void)
{
// Set clock
SetSysClockTo72();
// ADC Init
ADC_DMA_init();
// TIM1, outputs, inputs, interrupts, etc. Init
BLDC_Init();
// Reverse pin Init
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_0);
while(1)
{
if (ADCBuffer[0] > BLDC_ADC_START) {
if (BLDC_MotorGetSpin() == BLDC_STOP) {
// Check Reverse pin
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) != 0) {
// Forward
BLDC_MotorSetSpin(BLDC_CW);
}
else {
// Backward
BLDC_MotorSetSpin(BLDC_CCW);
}
BLDC_MotorCommutation(BLDC_HallSensorsGetPosition());
}
BLDC_SetPWM(BLDC_ADCToPWM(ADCBuffer[0]));
}
else {
if (BLDC_MotorGetSpin() != BLDC_STOP) {
if (ADCBuffer[0] < BLDC_ADC_STOP) {
BLDC_MotorStop();
}
}
}
}
}
Мікроконтролер має працювати на частоті 72Мгц з використанням зовнішнього кварцового резонатора частотою 8Мгц. Ця функція налаштовує тактування мікроконтролера:
SetSysClockTo72();
Далі виконується ініціалізація ADC:
ADC_DMA_init();
ADC працює з використанням DMA. Результат перетворення з ADC_Channel_9 зберігається у ADCBuffer[0];
І на кінець виконується ініціалізація BLDC. Налаштовуються виходи і входи, переривання, перший таймер:
BLDC_Init();
У головному циклі програми керуємо двигуном в залежності від положення потенціометра. Зверніть увагу на наступний фрагмент:
if (BLDC_MotorGetSpin() == BLDC_STOP) {
// Check Reverse pin
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) != 0) {
// Forward
BLDC_MotorSetSpin(BLDC_CW);
}
else {
// Backward
BLDC_MotorSetSpin(BLDC_CCW);
}
BLDC_MotorCommutation(BLDC_HallSensorsGetPosition());
}
BLDC_SetPWM(BLDC_ADCToPWM(ADCBuffer[0]));
Він відповідає за старт двигуна. Функція BLDC_MotorSetSpin(BLDC_CCW); задає напрямок обертання двигуна. Оскільки положення ротора вираховується у момент надходження переривань від датчиків Холла, відразу після старту програми контролер може і не знати положення двигуна, оскільки переривання ще не надходили. Тому треба обов`язково перед стартом викликати функцію BLDC_MotorCommutation(BLDC_HallSensorsGetPosition());
У головному циклі також встановлюється шпаруватість PWM. Дивись функцію BLDC_SetPWM. Функція BLDC_ADCToPWM перераховує показник ADC у значення для таймеру в залежності від встановлених лімітів ADC та налаштувань таймеру TIM1, зокрема в залежності від частоти PWM. Якщо Ви плануєте керувати обертами двигуна використовуючи не потенціометр, а інші канали (послідовний порт, тощо), слід використати свою аналогічну функцію яка буде вираховувати значення для запису у таймер. Детальніше про PWM читайте у статті STM32. Програмування STM32F103. TIMER. PWM
Ініціалізація таймера
Ініціалізація першого таймеру, налаштування виходів і TIM1_BKIN відбуваються у функції BLDC_PWMTimerInit. Налаштовується частота PWM:
TIM_TimeBaseStructure.TIM_Period = BLDC_CHOPPER_PERIOD;
Також встановлюється DeadTime:
TIM_BDTRInitStructure.TIM_DeadTime = BLDC_NOL;
Також налаштовується вхід TIM1_BKIN. Зверніть увагу можна задавати рівень сигналу при якому відбувається відключення:
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
Шпаруватість PWM встановлюється для кожного з трьох каналів окремо. Це виконує функція BLDC_SetPWM:
void BLDC_SetPWM(uint16_t PWM)
{
TIM1->CCR1 = PWM;
TIM1->CCR2 = PWM;
TIM1->CCR3 = PWM;
}
Відео
Керування BLDC двигунами з датчиками - це один з найпростіших алгоритмів керування безколекторними двигунами. Простота цього алгоритму досі забезпечує його широке використання. Але...далі буде. Скачати проект можна за наступним посиланням: https://github.com/avislab/STM32F103/tree/master/Example_BLDC Дивись також:
Статті по безколекторним двигунам:
- Бесколлекторный мотор постоянного тока. Что это такое?
- Устройство бесколлекторного мотора
- Управление бесколлекторным мотором с датчиками Холла (Sensored brushless motors)
- Управление бесколлекторными моторами без бездатчиков (Sensorless BLDC)
- Запуск бесколлекторного мотора без бездатчиков (Sensorless BLDC)
- Определение положения ротора бесколлекторного мотора в остановленном состоянии
- Регулятор бесколлекторного мотора. Структура (ESC)
- Схема регулятора бесколлекторного мотора (Схема ESC)
- Силова частина регулятора BLDC двигунів
- Література по безколекторним двигунам.
- Безколекторні двигуни. Приклади програм для мікроконтролера
- Схема регулятора BLDC на STM32
- STM32. Приклад. Керування безколекторним двигуном (BLDC)
- STM32. Приклад. Керування PMSM. Приклади програм
- Видео о бесколлекторных моторах. BLDC, PMSM, векторное управление (російською)
Дивись також:
- 1. STM32. Програмування STM32F103. Тестова плата. Прошивка через UART та через ST-Link
- 2. STM32. Програмування. IDE для STM32
- 3. STM32. Програмування STM32F103. GPIO
- 4. STM32. Програмування STM32F103. Тактування
- 5. STM32. Програмування STM32F103. USART
- 6. STM32. Програмування STM32F103. NVIC
- 7. STM32. Програмування STM32F103. ADC
- 8. STM32. Програмування STM32F103. DMA
- 9. STM32. Програмування STM32F103. TIMER
- 10. STM32. Програмування STM32F103. TIMER. Захоплення сигналу
- 11. STM32. Програмування STM32F103. TIMER. Encoder
- 12. STM32. Програмування STM32F103. TIMER. PWM
- 13. STM32. Програмування STM32F103. EXTI
- 14. STM32. Програмування STM32F103. RTC
- 15. STM32. Програмування STM32F103. BKP
- 16. STM32. Програмування STM32F103. Flash
- 17. STM32. Програмування STM32F103. Watchdog
- 18. STM32. Програмування STM32F103. Remap
- 19. STM32. Програмування STM32F103. I2C Master
- 20. STM32. Програмування STM32F103. I2C Slave
- 21. STM32. Програмування STM32F103. USB
- 22. STM32. Програмування STM32F103. PWR
- 23. STM32. Програмування STM32F103. Option bytes
- 24. STM32. Програмування STM32F103. Bootloader
- STM32. Скачати приклади
- System Workbench for STM32 Інсталяція на Ubuntu
- Keil uVision5 – IDE для STM32
- IAR Workbench – IDE для STM32
- Керування безколекторним двигуном постійного струму (BLDC) за допомогою STM32
- Керування PMSM за допомогою STM32
Бажаю успіхів.
Замечательно ! Вы обещали и так быстро создали этот материал, что я запоздало, прежде чем увидел это, написал комментарий на общей странице для STM32. Я читал http://www.avislab.com/blog/brushless04/ где коментари запрещени, а хотел сообщить, что есть схема с исползованием компараторa LM339 для детекция BEMF zero-crossing, е.t. без применение ADC, которая будет хорошо проанализироват.
Дуже дякую за наведений матеріал. Наскільки я зрозумів, програмна реалізація алгоритму має на увазі, що ми керуемо драйвером з прямими входами. Отже, для керування драйвером у яких інверсний вхід необхідно або інвертувати сигнал для керування драйверами, або змінити алгоритм генерування PWM?
Так, якщо драйвери мають інверсний вхід необхідно просто інвертувати сигнал.
خیلی عالی هست درصورت امکان فایل کامل نرم افزار کنترلی رو میشه دانلود کرد تابتونیم از آن بسازیم متشکرم
а как инвертировать сигнал ?
Hi fantastic work dear engineer. is this code can be modified for STM32F072C8T6, if yes Please let me know how ?? also i want to add the current and voltage sense feature with this
which Compiler is used for Programing ? BLDC motor Con & Other STM32 Code Example Keil IDE ?
Недавні записи
- LCD Display ST7567S (IIC)
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
- DC-DC для IGBT драйверів ізольований 2 W +15 -8 вольт
Tags
battery soldering java-script ngnix adc rs-232 flask esp8266 watchdog web exti solar mongodb rtc sms pwm usart books ethernet smd git websocket meteo css python dc-dc displays led ssd1306 eeprom gpio barometer max1674 mpx4115a brushless motor mpu-6050 timer sensors remap servo bldc atmega pmsm 3d-printer flash encoder examples dma raspberry-pi tim ssd1331 piezo mpu-9250 rfid eb-500 foc bme280 gps nvic dht11 bluetooth hih-4000 stm32 st-link docker uart avr html wifi bmp280 bkp nodemcu options usb lcd programmator i2c capture
Архіви