AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
29.06.2013, 19:56
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.11.2011
Адрес: Анапа
Сообщений: 1,620
Сказал спасибо: 284
Сказали Спасибо 129 раз(а) в 111 сообщении(ях)
|
Алгоритм программного шима для светодиодов
Не могу отыскать тут тему, была недавно..
В общем, я там отписывался, что 16 каналов завел на 8мгц - и все работает, включая usb_hid вопросы.
Добавил вывод на сдвиговые регистры (решил расширится) - и все, камень стал затыкаться. Понижаю частоту - мерцание. Повышаю - нехватает ресурсов.
Стал задумываться над сменой алгоритма формирования ШИМа для яркостей.
Сейчас: цикл от 0 до 100, внутри производится сравнение с ячейкой массива для данного канала. Если больше переменной головного цикла - пин (или бит на сдвиговый) остается прежним. Если меньше - отрубается.
Есть мысль "размазать" включения/выключения более плавно и просто понизить частоту - тогда глаз не заметит "подвоха". Другими словами, при яркости 50 у меня 50 движений цикла диод горит, 50 - нет. Хотелось бы чтобы он в таком случае мигал "через один" - но как математически обрисовать это минимальным кодом, пока в голову не лезет.
Подскажете?
|
|
|
|
29.06.2013, 20:47
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.11.2011
Адрес: Анапа
Сообщений: 1,620
Сказал спасибо: 284
Сказали Спасибо 129 раз(а) в 111 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
мысль такая: разделив 100 на нужное значение яркости, получим число: "каждый X раз выводить пин, остальные разы выключить".
Например, при яркости 50 из ста получаем 100/50=2, каждый второй раз включать пин.
А вот дальше чего то туго. Делить 100 на текущий шаг (основного цикла сравнения) и сравнивать - непрокатило, еще больше ресурсов хавает)
|
|
|
|
29.06.2013, 21:19
|
|
Почётный гражданин KAZUS.RU
Регистрация: 20.06.2006
Адрес: Украина, Запорожье
Сообщений: 8,002
Сказал спасибо: 0
Сказали Спасибо 4,946 раз(а) в 2,373 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
whoim,
поищите в аккаунт-статистика-найти все сообщения.
алгоритм брезенхема? путем сложения и проверки на превышение, при превышени добавляете к числу константу, чтоб получить число в диапазоне.
для 33 в диапазоне 100: 0›33›66›99›превышение 132+156›32›65›...
|
|
|
|
29.06.2013, 21:23
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.11.2011
Адрес: Анапа
Сообщений: 1,620
Сказал спасибо: 284
Сказали Спасибо 129 раз(а) в 111 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
jump, попробую осмыслить, перекурю только предварительно) спасибо!
|
|
|
|
29.06.2013, 21:30
|
|
Почётный гражданин KAZUS.RU
Регистрация: 20.06.2006
Адрес: Украина, Запорожье
Сообщений: 8,002
Сказал спасибо: 0
Сказали Спасибо 4,946 раз(а) в 2,373 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
whoim,
хорош курить, программа стынет!
|
|
|
|
29.06.2013, 22:55
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.11.2011
Адрес: Анапа
Сообщений: 1,620
Сказал спасибо: 284
Сказали Спасибо 129 раз(а) в 111 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
jump, в принципе, завелось, но на скважности ‹4 из ста начинаются жуткие мерцания) на 4 уже не видно..
Код:
|
uint8_t bri[CH_MAX]; //массив текущей яркости канала
static int16_t sigma[CH_MAX]; //модуляторы
static int8_t delta[CH_MAX];
uint8_t bri_step; //счетчик для цикла программного ШИМ
uint8_t ch_step; //счетчик канала для програмного ШИМ
...
if(ch_step › CH_MAX-1)
{
ch_step = 0;
bri_step++;
if(bri_step › 100) bri_step = 0;
}
if(sigma[ch_step] › 100)
{
delta[ch_step] = -100;
ch_state(ch_step, 1);
}
else
{
delta[ch_step] = 0;
ch_state(ch_step, 0);
}
sigma[ch_step] = sigma[ch_step] + bri[ch_step] + delta[ch_step];
ch_step++; |
|
|
|
|
29.06.2013, 23:16
|
|
Почётный гражданин KAZUS.RU
Регистрация: 20.06.2006
Адрес: Украина, Запорожье
Сообщений: 8,002
Сказал спасибо: 0
Сказали Спасибо 4,946 раз(а) в 2,373 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
whoim,
такой метод я применял для... нагревателей. они не мерцают (увы, не светодиоды) и регулировка была отличной. я пока ничего не придумал, но подозревал. для снижения мерцания только увеличение частоты спасет
|
|
|
|
29.06.2013, 23:34
|
|
Почётный гражданин KAZUS.RU
Регистрация: 24.09.2007
Адрес: Полтава, UA
Сообщений: 2,447
Сказал спасибо: 375
Сказали Спасибо 1,059 раз(а) в 623 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
Сообщение от whoim
|
Добавил вывод на сдвиговые регистры (решил расширится)
|
Насколько вы хотите расшириться?
На меге8 можно сделать 21 независимый канал 8-ми битного ШИМа при частоте всего 4 МГц.
Все 3-и аппаратных + 18 программных, проверял в железе - работает.
На мега640 по этому же алгоритму - 86 независимых каналов, правда уже только 6-ти битных. В железе не проверял, но в IAR все успевало тоже.
__________________
Мелочи не решают главного. Они решают всё!
|
|
|
|
30.06.2013, 13:26
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.11.2011
Адрес: Анапа
Сообщений: 1,620
Сказал спасибо: 284
Сказали Спасибо 129 раз(а) в 111 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
gary2007, очень сильно хочу) 4-5 модулей по 8 каналов.
Пока успеха нет к сожалению..
Внедрил буферы для регистров, но слишком много операций
Код:
|
void shiftout_registers(void)
{
PORTC &= ~(1‹‹DS); //установим ноль на пине данных
PORTC &= ~(1‹‹ST_CP); //снимем "защелку" 74HC595
for(uint8_t mod_i=ext_modules_count; mod_i›0; mod_i--) //обратный цикл по количеству модулей
{
for (uint8_t ch_i=0; ch_i‹8; ch_i++) //цикл по пинам модуля расширения
{
//выведем бит данных
if(registers[mod_i-1]&(1‹‹ch_i)) PORTC |= (1‹‹DS);
else PORTC &= ~(1‹‹DS);
//обозначим clock
PORTC |= (1‹‹SH_CP);
PORTC &= ~(1‹‹SH_CP);
}
}
PORTC |= (1‹‹ST_CP); //установим "защелку" 74HC595
}
....
//обработка программного ШИМа для выходов
if(ch_step › (15+(ext_modules_count‹‹3))) //если значение больше максимального требуемого
{
ch_step = 0; //сбросим
bri_step++; //увеличим следующий цикл яркости
if(bri_step › BRI_MAX) bri_step = 0;
}
if(sigma[ch_step] › BRI_MAX)
{
delta[ch_step] = -BRI_MAX;
if(ch_step ‹ 8) PORTB |= (1‹‹ch_step);//каналы 1-8
else if(ch_step ‹ 16) PORTD |= (1‹‹(ch_step-8));//каналы 9-16
else registers[(ch_step-16)››3] |= ( 1‹‹( (ch_step-16) - (((ch_step-16)››3)‹‹3)) );
}
else
{
delta[ch_step] = 0;
if(ch_step ‹ 8) PORTB &= ~(1‹‹ch_step);//каналы 1-8
else if(ch_step ‹ 16) PORTD &= ~(1‹‹(ch_step-8));//каналы 9-16
else registers[(ch_step-16)››3] &= ~( 1‹‹( (ch_step-16) - (((ch_step-16)››3)‹‹3)) );
}
shiftout_registers();
sigma[ch_step] = sigma[ch_step] + bri[ch_step] + delta[ch_step];
ch_step++; |
прихожу к выводу - сложность вычислений при работе с этой реализацией заполнения ШИМ не даст прироста, ибо в обычной реализации (начальное заполнение) можно поднять частоту и получить тот же результат.
|
|
|
|
30.06.2013, 14:14
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.11.2011
Адрес: Анапа
Сообщений: 1,620
Сказал спасибо: 284
Сказали Спасибо 129 раз(а) в 111 сообщении(ях)
|
Re: алгоритм программного шима для светодиодов
куда глаза смотрели? перенес шифтаут в нужное место (после заполнения всех каналов и буфера) - стало лучше в разы. Но блин.. все равно чутка нехватает.
Мож чего еще можно оптимизировать, не подскажете?
Как вариант - переделать на кварц, 16мгц (у at90usb162 внутренний 8 максимум). Но тогда придется выкинуть светодиод - пины все заняты)
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 03:33.
|
|