2-x фазный ШИМ (PWM) генератор на STM32F030F4

Для питания ряда устройств (например электродвигателей переменного тока) иногда необходимо наличие сдвинутых по фазе питающих напряжений. Для питания 2-х фазных индукционных двигателей необходимо наличие двух фаз синусоидального напряжения с частотой 400 Герц и сдвинутых по фазе на 90 градусов. Один из примеров таких двигателей являются двигатели серии ДИД. Они интересны тем, что их частота вращения может составлять от 16000 до 18000 об/мин. Для питания таких двигателей и было сделано данное устройство, которое представляет собой задающий генератор 2-х фазного 400 Гц напряжений сдвинутых по фазе на 90 градусов относительно друг друга.
В качестве микроконтроллера использован STM32F030F4. Его выбор обусловлен его «минимализмом» — наименьший из корпусов в серии STM32F0 и естественно с минимальной стоимостью. Схема подключения изображена ниже. Микроконтроллер работает на частоте 48 МГц. В качестве задающего генератора использован TIM3, так как в данном контроллере только этот таймер можно конфигурировать так, чтобы использовать выходы трех каналов. Третий канал можно в случае необходимости использовать для генерации 3-фазного напряжения. Таймер работает в режиме генерации ШИМ (PWM). Для получения синусоидального напряжения 400 Гц в канале используется высокочастотное изменение коэффициента ШИМ с частотой 40 кГц, на которую настроен системный таймер SysTick. Синусоида формируется с помощью таблицы значений синуса с шагом 360/100 градусов. Очень полезный калькулятор для такого рода таблиц можно найти на сайте. При желании с помощью АЦП можно управлять амплитудой, фазой, частотой генерации. Но в данной реализации это не сделано.



Ниже показаны выходные осциллограммы генератора. Синяя и фиолетовая синусоиды — сдвинуты на 90 градусов, желтая — выход таймера для синей синусоиды, зеленый — тестовый сигнал генерируемый при начале формирования синусоиды



Ниже приводится текст программы для STM32F030F4. При желании данный принцип можно реализовать и на STM32F103 вариант для STM32F103.

#include «stm32f0xx.h»

int t1,t2;

const int table[125]={
240,255,270,285,300,314,328,342,
356,369,381,393,404,415,425,434,
443,450,457,463,468,472,476,478,
480,480,480,478,476,472,468,463,
457,450,443,434,425,415,404,393,
381,369,356,342,328,314,300,285,
270,255,240,225,210,195,180,166,
152,138,124,111,99,87,76,65,
55,46,37,30,23,17,12,8,
4,2,0,0,0,2,4,8,
12,17,23,30,37,46,55,65,
76,87,99,111,124,138,152,166,
180,195,210,225,240,
//
240,255,270,285,300,314,328,342,
356,369,381,393,404,415,425,434,
443,450,457,463,468,472,476,478
};

void ConfigureHSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/******************************************************************************/
/* HSE used as System clock source */
/******************************************************************************/
/* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
/* Enable HSE */
RCC->CR |= RCC_CR_HSEON;
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != 5000));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = 0x01;
}
else
{
HSEStatus = 0x00;
}

if (HSEStatus == 0x01)
{
/* Enable Prefetch Buffer and set Flash Latency */
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;

/* HCLK = SYSCLK / 1 */
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

/* PCLK = HCLK / 1 */
RCC->CFGR |= RCC_CFGR_PPRE_DIV1;

/* Select HSE as system clock source */
// RCC->CFGR &= ~(RCC_CFGR_SW_PLL);
// RCC->CFGR |= RCC_CFGR_SW_HSE;
RCC->CFGR |= RCC_CFGR_SWS_PLL;
RCC->CFGR |= RCC_CFGR_SW_PLL;
/* Wait till HSE is used as system clock source */
// while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE)
// {
// }
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}

int main(void)
{
ConfigureHSE(); //only for quarz synhro
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER7)) | (GPIO_MODER_MODER7_1);
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER6)) | (GPIO_MODER_MODER6_1);
GPIOB->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER1)) | (GPIO_MODER_MODER1_1);
GPIOA->AFR[0] |= 0x11000000;
GPIOB->AFR[0] |= 0x00000010;

TIM3->PSC = 0; //APBCLK=48 MHz
TIM3->ARR = 480;
TIM3->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE;
TIM3->CCMR1 |= TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE;
TIM3->CCMR2 |= TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE;

TIM3->CCER |= TIM_CCER_CC1E;
TIM3->CCER |= TIM_CCER_CC2E;
TIM3->CCER |= TIM_CCER_CC4E;
TIM3->BDTR |= TIM_BDTR_MOE;
TIM3->CR1 |= TIM_CR1_CMS_0 | TIM_CR1_CEN;
TIM3->EGR |= TIM_EGR_UG;
SysTick_Config(1200); // 40 kHz
__enable_irq ();
t1=0;
t2=0;
while (1)
{
__WFI();
}
}
///////////////////////////////////////////////////////////////////////////
void SysTick_Handler(void)
{
t1++;
if(t1>=100){t1=0;}
t2++;
if(t2>=100){t2=0;}

TIM3->CCR1=(table[t2+25]);
TIM3->CCR2=(table[t1]);
TIM3->CCR4=table[t1+50];
}
Файлы в топике: PWM.zip

Комментарии (78)

RSS свернуть / развернуть
Код засунь в тег <code>. Причем скопипасти из исходника заново, тут у него индентация побилась.
0
  • avatar
  • Vga
  • 27 мая 2015, 18:01
код убрал под кат, а отступы не выходят, в аттаче в принципе готовый проект
Keil
0
Чтобы отступы выходили, нужно под
писать же.
0
Тег code используй. Там даже специальная кнопочка в редакторе есть, и в справке написано. Но разве ж справку кто-то кроме меня читает?
0
Честно сказать, схема и программа это все хорошо. Но я как и многие теорию не то что не люблю, но испытываю некоторую неловкость если она не подкреплена практикой. Я думаю мне, и не только мне хотелось бы видеть готовое работающее устройство. Думаю тогда многие споры отпали бы сами собой, либо стали бы ещё ожесточённей.
0
Хмм. Что сложного в том, что бы добавить пару схем из даташита и сделать готовое устройство под свои задачи? А так, как по мне, автор сделал все правильно — заготовка («строительный блок») из которой с минимальными усилиями можно сделать свое решение под свои условия и требования.
+1
нужно фото макетки-переходника TQFP-DIP с двумя конденсаторами и резисторами?
просто устройство задумано как составная часть блока питания для высокооборотистого двигателя
0
Да вовсе нет. Просто не часто, но все таки сталкиваюсь с абсолютно не работающими схемами. Не в обиду.
0
Я чего-то не понял. То есть это тупо квадратурный генератор (генерирует одновременно синус и косинус) на частоту 400 Гц, и все? Ни изменения частоты, ни подстройки фазового сдвига, ни какого-нибудь ПИД-контроллера?

В таком случае, не дешевле ли выйдет LM358?



Вот познавательный документ, и еще один, рекомендую.
0
кроме «тупого» синуса есть его ШИМ-генерация, которая позволяет легко увеличивать его ключевыми каскадами, если посмотреть код, то можно увидеть, что сдвиг фаз можно установить любой от 0 до 360 градусов, кроме того есть кварцевая стабилизация частоты, кроме того можно получить и три фазы хоть по 120 градусов (правда не 380 Вольт...)
0
Можно, путем перекомпиляции кода и перезаливки прошивки. В устройстве я такой возможности не вижу. И что-то меня берут сомнения, что двигателю нужна кварцевая стабилизация частоты… Ну а ШИМ, если это самоцель, тоже можно получить куда более дешевыми средствами, да и три фазы тоже. Пока что я вижу оверкилл громадных масштабов.
0
буду признателен за ссылки на получение ШИМа «куда более дешевыми средствами»
0
Не поверите, но это делается на таймере 555, куда уж дешевле…
0
… не вижу по Вашей ссылке 2-Х ФАЗНОГО ШИМа, тем более 3-х фазного
0
Там показан принцип. Чтобы получить двухфазный ШИМ, достаточно взять сдвоенную модификацию 555 — 556. Трехфазный — счетверенную модификацию, 558. По цене они почти не отличаются, полюбому выходит около 20 р. вместе с LM358.

Разумеется, по моим ссылкам показаны отдельные блоки. Но в цельную схему они собираются элементарно. Все эти решения известны уже сто лет.
0
проблема будет в поддержании точного сдвига в 90 градусов и невозможности кварцевой стабилизации частоты, которая в данном случае для меня очень важна, ибо двигатель для которого это все сделано используется в обтюраторе для синхронно-фазового детектора лазерного излучения и точность при применении Ваших 555 таймеров получается низкой
+2
На МК ST просто дешевле и обвязки меньше. И никаких подстроечников. Дешево, надежно, практично (С) :)
0
Ну а ШИМ, если это самоцель, тоже можно получить куда более дешевыми средствами, да и три фазы тоже.
Учитывая цену STM32F030F4 — это не так просто. Особенно если учитывать сложность получающейся схемы и ее трассировку. Опять же, здесь можно просто модифицировать прошивку и все требуемые параметру сразу станут настраиваемыми.
+1
Учитывая, что LM358 и 555 продаются почти по цене песка, это все не так сложно. Да и 400 Гц/40 кГц не те частоты, где начинаются сложности.

Применять ключевой режим транзисторов имеет смысл на большой нагрузке. А на большой нагрузке при 40 кГц драйверы полевиков уже будут отдельной задачей куда сложнее цепей генерации сигнала, как в плане выбора деталей, так и в плане трассировки.
0
нагрузка не такая уж и маленькая 50-100 Ом, а
при применении УНЧ для усиления 400 Гц синусоид
необходимо будет питание для него под 50 Вольт
0
А на большой нагрузке при 40 кГц драйверы полевиков уже будут отдельной задачей куда сложнее цепей генерации сигнала, как в плане выбора деталей, так и в плане трассировки.
Драйверы полевиков давно не проблема, решения есть практически на все случаи жизни. Более того, для специфичных применений есть и специализированные решения. Скажем, для 3-фазных двигателей под разные напряжения можно применить IRF2136xxx (из там целый выводок) или DRV8301/2. У последних, помимо драйверов, еще и остальная аналоговая часть прямо в пузе (усилители сигнала с шунтов). Ну а об отдельных драйверах полумостов можно целые трактаты писать, уж чего-чего, а этого добра предостаточно. Ах да, чуть не забыл: как правило драйвера весьма удобны в разводке. И получить правильный сигнал даже на 500-600кГц не составляет труда, тем более на типичных, для драйверов двигателей, 30-100кГц.
0
Это да. Правда, в этом случае соображения экономии на формирующей части отходят на второй план, а вот тот факт, что аналоговая схема не может повиснуть и не требует написания прошивки и наличия программатора, становится гораздо ценнее.
0
в заголовке статьи нет слова «экономичный», если Вас не устраивает цена данного решения, то ради бога, используйте 555 таймеры
0
а вот тот факт, что аналоговая схема не может повиснуть
С ней может случиться что-нибудь другое. Например, уход частоты (и уползание по фазе). К слову, схема на мк при правильно написанной прошивке тоже не может повиснуть (watchdog timer, да).
не требует написания прошивки и наличия программатора
Зато требует периодической проверки и подстройки.
становится гораздо ценнее.
Особенно когда смотришь на счет за электроэнергию или батарейки.
0
тут самое главное, что нужно получить напряжения для двигателя 36 вольт,
а для усиления сигнала от операционников нужен УНЧ, а тут при наличии ШИМа
можно обойтись ключевым каскадом
0
Что в ключевом каскаде транзистор, что в усилительном, разве нет? «А если разницы нет, то зачем платить больше?»
0
На ключевом каскаде выделяется 1% потребляемой схемой мощности, а на линейном — 50%. А это, помимо траты искричества впустую означает хороший радиатор — который, вероятно, будет куда дороже транзистора.
0
Ну в таком случае комбинацию из дешевого 32битного мк и ключа, ничем не переплюнуть как по цене, так и функциональным возможностям.
0
Вот потому оно обычно так и делается) Хотя тут и менее мощный МК справился бы, вроде атмеги.
0
«дешевые» Atmega не обладают многоканальными таймерами и потом, цена STM32F030F4 — 0,5$
+2
Насколько я помню, как минимум двухканальные — есть. Да и синхронизации ШИМов в твоем случае вроде не требуется, так что можно припахать второй таймер и получить третий канал. И ESC'и на ATMEGA8 делают вполне успешно.
0
в Киеве Atmega8 стоит в 2-3 раза дороже, используемой STM-ки
0
А я и не говорил, что «менее мощный МК» дешевле. Да и против STM32F0 ничего не имею. Вот решение с 40кГц прерыванием от SysTick мне не нравится, на таком камне можно сделать красивше.
+1
Ну атмеги не настолько дешевы, или нет?
Я вот не в курсе, появилось ли что-нибудь на рынке 8битных мк, что бьет по отношению цена/функционал stm8s003f3?
0
Лично я таких пока не встречал. По ходу тут пока абсолютный рекорд по цене даже среди куда более бедных по ресурсам МК. У них разве что по размерам есть конкуренты…
0
Если б ребята из ST сделали бы STM8 в SOT-23-6 (в таких корпусах, например, живут ATTINY4 и PIC10F20) — это было бы бомбой на мой взгляд. Ну при небольшой цене соответственно.
+2
это сделали
ребята из NXP. Ждем ответки от ST
0
Не совсем понятно на кого ориентированы в нынешнее то время такие дип корпуса, не на любителей же?)
А вот бюджетный супермикропотребляющий мк в козявочном корпусе с каким нибудь интерфейсом, да АЦП, да таймером с шимом на пару каналов был бы просто шикарен. И совесть была бы спокойна насчет пихания его куда ни попадя. А то: «Оверкил, оверкил» =)
0
остается вопрос зачем?
0
В макетку воткнуть.
0
да хер с ним с корпусом. Кортекс в дип8…
0
в смысле восьминогий.
0
А я про цену ничего и не говорил. Хотя если шарить по рознице, цена на стм-ки задрана и не сильно отличается от атмег.
Но в качестве менее мощного можно привести и STM8S003 — они, полагаю, тоже справятся и стоят в пару раз дешевле (опять же, есть нюансы — например, я видел в рознице 103 дешевле чем аналогичный 003).
0
Ну под ценами я понимаю в первую очередь заказ из доступного места с учетом доставки в количестве 5-10 шт. Нафиг, нафиг розничные мк — за них цены огого и выбор ограничен.
+1
«В количестве 5-10 штук» я нашел только у знакомого, у которого и выпросил десяток S003-х из купленной им сотни. Просмотренные магазины предлагали вменяемую цену только от 100шт.
0
Вменяемая это сколько? На али можно найти лоты из 10шт где цена на микруху получается 20р/шт. Вполне вменяемо на мой взгляд.
0
Ну, я по отечественным шарился. До 100шт там были цены в стиле 20р за STM8S003F3 и 50р за STM32F030F4 — причем это было еще до декабрьского кризиса.
0
Сейчас цены на удивление выравнялись примерно 30-35р что за один, что за второй (База Электроники).
0
Во-во. Особенно странно видеть, как удешевленная версия стоит дороже базовой (такое реально было в Промэлектронике, где STM8S003K3 стоил дороже чем STM8S103K3 — причем последний стоил вполне вменяемо, 20р).
0
20 ногие qfn беру в районе 15р при партии в сотню. но дма нет. и да, справятся, но только по тому же принципу что и в статье.
0
справятся, но только по тому же принципу что и в статье
Забавно, но именно потому я про них и вспомнил. От «генератора на STM32F030» ожидал более интересного решения — например, генерации исключительно силами периферии.
0
та же фигня. подумываю на что то более умное перейти как раз из-за ограничений периферии, вынуждающих кодить, а не тупо конфигурировать xD
0
На этих МК можно сигнал генерировать и не загружая ядро сорока тысячами IRQ в секунду. Полагаю, можно сделать вообще чисто аппаратную генерацию, в которой ядро не будет участвовать вообще. Даже если на проце все равно нечего больше крутить — аппаратная генерация периферией будет стабильнее и с меньшим джиттером.
+1
  • avatar
  • Vga
  • 27 мая 2015, 18:53
дма прикрутить предлагаешь?:)
0
Я не настолько хорошо знаю периферию STM32F0) Но полагаю да, если DMA у этих МК есть.
0
чисто аппаратно можно сделать с помощью DMA, пересылая в таймер таблицу синусов (может когда-нибудь и напишу такой вариант, если нужно будет освобождать процессорное время)
0
А у Вас не закралась ошибка в таблицу синуса?
Там где два слэша, два раза повторяется значение 240.

Я построил такую же таблицу синуса для индексов от 0 до 124 по модулю 100 и сравнил их.
И как раз с этого места значения стали сдвинуты на 1 отсчет.
0
спасибо за внимательность, но ошибки нет, просто после слешей идет повтор первых 25 начальных значений синуса. Это сделано для удобства при формировании значений сдвинутых фаз. Кстати добавил в статью ссылочку на полезный калькулятор думаю Вам будет интерестно в плане упрощения построения подобных таблиц
+1
Маленький вопрос, скорее чтобы придраться, а не по теме: почему у вас (по схеме) микроконтроллер в режиме сброса работает?
0
спасибо за замечание, исправил
0
А переменные t1 и t2 кто инкрементирует? Роберт Рождественский? Зачем выкладывать код с ошибками?
+1
спасибо за замечание, исправил
0
У вас переменные так и тикают в бесконечность (точнее до 2147483647)? Чего то не нашел опроса этого момента. И доступ к массиву table у вас примерно через 75 тиков вылезет за его пределы и в лучшем случае ваша прога выпадет в DefaultAbortHandler. В худщем — выдаст какой-то такой хитрый синус, что моторчик будет бешено вертеться :)
Вы точно эту программу запускали?
0
поправил…
просто в тексте исходник представлен как выжимка из части программы.
в аттаче проект рабочий
0
синхронных индукционных двигателей

Как индукционный двигатель может быть синхронным?
0
Вы правы «синхронный» — лишнее — убрал
0
А что это за зверь вообще? Обычный асинхронник?
0
Да, индукционными называют асинронники.
0
А есть где-нить изображение устройства этих ДИД? Я немного погуглил, но с полпинка не нашел.
0
0
В следующий раз просто комп включите, чтоб светодиодом поморгать, пентиум вполне справится.
-1
А куда вы к современному компу светодиодик подключите?
0
даже если в компе нет ниодного разъёма с прямым доступом типа LPT, COM, GAME, IRDA, AUDIO
, а на компах в P4 сомневаюсь что какой-то из них отсутствует,
я воткну светодиод в угол экрана через фотодатчик или тот же светодиод с обратно смещёным включением и мне таки удастся поморгать и поуправлять чем угодно.
:)
0
Тогда вы немного опоздали с комментарием. dcoder уже оформил серию постов про мигание светодиодиком с монитора, да и медленный программатор там тоже был.
+1
так вот ты сам на свой вопрос ответил, зачем же мне его задавать?
— Риторический вопрос это был.
-1
да, и ещё бывают светодиоды скроллок нумлок, капслок и светодиод питания монитора\нуоутбука для исключительных случаев
— Надеюсь убедил.
0
Архив поврежден, или имеет неизвестный формат
0
перезалил файл
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.