Поднять частоту ШИМа с коррекцией фазы на AVR

Все о микроконтроллерах: AVR, PIC, STM8, STM32, Arduino, Altera, Xilinx, все что угодно. Этот раздел для всего что клацает байтиками.
Аватара пользователя
Kubrikov
Сообщения: 43

Сообщение Kubrikov » 21 июл 2018, 17:28

Парни! Делаю мощный чоппер с приводом от компа. Посылаю на порт атмелки число, атмелка его ловит и управляет скважностью ШИМа.



Схема: https://yadi.sk/i/sx1hFQE03ZMWNy

Использую ШИМ с коррекцией фазы на таймере T1 (встроенная 10-битная ШИМ). И кварц на 16 Мгц. При таком кварце атмелка может дать частоту ШИМа максимум 7.8 кГц. Этого мало, приходится ставить очень громоздкий дроссель. Надо поднять частоту хотя бы в два раза.

Можно ли программными ухищрениями поднять частоту ШИМа, или придется переходить на STM ? Или попробовать разогнать атмелку до 30 МГц внешним генератором?

Текст программы для CVAVR:

 
/*--------------------------------------------------------------------------------------

Дата: 05.07.2018

Назначение программы: импульсный источник питания с регулированием мощности от внешнего устройства.

Тип конструкции: ШИМ-регулятор.

Регулирование мощности: Со стороны пользователя: ПК с системой LabView 2013 и внешним управляющим модулем E14-140-M;
Со стороны устройства: микроконтроллер ATmega8515.

Редактор: CodeVisionAVR V3.32 Evaluation.

Микроконтроллер: ATmega8515.

Частота тактового генератора микроконтроллера с подключенным внешним кварцем: 16 МГц.

Режим: ШИМ с коррекцией фазы на таймере T1 (встроенная 10-битная ШИМ).

Частота ШИМ-сигнала: 7.819 кГц.

---------------------------------------------------------------------------------------- */

#include <mega8515.h>
#include <delay.h>


void main(void)
{

// Настройка портов --------------------------------------------------------------------

PORTC = 0b00000000; // Настраиваем порт С на ввод информации (для опроса E14-140-M). Подключить внешние PULL-DOWN резисторы 1.8 КОм на все пины порта С.
DDRA = 0b11111111; // Настроим порт A на ввод сигнала для контроля принимаемого двоичного числа.

DDRE = 0b111; // Настроим порт E на вывод сигнала.


// Настройка 16-битного таймера. 10-битная ШИМ с коррекцией фазы на выводе OC1B (второй пин порта E) -----

TCCR1A = 0b00110011; // COM1A1-COM1A0-COM1B1-COM1B0-FOC1A-FOC1B-WGM11-WGM10

TCCR1B = 0b00000001; // ICNC1-ICES1- - -WGM13-WGM12-CS12-CS11-CS10



OCR1B = 0; // Чем ближе к 0, тем тускнее. В начале программы устанавливаем нулевую выходную мощность.

SFIOR = 0b00000001; // Записываем единичку в первый бит регистра особых условий ввода-вывода
// (SFIOR - Special Function Input-Output Register) и сбрасываем предделитель.

TCNT1 = 0; // Обнуляем счётный регистр 16-битного таймера. */



delay_ms(500); // Задержка программы на 500 мс для успокоения переходных процессов.


// -------------------------------------------------------------------------------------

while(1) // Бесконечный цикл опроса линий E14-140-M (поллинг). Изменение регистра сравнения на лету.
{

PORTA = PINC; // Индикация принимаемого двоичного числа от E14-140-M на порт A.



if (PINC == 255) // Формирование ШИМ-сигнала.
{
OCR1B = PINC*4+3; // Устранение паузы.
}

else
{
OCR1B = PINC*4; // Заполнение регистра сравнения.
}


}


}

Аватара пользователя
BSVi
Адепт
Сообщения: 3470
Откуда: Киев

Сообщение BSVi » 21 июл 2018, 22:06

Если экземпляр единичный, то можно разгонять. АВРки хорошо гонятся. Но, в целом, лучше на СТМ сделать.

Аватара пользователя
Kubrikov
Сообщения: 43

Сообщение Kubrikov » 21 июл 2018, 23:13

Спасибо Сергей! А stm какую максимальную частоту ШИМа может выдать?

Вообще странно, частота AVR 16 Мгц, частота шима 8кГц (что в 2000 раз меньше).
Неужели он 2000 тактов пропускает?
Последний раз редактировалось Kubrikov 22 июл 2018, 00:31, всего редактировалось 1 раз.

Аватара пользователя
Kubrikov
Сообщения: 43

Сообщение Kubrikov » 21 июл 2018, 23:55

Сергей, а какой можешь порекомендовать stm на 2018 год не слишком сложный для новичков? Может какие-нибудь отладочные платки есть?
В свое время рекламировали xmega на 32 МГц. Говорили, их можно будет программировать так же, как обычные атмелки. С ними вообще сейчас кто-нибудь работает?

Аватара пользователя
BSVi
Адепт
Сообщения: 3470
Откуда: Киев

Сообщение BSVi » 22 июл 2018, 08:22

С АВРкой все правильно - она считает вверх и в низ. Таймер 10-битный, поэтому и считает 2048 тика. Если нужно быстрее за счет точности, можно обрезать разрешение таймера.

А СТМки примерно все на одно лицо. Я в основном пользуюсь старенькими stm32f100c6 или новенькими stm32f407rg возможно, вам подойдут более дешевые и быстрые в плане клока stm32f0xx

Аватара пользователя
Kubrikov
Сообщения: 43

Сообщение Kubrikov » 22 июл 2018, 14:48

А как обрезать разрешение таймера? Записать в него число что ли?

Аватара пользователя
BSVi
Адепт
Сообщения: 3470
Откуда: Киев

Сообщение BSVi » 22 июл 2018, 16:09

Поменять биты WGM в TCCR1A так чтобы масимум задавался OCR1A, а потом записать туда требуемое значение.

Rabby
Сообщения: 177
Откуда: Tel Aviv

Сообщение Rabby » 22 июл 2018, 17:50

http://ww1.microchip.com/downloads/en/D ... supply.pdf -там почти готовая прога для бака с регулировкой по току,тока инициализацию добавить под нужный проц

Аватара пользователя
iEugene0x7CA
Адепт
Сообщения: 1292
Откуда: Киев

Сообщение iEugene0x7CA » 22 июл 2018, 20:57

Я наверное сейчас начну лезть не в свое дело и рассказывать как сделать лучше вместо прямых ответов на прямые вопросы, уж простите. :)

1. Нельзя просто подать нужную скважность ШИМ дабы DC-DC выдал стабильное напряжение — это будет работать исключительно когда нагрузка отсутствует, но достаточно таковой появиться и выход сразу просядет.
В рабочих преобразователях всегда юзается та или иная система обратной связи, которая измеряет напряжение на выходе и сама подкручивает ШИМ так, чтобы вход соответствовал заданному напряжению пользователем.

2. Хотя и можно, но крайне не рекомендуется строить преобразователи в которых МК является частью генерирующей/стабилизирующей системы.
Т.е. например таких, где МК одновременно генерирует сигнал от которого управляются транзисторы и еще меряет АЦП'шкой напряжение выхода дабы математикой что-то там подстраивать.
Проблем в таком подходе две: Во первых это значительно менее надёжно чем железная схема управления(любой глюк сразу приведет к взрыву силовухи), и во вторых МК это просто медленно: пока АЦП померяет напряжение выхода и процессор посчитает как нужно изменить заполнение ШИМ — может многое измениться. А медленная стабилизация – это возможный геммор с нагрузками которые потребляют ток быстро, например другими преобразователями в составе подключенных приборов.

Обычно DC-DC с управлением от МК строят по вот такой структуре:
1. Есть силовая часть, управляемая железной аналогово-цифровой схемой;
2. Есть МК, который обеспечивает связь с ПК и управляет упомянутой выше схемой холодным способом – обычно выставляя опорное напряжение на входе ОУ.

P.S.
Относительно прямых вопросов — можно заюзать 8-битный Timer 0 и AVR'ку с даташитной частотой 20 МГц(они бывают на 16 и 20 МГц соответственно).
Упадет точность относительно 10-ти бит(256 состояний вместо 1024), но зато 20МГц/256 == 78.125 кГц для Fast PWM и 39.0625 кГц для Phase Correct PWM.

Насчет перехода на STM'ки — они содержат колоссально более мощный функционал, особенно таймера там просто конфетки. ;)
Но есть и минус — одновременно STM32 просто пипецки более сложные, процессом программирования и чисто внутренней структурой(даташиты по 2000 страниц — это норма).
Еще очень большой минус — по ним гораздо меньше инфы в инете, меньше готовых проектиков, драйверов и т.д.
Лично я намного больше всего делал на AVR'ках чем сейчас когда перескочил на STM32. Более того – иногда до сих пор достаю AVR'ки если нужно какую-нить совсем мелочь запрогать, куда 32-бита ну никак. :mrgreen:

Аватара пользователя
BSVi
Адепт
Сообщения: 3470
Откуда: Киев

Сообщение BSVi » 23 июл 2018, 06:26

Сейчас процессоры в преобразователях уже широко используются, но да, по большей части это - не любительские поделки. У СТМ таймерах есть куча спец фич для DC-DC, в частности асинхронная аппаратная защита. Можно к пину подключить датчик тока и защита будет работать отдельно от проца.

А под 10 бит я имел ввиду настройку WGM где TOP=0x01FF

Аватара пользователя
Kubrikov
Сообщения: 43

Сообщение Kubrikov » 24 июл 2018, 02:32

Набросал быдлокод, пущай мк генерит шим нопами. Поскольку ничего сложного мк у меня не делает, то это допустимо. (надо только их количество подобрать, чтобы выдавалось 30 кГц, и кварц тоже)
Если силовая часть будет работать нормально, тогда начну курить stm.

И врубил собаку, если заглючит - кратковременные сбои проглотят конденсаторы. Они на это и рассчитаны.

 
#include <mega8515.h>
#include <delay.h>

int i;

void main(void)
{

// Настройка портов --------------------------------------------------------------------

PORTC = 0b00000000; // Настраиваем порт С на ввод информации (для опроса E14-140-M). Подключить внешние PULL-DOWN резисторы 1.8 КОм на все пины порта С.
DDRA = 0b11111111; // Настроим порт A на вывод сигнала для контроля принимаемого двоичного числа.

DDRE = 0b111; // Настроим порт E на вывод сигнала.

PORTE = 0; // Обнуление порта E.

WDTCR = (0<<WDCE) | (1<<WDE) | (0<<WDP2) | (0<<WDP1) | (0<<WDP0); // Настройка сторожевого таймера. Предделитель 1/16k.


#asm("sei"); // Разрешение общих прерываний.



delay_ms(300); // Задержка программы на 300 мс для успокоения переходных процессов.



// -------------------------------------------------------------------------------------

while(1) // Бесконечный цикл опроса линий E14-140-M (поллинг).
{

PORTA = PINC; // Индикация принимаемого двоичного числа от E14-140-M на порт A.

PORTE = 1;

for (i=0; i<=PINC; i++) // Формирование длительности импульса.
{
#asm
NOP
NOP
NOP
#endasm
}

PORTE = 0;

for (i=0; i<=(255-PINC); i++) // Формирование длительности паузы.
{
#asm
NOP
NOP
NOP
#endasm
}

}


#asm("wdr"); // Сброс сторожевого таймера.


}



Кстати, а если включить собаку аппаратно фьюзами, это же наверное надежней будет? Тогда в тексте программы включать собаку командой (1<<WDE) необязательно? Или оставить обе команды?

WD.jpg

Аватара пользователя
BSVi
Адепт
Сообщения: 3470
Откуда: Киев

Сообщение BSVi » 24 июл 2018, 08:01

Если включить фьюзом, то вочдог будет работать в том числе в бутлодере и коде инициализации, который идет до мэйна. Врядле тебе это нужно.

А идея с нопами - плохая, лучше бы с таймерами разобрался.

Аватара пользователя
Kubrikov
Сообщения: 43

Сообщение Kubrikov » 25 июл 2018, 18:44

Ребят, поглядите, я собаку правильно включил? МК иногда виснет, но не сбрасывается. Настроил предделитель 1/2048 и сбрасываю командой WDR в конце каждого цикла While. Еще рекомендуют сбрасывать собаку в самом начале перед настройкой. Что пошло не так?

 
/*--------------------------------------------------------------------------------------
#include <mega8515.h>
#include <delay.h>

int i, a, b;

void main(void)
{

// Настройка портов --------------------------------------------------------------------

PORTC = 0b00000000; // Настраиваем порт С на ввод информации (для опроса E14-140-M). Подключить внешние PULL-DOWN резисторы 1.8 КОм на все пины порта С.
DDRA = 0b11111111; // Настроим порт A на вывод сигнала для контроля принимаемого двоичного числа.

DDRE = 0b111; // Настроим порт E на вывод сигнала.

PORTE = 0; // Обнуление порта E.

#asm("sei"); // Разрешение общих прерываний.

#asm("wdr"); // Сброс сторожевого таймера.

WDTCR = (0<<WDCE) | (1<<WDE) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0); // Настройка сторожевого таймера. Предделитель 1/2048k.


delay_ms(300); // Задержка программы на 300 мс для успокоения переходных процессов.



// -------------------------------------------------------------------------------------

while(1) // Бесконечный цикл опроса линий E14-140-M (поллинг).
{

PORTA = PINC; // Индикация принимаемого двоичного числа от E14-140-M на порт A.

if (PINC == 0)
{
PORTE = 0;
}

else
{
if (PINC == 31)
{
PORTE = 1;
}

else
{
a = PINC;

PORTE = 1;


for (i=0; i<=a; i++) // Формирование длительности импульса.
{
}


PORTE = 0;

b = 31-a;


for (i=0; i<=b; i++) // Формирование длительности паузы.
{
}

}
}


#asm("wdr"); // Сброс сторожевого таймера.


}

}

Rabby
Сообщения: 177
Откуда: Tel Aviv

Сообщение Rabby » 26 июл 2018, 13:57

я задержку в конце while добавил бы хотя бы 1 мкс-а то чета слишком короткий код в while почему то зависает.

Вернуться в «Микроконтроллеры и ПЛИС»



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя