Программный ШИМ на сдвиговом регистре.
- Войдите на сайт для отправки комментариев
Здравствуйте. Собственно, суть вопроса, который я собираюсь задать, отражена в заголовке темы. РЕализовать хочу это "just for fun", хотя, если получится хорошо...
Есть rgb светодиод. Подключаю его через сдвиговый регистр 74hc165.
Наваял вот такой скетчк (подключены 2 светодиода, светодиоды с общим анодом):
byte latchPin = 8; byte clockPin = 12; byte dataPin = 11; byte rstPin = 7; void setup() { pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(rstPin, OUTPUT); digitalWrite(rstPin, LOW); digitalWrite(rstPin, HIGH); // устанавливаем синхронизацию "защелки" на LOW digitalWrite(latchPin, LOW); // 255 - все светодиоды погашены shiftOut(dataPin, clockPin, MSBFIRST, 252); //"защелкиваем" регистр, тем самым устанавливая значения на выходах digitalWrite(latchPin, HIGH); } unsigned int howred=25000; unsigned int howgreen=0; unsigned int howblue=100; void loop() { if (howblue) { // устанавливаем синхронизацию "защелки" на LOW digitalWrite(latchPin, LOW); // передаем последовательно на dataPin для синего shiftOut(dataPin, clockPin, MSBFIRST, 252); //"защелкиваем" регистр, тем самым устанавливая значения на выходах digitalWrite(latchPin, HIGH); // пауза перед следующей итерацией delayMicroseconds(howblue); } if (howred) { digitalWrite(latchPin, LOW); // передаем последовательно на dataPin для красного shiftOut(dataPin, clockPin, MSBFIRST, 207); //"защелкиваем" регистр, тем самым устанавливая значения на выходах digitalWrite(latchPin, HIGH); // пауза перед следующей итерацией delayMicroseconds(howred); } if (howgreen){ digitalWrite(latchPin, LOW); // передаем последовательно на dataPin для зелёного цвета shiftOut(dataPin, clockPin, MSBFIRST, 243); //"защелкиваем" регистр, тем самым устанавливая значения на выходах digitalWrite(latchPin, HIGH); // пауза перед следующей итерацией delayMicroseconds(howgreen); } }
Это работает(в данном случае получается красивый малиновый цвет), но не совсем адекватно. Например, если в данном скетче уменьшить Howred в 10 раз, то цвет не изменится, а при увеличении howblue в 10 раз, цвет меняется. И не регулируется общая яркость. Пробовал ставить задержку при полностью выключенных светодиодах, но тогда при установке значения задержки до 5000 яркость не меняется, а при 10000, например, яркость снижается, но появляется заметное глазу мигание.
Вопрос: вообще взлетит или на регистрах это нереально?
P.S. Про внешние ШИМ-контроллеры знаю, занимаюсь этим для развлечения.
На регистрах можно, конечно. Можно даже при желании замутить в прерывание какое-нибудь быстрое на таймере...
По теме.
Я бы пошел по другому пути. В цикле от 0 до 255 сравнивал с установкой яркости светодиода (в диапазоне от 0 до 255) и устанавливал бы соответствующий бит. Где-то так:
На регистрах можно, конечно. Можно даже при желании замутить в прерывание какое-нибудь быстрое на таймере...
По теме.
Я бы пошел по другому пути. В цикле от 0 до 255 сравнивал с установкой яркости светодиода (в диапазоне от 0 до 255) и устанавливал бы соответствующий бит. Где-то так:
А что делает оператор &?
Интернет говорит, что это побитовое сравнение (0&0=0; 0&1=0; 1&1=1;) но в данном случае, я так понимаю, этот оператор "насаживает" на buffer значения? Или...
На регистрах можно, конечно. Можно даже при желании замутить в прерывание какое-нибудь быстрое на таймере...
По теме.
Я бы пошел по другому пути. В цикле от 0 до 255 сравнивал с установкой яркости светодиода (в диапазоне от 0 до 255) и устанавливал бы соответствующий бит. Где-то так:
А что делает оператор &?
Интернет говорит, что это побитовое сравнение (0&0=0; 0&1=0; 1&1=1;) но в данном случае, я так понимаю, этот оператор "насаживает" на buffer значения? Или...
UPD:
А! & складывает биты! Отлично. Спасибо!
P.S.
Промахнулся мимо кнопки редактирования.
Не складывает, а побитно умножает. Это основы с - битовые операции. Так мы ставим 0 на нужное место. Правильно было написать buffer&=0b11110111 - сбросить бит в четвертой позиции в 0. Но боялся, что испугаетесь, а так - разобрались :)
Единицу поставить можно так: buffer|=0b00001000 (| - это как раз побитное сложение)
Слишком медленно... Цвет получается ровный, но... стробоскоп, одним словом :)
Код ещё не ковырял. Просто загрузил в ардуину в том виде, что вы дали :)
Убавте delay в конце цикла - он должен быть не более 200. Мне было лень считать, когда текст писал.
По большому счету, его можно вообще убрать. Но я бы оставил. Скажем, 50 или даже 100 :)
Если денег не жалко, то можно посмотреть в сторону I2C порт-расширителей. Некоторый умееют по I2C принять команду типа "включили вот такой PWM на такой своей ноге". И все. Дальше он сам его там генерить, не занимая основной контроллер.
Вот например такая "жирная штука" http://www.nxp.com/documents/data_sheet/PCA9685.pdf
Много чего еще умеет помимо "тупо включить PWM".
Убавте delay в конце цикла - он должен быть не более 200. Мне было лень считать, когда текст писал.
По большому счету, его можно вообще убрать. Но я бы оставил. Скажем, 50 или даже 100 :)
Его убрал первым делом - не помогло. Я думаю, что в моём способе - держать один цвет, потом другой, регистр переключается 1 раз и это незаметно. А в вашем - ему приходится переключаться огромное количество раз, что становится заметным глазу.
Если денег не жалко, то можно посмотреть в сторону I2C порт-расширителей. Некоторый умееют по I2C принять команду типа "включили вот такой PWM на такой своей ноге". И все. Дальше он сам его там генерить, не занимая основной контроллер.
Вот например такая "жирная штука" http://www.nxp.com/documents/data_sheet/PCA9685.pdf
Много чего еще умеет помимо "тупо включить PWM".
ненене. Нужно именно на сдвиговом регистре :)
А вы случайно сдвиговым регистром не ошиблись? Судя по даташиту 74hc165 имеет параллельный вход и последовательный выход. То есть данный регистр предназначен для размножения входов, а не выходов. Честно говоря странно, что у вас вообще что-то работает...
Может все таки вы используете 74hc595 ?
Если у вас все-таки 74hc595 (или что то пожее), то попробуйте так:
По моим подсчетам у вас должно получиться около 28 "кадров" в секунду, если для вас это медленно, то:
1. Сделайте разрядность ШИМ не 8 бит (BIT_PWM = 256), а например 7 бит (BIT_PWM = 128), из моей практики этого вполне достаточно, что бы плавно рулить цветами;
2. Используйте не shiftOut, а SPI он в разы быстрее. При частоте МК 16МГц частота линии CLK может достигать 8МГц.
у меня почему то не хочет работать ни один код, поясните что делает в схеме/коде этот пин "
byte
rstPin = 7;
" , мне сейчас нужно реализовать программный шим для 64 разрядов. сделано на 74HC595 регистрах, светики подключены через 220 ом на землю.задача понизить яркость на всех светиках сразу, уж больно ярко в панели они светят) возможно ли это?
программный шим для 64 разрядов. сделано на 74HC595 регистрах, светики подключены через 220 ом на землю.
В общем виде (регулировку отдельно каждого светика) - не получится. Выйдет "стробоскоп".
задача понизить яркость на всех светиках сразу, уж больно ярко в панели они светят) возможно ли это?
А вот это - уже реальней. Только регистры тут совсем не причем. Общая яркость и "кто включен, а кто нет" - это отдельные блоки.
У вас же все светики имеют "что-то общие" (общий катод или анод). Вот этот "общий" и нужно не на прямую подключать к земле (или питанию), а через какой-то полевик (или ULN2003 и т.п.). Через какой-то "краник", на который вы можете подать шим от ардуины.
Вообщем рассматривайте свою задачу как "нужно шимить нагрузку", а не "шимить регистры".
посадить все сразу никак не получится физически, ну или получится только мне эти 64 провода нужно вырезать из 15 плат и соединять вместе((( а было бы идеально!!! я решил задачу так:
1 вариант
+ просто и без моргания, - 10 мс для меня уже проблема....
2 вариант
+ нет задержки для основного кода, - наблюдаются нестабильные моргания, немного напрягающие...
есть ещё варианты?
я заметил что моргание получается во всём коде а не в примере что я написал, выключил не нужную задержку и всё заработало как надо.
> ну или получится только мне эти 64 провода нужно вырезать из 15 плат и соединять вмест
Какие 64-ре? Вы что? Я же расписывал что вам нужно смотреть на светики "с другого конца". У вас же эти светики имеют общую землю или общие питание. Вот это и нужно рулить.
Как у вас светик подключен? Грубо говоря "одной ногой к регистру, другой к земле". А вам нужно "к земле через полевик". Причем вас же никто не заставляет для каждого светика ставить отдельный полевик. Взять полевик помощьней и все к одному свести. Сейчас они у вас к земле сходятся, а будут к полевику.
По коду:
зачем вы оборачиваете в millis() какие-то составные части процесса "отсылки данных на сдвиговый"? Оберните все целиком.
Раз в 10 мсек - отсылать данные на сдвиговый.
Только еще раз - фигня это. Когда у вас увеличится количество сдвиговых вы задержку будете не добавлять, а бится как-бы ее поменьше сделать. Само время передачи данных на сдвиговый уже будет слишком большим для "комфортности глаз".
Или не мучайтесь и возмите i2c экспандер, который сам умеет шим делать, не запаривая мозг дуине (ссылку выше я давал).
ShiftPWM
смотрел здесь, но долго не разбирался, спасибо но в следующиё раз)
Какие 64-ре? Вы что? Я же расписывал...
leshak
а теперь представте что у меня в конструкции 15 плат, на которых находятся кнопки, светодиоды, резисторы, транзисторы, разьёмы наружные и внутренние, платы разнесены по всему корпусу "прибора", подключены по разному, они все разные, Вы хотите что бы я резал дорожки от каждого светодиода на плате соединил так каждый катод светодиода а после ещё с каждой платы тянул эти провода в одну точку на колектор транзистора упровляемого шимом? ну и как Вы себе это представляете?))))
я про эту конструкцию как то Вам рассказывал, она готова и я как то не хочу её переделывать, осталось дело за кодом и только, когда закончу выложу здесь проект)
по коду, я эксперементировал, так работает и по другому работает, я оставил задержку именно на "гашение" а дальше пусть код работает своим ходом...