Переключение битности PWM(ШИМ) на ATmega328

orcsin
Offline
Зарегистрирован: 12.06.2015

Здравствуйте!

Есть Arduino Nano (ATmega328) по умолчанию её неё 6 шим выходов с битность 8 (0-256). Но у чипа есть один из трёх таймеров на 16 бит. Вроде бы можно сделать 9 битный (0-512) или 10 битный (0-1024) шим. Вроде бы в таком режиме может заработать только 2 из 6 шимов.

Поясните пожалуйста как это сделать и какие именно пины будет работать в таком режиме. Прочитал несколько статей, но в голове только каша ,если можно то с пояснениями.

orcsin
Offline
Зарегистрирован: 12.06.2015

Забыл уточнить, нужно это для более плавном включении светодиода (рассвет-закат)

При 8 битном на малых значениях яркость изменяется скачками.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

orcsin, разрядность ШИМ можно хоть 16 бит сделать, но в вашем случае  истинной плавности регулировки яркости можно добиться только регулируя ток светодиодов, для этого потребуется собрать шим-управляемый стабилизатор тока тыц.

Alex_Ferrum
Offline
Зарегистрирован: 04.05.2015

В принципе можно попробовать 12-ти разрядный ШИМ. Можно использовать режимы номер: 8, 9, 10, 11, 14, 15. 12-ти разрядный ШИМ - это своего рода компромиссный вариант, с одной стороны чем больше разрядность ШИМ, тем лучше, с другой стороны ШИМ должен работать с частотой не менее 100 герц, чтобы не было заметно мерцания, а при этом длительность импульса для минимальной яркости равна 1С/(100*4000)=2.5 мкС и если мы управляем мощным светодиодом или лентой через силовой ключ, то необходимо некоторое время чтобы его открыть и закрыть.

Управлять яркостью, также как и громкостью необходимо по логарифмическому закону чтобы она менялась плавно. Соответственно в режимах 8, 10, 14 - ШИМ сигнал снимается с выводов контроллера, они же ШИМ-выходы OC1A и OC1B, в режимах 9, 11, 15 - с вывода OC1B. Для данной задачи не обязательно использовать быстрый ШИМ, по указанной выше причине.

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

А код будет?

orcsin
Offline
Зарегистрирован: 12.06.2015

Это для аквариумного контроллера, управление 3х ватными светодиодами через драйвер на основе CL6807.

У Меги вроде тоже 8 бит по умолчанию, но там больше таймеров (шим выходов) и люди делают 10 битные шим и вроде бы эта болезнь исчезает, ну покрайней мере с 10 битным можно логарифмическую функцию прописать. Частота у них получалась 90 гц, что не заметно для человека.

Я просто не могу понять, как именно прописывать установки разных режимов ШИМ, это и прошу пояснить.

Как это всё записывается? Читал вот это, но так язык не много не тот, с которым я знаком.

Регистр TCCR1A, биты WGM11 и WGM10 вместе с битами WGM12 и WGM13, находящимися в регистре TCCR1B задают режим работы генератора.
WGM13	WGM12	WGM11	WGM10	Режим работы
0	1	0	1	Fast PWM 8 бит
0	1	1	0	Fast PWM 9 бит
0	1	1	1	Fast PWM 10 бит

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

orcsin, вот вам универсальный PWM генератор.

void setup() {
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
ICR1=65535;
OCR1A=32767;
}

void loop() {}

Регистром ICR задаёте до скольки считать(частота), регистром OCR1A задаёте на каком такте задирать лапу (скважность). Значения в скетче -частота 244 Герц,  разрядность ШИМ 16 бит, дьюти 50%.  

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Alex_Ferrum пишет:

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

Дался вам этот логарифм 

#include <math.h>
long value=10;
const long value_max=10000;
const long value_min=0;
float result;
const long result_max=10;
const long result_min=0;

void setup() {

}

void loop() {
  result= map(value, log(value_min), log(value_max),result_min, result_max);
}

 

orcsin
Offline
Зарегистрирован: 12.06.2015

dimax, подкажите, а где WGM10?

TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm

 

orcsin
Offline
Зарегистрирован: 12.06.2015

qwone, за использование логарифма в map не догадался, большое спасибо :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

orcsin, вот вам универсальный PWM генератор.

void setup() {
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
ICR1=65535;
OCR1A=32767;
}

void loop() {}

Регистром ICR задаёте до скольки считать(частота), регистром OCR1A задаёте на каком такте задирать лапу (скважность). Значения в скетче -частота 244 Герц,  разрядность ШИМ 16 бит, дьюти 50%.  

Огласите весь список...
Дмитрий, а как с ним работать?
Через analogwrite на 9 пин можно?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ua6em, это эквивалент функции analogWrite ().   Выход на 9 ногу (atmega328).  Всё что нужно знать написано в #6   Обязательно должно соблюдаться условие OCR1A <=  ICR1

orcsin
Offline
Зарегистрирован: 12.06.2015

dimaх, где эквивалент функции analogWrite ()? В #6  вроде бы настройка порта как я понял, а потом в программе же всё равно нужно вызывать analogWrite ()...

Ещё вопрос, если 8 битному шим задать параметр больше 255 он его как максимум восприймет?

И посмотрите пожалуйста пост #8

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

orcsin пишет:

 В #6  вроде бы настройка порта как я понял, а потом в программе же всё равно нужно вызывать analogWrite ()...

Ничего не нужно вызывать!!! Это вместо функции analogWrite, а не в дополнение её.

orcsin пишет:

Ещё вопрос, если 8 битному шим задать параметр больше 255 он его как максимум восприймет?

Зависит от обработчика. По умолчанию проигнорируются все данные за границей 8-ми бит. Таким образом например число 270 воспримется как 14.

orcsin пишет:

И посмотрите пожалуйста пост #8

Посмотрите в вашу табличку вверху темы. -Нет там бита WGM10 в 14 режиме. Не понимаю что тут ещё можно сказать.

orcsin
Offline
Зарегистрирован: 12.06.2015

dimax, то есть ноль там по умолчанию и ни каких WGM10 делать не нужно?

orcsin
Offline
Зарегистрирован: 12.06.2015

ТО есть OCR1A это val  в analogWrite(9, val)?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

orcsin, В операции присваивания всё, что не установлено как единица -всё ноль. Мой вам добрый совет -поизучайте двоичные операции, без этого программирование немыслимо.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

orcsin пишет:

ТО есть OCR1A это val  в analogWrite(9, val)?

По аналогии да.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Дмитрий! А этот код нельзя оформить в виде функции, чтобы её использовать передавая параметры?
Или просто вталкиваем переменную в OCR1A и будет нам счастье?

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Вроде так -

/* Вызываем в setup() */
void setup16bitPWM () {
   pinMode(9,OUTPUT);
   TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
   TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
   ICR1=65535;
   OCR1A=32767; //50% default value
}

/* Вызываем для изменения скважности) */
void analogWrite16bit(uint16_t value) {
   OCR1A = value;
}

ЗЫ. Вот, в принципе, аналогично, для двух пинов - 9 и 10.

orcsin
Offline
Зарегистрирован: 12.06.2015

Друзья, поясните пожалуйста колонку ТОР из таблички в первом посте, как установить режим уже понятно, осталось вот это ещё понять :)

ТОР это я так понимаю мах верхнее значение, а что для режимов 1-3 и 5-7 за значения в шестнадцатеричном виде указаны?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

OlegK пишет:

Вроде так -

/* Вызываем в setup() */
void setup16bitPWM () {
   pinMode(9,OUTPUT);
   TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
   TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
   ICR1=65535;
   OCR1A=32767; //50% default value
}

/* Вызываем для изменения скважности) */
void analogWrite16bit(uint16_t value) {
   OCR1A = value;
}

ЗЫ. Вот, в принципе, аналогично, для двух пинов - 9 и 10.

ДА! Работает великолепно!

Это даже лучше чем мне надо было, старый полевой транзистор КП103 пищит от удовольствия )))

Megawollt
Offline
Зарегистрирован: 06.12.2015

То есть на 328 атмеге можно использовать только 2 16 битных канала? 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Megawollt пишет:

То есть на 328 атмеге можно использовать только 2 16 битных канала? 

Ну если использовать только 16 битный таймер, то да - два 16 битных канала с независимой регулировкой коеффициента заполнения/скважности при одинаковой частоте ШИМ. Есть ещё 8 битные таймеры.

Alex_Ferrum
Offline
Зарегистрирован: 04.05.2015

Да вы совершенно правы в ATMEGA328 можно использовать максимально до 2 каналов с разрядностью до 16 бит с независимой регулировкой, в ATMEGA162, ATTINY441/841 до 4 каналов с разрядностью до 16 бит с независимой регулировкой, в ATMEGA128 до 6 каналов с разрядностью до 16 бит с независимой регулировкой.

Megawollt
Offline
Зарегистрирован: 06.12.2015

Почему ICR1=65535;

16 бит это не 65025?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Нет.

Megawollt
Offline
Зарегистрирован: 06.12.2015

И как это работает?

qwone пишет:

Alex_Ferrum пишет:

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

Дался вам этот логарифм 

#include <math.h>
long value=10;
const long value_max=10000;
const long value_min=0;
float result;
const long result_max=10;
const long result_min=0;

void setup() {

}

void loop() {
  result= map(value, log(value_min), log(value_max),result_min, result_max);
}

 

Alexsandr
Offline
Зарегистрирован: 24.02.2019

dimax пишет:

orcsin, вот вам универсальный PWM генератор.

void setup() {
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
ICR1=65535;
OCR1A=32767;
}

void loop() {}

Регистром ICR задаёте до скольки считать(частота), регистром OCR1A задаёте на каком такте задирать лапу (скважность). Значения в скетче -частота 244 Герц,  разрядность ШИМ 16 бит, дьюти 50%.  

Откуда в скетче эта частота  244герц ?  где он указан? где спрятан в скетче делитель на 256 ?

Другие частоты ШИМ можно выставить делителями согласно табличке.

Константа   Делитель          Частота(Гц)

   0x01           1              62500

   0x02           8              7812.5

   0x03          64              976.5625

   0x04         256              244.140625

   0x05        1024              61.03515625

Я думал: mode 14 Fast PWM - это когда  Разрешающая способность ШИМ может быть фиксированной 8, 9 или 10 разрядов или задаваться регистром ICRn или OCRnA, но не менее 2 разрядов (ICRn или OCRnA = 0x0003) и не более 16 разрядов (ICRn или OCRnA = 0xFFFF). 

Наверное, я заблуждаюсь..- но в моем понятии "разрешающая способность" в вашем скетче и есть 244гц.

а если надо получить ШИМ  200 КГЦ?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Alexsandr пишет:

Откуда в скетче эта частота  244герц ?  где он указан? где спрятан в скетче делитель на 256 ?

244 Гц = F_CPU/65536 ; 

Делитель ==1  (1<<CS10)

Alexsandr, вам нужно изучать программирование таймера на уровне его регистров, иначе полного понимания что и как тут надо настраивать не придёт.

Alexsandr
Offline
Зарегистрирован: 24.02.2019

Спасибо!

Я сразу понял,. что в этом случае, все делается на уровне контроллера (т.е не програмно). Об этом мне сразу стало понятно, когда "dgitalwrite"  заменяют операцией с регистрами. Еще раз спасибо, буду глубже вникать. В мои молодые годы (80-е) все это делалось на 155 или 561 логике. Но я отстал, надеюсь не навсегда..Догоню...Догоняю....

Если говорить "на уровне 155 логики" :  мы просто делаем задающий генератор с частотой кварца, а потом двумя операндами  "пропускаем" нужного размера куски.

А в каких пределах может изменяться ICR ?     Мое мнение: от частоты камня  и до 2гц   (соотв.-длительность: от 1/2 частоты камня и .до 1гц)   Это верное мнение?

Еще раз спасибо!

С уважением!

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Alexsandr пишет:

А в каких пределах может изменяться ICR ? 

0....65535 (16 бит).

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

Светодиод по ШИМ.... Да сделай программный ШИМ хоть на 32 да хоть на 64 бита! .... Хоть на все выходы...
Скорости до светодиода хватит

Alexsandr
Offline
Зарегистрирован: 24.02.2019

dimax пишет:

orcsin, вот вам универсальный PWM генератор.

void setup() {
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
ICR1=65535;
OCR1A=32767;
}

void loop() {}

Регистром ICR задаёте до скольки считать(частота), регистром OCR1A задаёте на каком такте задирать лапу (скважность). Значения в скетче -частота 244 Герц,  разрядность ШИМ 16 бит, дьюти 50%.  

Есть желание сделать генератор фиксированных частот и скважностей (2-е разные скважости для аждой фиксированной частоты:  для ножки 9-своя, для ножки 10-своя .) , Т.е ...    Около 10 частот , и каждая имеет 2 значения скважости (одна для 9пина, вторая для 10 пина) .

получатся такая таблица:

№  nomer:   1          2          3         4           5           6           8           9         10

ICR1       65535    57431    42123    33421   22333    12345     8765    6543     5432

0CR1A    45000    42000     40021    30089    20189    11955    8555     5543    4324

OCR2A    20000    15000     12000    13000    11960     987       210      100       110

Скетч,  для работы на 9 и 10 ножку, я подкорректировал ( я полюбил этот скетч, ибо библу с детства не люблю - лушче расчитывать на свои ресурсы (регистры))

С массивами я никогда не работал.  Как мне "оформить" и "вскармливать"  эти  данные  (в виде массива). ?

Ведь, если делать через массивы,  буде более красивее и кошернее!

С уважением!

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

массив с 0-го элемента  начинается, совсем кошерно не получится (от 0 до 9)

b707
Offline
Зарегистрирован: 26.05.2017

Alexsandr пишет:

Есть желание сделать генератор фиксированных частот и скважностей (2-е разные скважости для аждой фиксированной частоты:  для ножки 9-своя, для ножки 10-своя .)

 

все давно сделано - и частот сильно поболе чем 10. Загляните в раздел проекты, тем "Генератор с регулируемой частотой на Ардуино"

Alexsandr
Offline
Зарегистрирован: 24.02.2019

b707 пишет:

Alexsandr пишет:

Есть желание сделать генератор фиксированных частот и скважностей (2-е разные скважости для аждой фиксированной частоты:  для ножки 9-своя, для ножки 10-своя .)

 

все давно сделано - и частот сильно поболе чем 10. Загляните в раздел проекты, тем "Генератор с регулируемой частотой на Ардуино"

О  да!   Только там энкодером частота изменяется!    А если делать на несколько фиксированых частот - наверное лчше через матрицу задавать данные.  Но как матрицу "вскормить"?

aidar_i
Offline
Зарегистрирован: 07.10.2018

Как заставить работать пин 9 ШИМ и пин 10 цифровой одновременно?

Не могу отключить таймер на 10м пине, но чтобы работал на 9м пине.

Если оба ШИМ, тоже работают :)

bool en;
void setup()
{
    DDRB |= 1<<PB1;
    DDRB |= 1<<PB2;
    PORTB &= ~(1<<PB2);
    TCCR1A=(1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
    TCCR1B = _BV(WGM13) | _BV(WGM12)  | _BV(CS10);
    ICR1 =16383 ;
}
void loop()
{
    en = 1;
     for (int i=0; i<5000; i++) {  // на 9 плавно загорается светодиод
            OCR1A = i;
            _delay_ms(1);
        }
// на 10 не горит светодиод, если поставить digitalWrite() работает
    (en) ? PORTB |= (1<<PB2) : PORTB &= ~(1<<PB2);// на 10 не горит светодиод
}

 

aidar_i
Offline
Зарегистрирован: 07.10.2018

Вроде сам нашел: строка 7   TCCR1A=(1<<COM1A1) | (1<<COM1B0) | (1<<WGM11);

Правильно?

b707
Offline
Зарегистрирован: 26.05.2017

aidar_i пишет:

Не могу отключить таймер на 10м пине, но чтобы работал на 9м пине.

 а зачем вы его включаете? - в вашем коде вы принудительно включаете ШИМ на оба пина, а потом жалуетесь...

b707
Offline
Зарегистрирован: 26.05.2017

aidar_i пишет:

Вроде сам нашел: строка 7   TCCR1A=(1<<COM1A1) | (1<<COM1B0) | (1<<WGM11);

Правильно?

сначала спрашиваем. потом даташит смотрим... нет бы наоборот

aidar_i
Offline
Зарегистрирован: 07.10.2018

Спасибо! Я раньше не лазил в таймеры, думал не разберусь :)

aidar_i
Offline
Зарегистрирован: 07.10.2018

Запустил пин 11 по коду:

void setup()
{
    TCCR2A = 0;
    DDRB |= 1<<PB3;
    TCCR2A |= (1 << COM2A1);
    TCCR2A |= (1 << WGM21);
    TCCR2A |= (1 << WGM20);
    TCCR2A |= (1 << CS20);
    OCR2A = (150);
}
void loop()
{
}

Не могу запустить 3й пин по коду:



void setup()
{ DDRB |= 1<<PD3;
   TCCR2A = 0;
   TCCR2A |= (1 << COM2B1);
   TCCR2B |= (1 << WGM22);
   TCCR2B |= (1 << CS20);
   OCR2B = (150);
   //analogWrite(3, 150); // ЭТА СТРОКА РАБОТАЕТ
}
void loop()
{
}

 

 

b707
Offline
Зарегистрирован: 26.05.2017

Если пин PD, то и регистр должен быть DDRD

aidar_i
Offline
Зарегистрирован: 07.10.2018

Спасибо! Полдня возился с регистрами, эту строку пропустил, менял А на В ,  не обратил внимания.