PWM на таймере

CatSoup
Offline
Зарегистрирован: 01.05.2017

Всем бобра! Задал сутки назад вопрос в теме с pwm либой но никто не откликнулся.

С таймерами не знаком пока, есть только теоретическое понимание работы. Задача - стара как "Н" мост: генерация управляющих импульсов для двух IR2110 с частотой 500-1500Гц и скважностью от 2% до 70% с недопущением сквозняков между диагоналями. путем курения манов, даташита 328 и туториалов обнаружил, что мне нужен режим "ШИМ с точной фазой с контролем максимума счета регистром OCRA" на таймере1, разрешающей способности которого вполне хватит для регулирования скважности с дискретностью в 2%, даже если управлять частотой путем избрания делителем 1 и ограничения значения TOP счетчика. 

Таким образом, моя задача решается установкой делителя 1 к таймеру 1, инициализацией таймера в режиме Phase and Frequency Correct PWM Mode, в котором, как раз кстати, работает буферизация регистра OCRA, и установкой его же (OCR1A) в режим переключения состояния по переполнению. Тогда, по идее, на 1 пине я получаю ШИМ с контролем частоты путем записи нужного значения в OCR1A и ограничении счетчика и контроль за скважностью петум записи значения в OCR1B, а на другом пине я получаю чередование лог. 1 и лог. 0 каждый импульс, что позволяет мне переключаться между диагоналями моста. Собственно вопрос в чем - мозг взрывается от таких вещей как: 

    TIMSK2 &= ~(1<<TOIE2); //запрещение прерывания по переполнению таймера/счетчика Т2 
    TCCR2A &= ~((1<<WGM21) | (1<<WGM20));// Режим работы таймера/счетчика
    TCCR2B &= ~(1<<WGM22);// Режим работы таймера/счетчика
    ASSR &= ~(1<<AS2);  //Выбор источника синхронизации таймера если AS2=0 от системного генератора
    tcnt2 = 6250; //  16000000/64/f=tcnt2

или:

  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22);
  OCR2A = 180;
  OCR2B = 50;

При этом читаю даташит:

If OCR1A is used to define the TOP value (WGM1[3:0]=0x9) and COM1A[1:0]=0x1, the OC1A output will toggle with a 50% duty cycle.

смотрю таблички и понимаю, что в TCCR1A мне нужно вписать 8 бит, 4 из которых задают режим работы ноги привязанной к регистру А, 2 из которых не на что не влияют (вписать нули), а 2 младщих в комбинации с 2мя старшими из TCCR2A задают режим работы выводов... И где-то на этом месте, просто БУМ, Фак мой мозг... Как это вписать? Куда? Что делает код приведенный выше? Начиная с какого бита отпралять информацию? Побитово как в стек или побайтово? И где почитать доступную для неподготовленного человека литературу?

 

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

CatSoup, вам стоит серьёзно продолжить изучение работы таймеров, ибо какие то проблески разумных мыслей среди ваших размышлений имеются.  Только сегодня советовал в соседней теме почитать Евстифеева "Микроконтроллеры AVR семейства Mega", по крайней мере я её читал, и сильно помогло. Начнём с того, что мега328 аппаратно не поддерживает Dead Time. А например копеечная Tiny25..85 -поддерживает.  Я бы делал на ней, впрочем можно и на меге 328, однако это менее надёжно. Режим эквивалентный dead-time это действительно фаза-коррект режимы. 8-битного таймера более чем хватает для  255 градаций скважности, это гораздо лучше 2%  дискретности, о котором вы говорили. Но если при этом нужно ещё и регулировать частоту, то только таймер1.  Регистры сравнения А и Б  должны отличаться на некую величину. При единичном прескалере один попугай различия в регистрах даст 62nS дидтайма на каждом фронте. Пример:

void setup() {
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B0)|(1<<COM1B1);//подключены выходы oc1a и oc1b
TCCR1B=(1<<WGM13)|(1<<CS10); //mode8 PWM, Phase and Frequency Correct
ICR1=7999; //ШИМ 1kHz
OCR1A=4000; OCR1B=3990; //50 процентов duty с dead-time 600nS 

 

CatSoup
Offline
Зарегистрирован: 01.05.2017

Спасибо! Если я правильно понял даташит и Ваши комменты к коду - строчка:

TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B0)|(0<<COM1B1); 

Включит инверсию 2го порта, и, соответственно, пина - тогда я получу красивый 2х канальный шим с четкой фазой центров импульсов, DT же вместе со скважностью при каждом изменении частоты и, соответственно, разрешающей способности по времени нужно пересчитывать - ну мне все равно учитывать паразитную емкость в схеме развязки, которая приводит к увеличению скважности.

Дальше - необходимые биты режима WGM10 и 11 отправляются в TCCRxA, 12,13 соотв. во второй регистр управления TCCRxB. Бит CS10 установил внутренний делитель на 1 и тики считаются 16*10^6 в секунду. При необходимости к конструкции добавляются инструкции 1<<CS11(12)  что меняет делитель.

Изменением ICR1 задается потолок счета - частота. В вашем коде написано 1кГц. Прикинул на пальцах, что 2, но потом дошло, что таймер будет считать обратно - соответственно, по 2 интервала в 8000 попугаев на модуляцию 1 импульса.

Изменением OCR1A и B задается ширина импульса, при этом, если один из выходов инверсный - DT можно просто вычесть из ICR1 а полученное значение разделить пополам, присвоить значерие 1 регистру сравнения, затем - вычесть из ICR1 и вписать во 2 регистр сравнения.

Если я все понял правильно - ваш код с коментариями для меня бесценен, спасибо огромное! Нигде не мог найти (не там искал) синтаксис. Тяжело думать на бейсике)). Пошел скачивать книгу)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Дополню чутка: "только таймер1" это в случае Нано, Уно и пр. на базе ATmega328, можно взять что-то на базе ATmega2560, типа "АрдуиноМега 2560" (готовые платы от  400руб/шт), MegaCore, IteaDuino.. будет 4 таймера, или на базе ATmega128A, типа Crumbuino - , будет 2 таких таймера.

P.S. Можно легко сваять что-то свое, и тут ATmega128A выходит вперед ещё и в ценовом вопросе .. купить её по 40-45руб/шт - не проблема, что делает итоговую плату даже дешевле чем УНО.

CatSoup
Offline
Зарегистрирован: 01.05.2017

Спасибо за информацию) Своё обязательно сваяю как прототип заработает, не отдавать же на производство устройство с дуино на борту) Засмеют жеж) А кроме китайского УНО на руках ничего нет - на работе упер пачку - были взяты с mifare картами развлекаться т.к. сисадмин сказал "дуино - модульная платформа, с кучей рабочих шилдов, либ и ООП - прям бери и конфигурируй на коленке, так удобно, что аж паять не надо, а к 1С примотать так вообще плевое дело". Естественно ничего не примотал ибо работать нужно. Я же столкнулся с производственной необходимостью и решил примотать семисегментку, 2 энкодера, 2 АЦП, 2 кнопки и 2х канальный шим - вроде бы ничего сложного, просто управление источником питания, даже не тех.процессом. На начальном этапе знаний было 0 - месяц назад не знал даже синтаксиса и типов данных (до этого только хелловорлды на VB6 и VBA писал). Вспоминаю его слова каждый день и жалею что сразу не начал с аврстудии, дрыганья ножками на асьме и распайки DIP на плате а зашел с обратной стороны - ООП без понимания работы железки, но забивать бошку еще кучей информации сейчас уже не хочу, поэтому пусть пока будет 328))

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

CatSoup пишет:

Спасибо! Если я правильно понял даташит и Ваши комменты к коду - строчка:

TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B0)|(0<<COM1B1); 

Включит инверсию 2го порта,

Не включит, вы отключите выход oc1b. Для инверсии нужно обнулить другой бит.

CatSoup пишет:

Дальше - необходимые биты режима WGM10 и 11 отправляются в TCCRxA, 12,13 соотв. во второй регистр управления TCCRxB.

Зачем они туда отправляются? В примере таймер УЖЕ работает в нужном вам режиме.

 

CatSoup
Offline
Зарегистрирован: 01.05.2017

Да-да, я понял, что Вы сделали всю работу за меня, но разобраться то нужно. Вдруг втянусь и захочется фазовый сдвиг, прерывания...

mag155
Offline
Зарегистрирован: 21.12.2017

А подскажите как перенастроить таймеры для ardyino due  ??

pdjboy
pdjboy аватар
Offline
Зарегистрирован: 22.01.2017

Вообще, как то муд"халсмя и я с этим вопросом. Пришел к  тому что лучше и дешевле для здоровья. Если только Вы не одержимы идеей именно на атмеге построить данный "алгоритм". Лично мое мнение, проще взять готовую для этих целей специализированную микросхему, их большое множество, например SG 2525. А если вообще ленивая жопа, то готовый модуль с ключиками и защитой, у китайцеф, которые все сделали за нас. Мегу можно использовать для более узконаправленных задач. Ну там измерения с выводом на дисплей, управление  SG микросхемой.

mag155
Offline
Зарегистрирован: 21.12.2017

Да Все же хочу заделать свой инвертор чтоб можно было менять прошивку под свои нужды.