Организация бегущей строки на светодиодной матрице, плюс вопрос о типах данных.
- Войдите на сайт для отправки комментариев
Здравствуйте. Проект, описанный в соседней теме (Подкиньте идею по реализации дисплея из 9 светодиодных матриц.) в разгаре. Прежде чем браться за матрицу 24Х24, решил попрактиковаться на матрице 8Х8. В качестве "самого сложного" реализовал бегущую строку. Только вот "бегает" у меня только то, что не превышает размера матрицы, таков алгоритм. А как заставить "бежать" строку длинее длинны матрицы? Скетч:
//Пин подключен к ST_CP входу 74HC595 int latchPin = 8; //Пин подключен к SH_CP входу 74HC595 int clockPin = 12; //Пин подключен к DS входу 74HC595 int dataPin = 11; //RST пин #define rst1 5 //Количество пропущенных кадров, до следующего "шага" анимации #define maxcount 50 //Количество строк матрицы #define matrixROWS 8 //Количество столбцов матрицы #define matrixCOLS 8 //Изначальное смещение строки - сдвинута за границу матрицы int cols_offset=-matrixCOLS; int counter=0; uint8_t rowbyte; uint8_t colbyte; //Строка для отображения uint8_t A[8] = {B00000100,\ B00001100,\ B00011100,\ B00101100,\ B00001100,\ B00001100,\ B00001100,\ B00011110}; void setup() { //устанавливаем режим OUTPUT pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(rst1, OUTPUT); } void loop() { //Отображаем первую строку rowbyte=B10000000; //Показываем кадр for (int i=0; i<=7; i++) { digitalWrite(rst1, LOW); digitalWrite(rst1, HIGH); digitalWrite(latchPin, LOW); //Rows shiftOut(dataPin, clockPin, MSBFIRST, rowbyte>>i); //Cols //Определяем, в какую сторону сдвигаем строку if (cols_offset < 0 ) {colbyte=A[i]>>(cols_offset*-1);} if (cols_offset >= 0 ) {colbyte=A[i]<
Ещё волнующий меня вопрос: для длинных матриц развёртку лучше делать горизонтальную или вертикальную?
С бегущими строками закончили. Дальше просто о отображении на матрице:
Если я планирую отображать изменяющиеся данные (курс акций например :) ), то каким образом сформировать очередной кадр? Я думаю разделить каждую строку на зоны (вот зона для отображения первой цифры числа, вот для второй и т.д.), в зависимости от выводимых данных формировать число, описывающее все биты этой строки, ну и отдавать это число в регистры. Собственно, как можно "слеплять" строки? Пример: Есть числа 00111000, 00110000 и 00001100. Как получить из них 001110000011000000001100? И я правильно понимаю, что мне тогда нужно будет делать сначала shiftOut(dataPin, clock, MSBFIRST, (data >> 16)), затем data >> 8, и на последок просто data?
Э... Честно говоря, от меня ускользает смысл некоторых действий. Но идея, как я понял в том, что бы просто выводить только часть массива, зная текущее смещение. Правильно? До такого решения "в лоб" я не додмуался, почему то :(
А что насчёт второй части вопроса? Кажется, я выбрал не самую лучшую реализацию...
Идея такая - есть функция, которая выводит данные на дисплей, причем эта функция работает только с массивом размером таким же как и дисплей, что-то типа видео-памяти. А вы уже как хотите так и заполняйте эту память, то есть вам не нужно думать как вывести на дисплей, вам просто нужно правильно заполнить массив видеопамяти.
Насчёт вывода изменяющейся информации придумал - нужно определить область, гарантированно вмещающую "длинное" число (999), и завести нужного размера маску из нулей. А потом эту маску умножать на нужные биты, в зависимости от выводимого числа.
У меня к несчастью (или к счастью?) матрица управляется регистрами сдвига. Поэтому использовать ваш код напрямую не получится. Написал такой код:
Проблема в следующем:
когда матрица была подключена с помощью каскада из двух регистров, анимация работала отлично. Но сейчас решил разделить регистры. Один для столбцов, другой для строк.
После разделения поправил код и увидел нечто дикое вместо адекватной картинки. После разбирательств и правок удалось добиться чёткой картинки, но с "паразитной" засветкой соседних пикселей. Происходит это так, как будто при подаче питания на очередной столбец, питание со строк ещё не снято. Так и было. Но потом я стал "открывать" защёлку сразу обоих регистров, что сделало "паразитную" засветку предельно тусклой. Однако, если я меняю порядок "защёлкивания" регистров (сначала строки, потом столбцы, и наоборот), яркость "лишних" пикселей заметно меняется. Наиболее тускло они светятся, если сначала защёлкивать строки. Что ещё странно, увеличение задержки добавляет мерцания, но не убирает паразитного свечения.
Как уже догадался пытливый читатель, с использованием каскада, когда регистры предельно синхронны, таких проблем нет.
Есть идеи?
Я так подозреваю, что можно обойтись и без ресета.
Виной засветкам являются монтажные ( и другие) емкости.
Попробуйте алгоритм (мультипликация построчная)
Паузой поиграться, возможно, и не потребуется.
Смысл в том, что строки должны зажигаться позже, а гаситься раньше столбцов.
Обратите внимание, что гасить и зажигать нужно не защелкой, а выбором (CS), т.е. в погашенном случае выходы регистра должны быть отключены.
Я так подозреваю, что можно обойтись и без ресета.
Виной засветкам являются монтажные ( и другие) емкости.
Попробуйте алгоритм (мультипликация построчная)
Паузой поиграться, возможно, и не потребуется.
Смысл в том, что строки должны зажигаться позже, а гаситься раньше столбцов.
Обратите внимание, что гасить и зажигать нужно не защелкой, а выбором (CS), т.е. в погашенном случае выходы регистра должны быть отключены.
Непременно опробую ваш совет, но если проблема в ёмкостях, то и при использовании каскада должна быть засветка.
UPD.
"CS" - это всмысле OE (pin 13) "Вход для переключения состояния выходов из высокоомного в рабочее"?
UPD2
По вашему алгоритму получается ооочень тускло. Однако, паразитная засветка исчезла сама собой. Я в замещательстве. Порядок передачи байта в регистры я менял много раз, сброс переносил в разные места и убирал... Непонятно.
Я так подозреваю, что можно обойтись и без ресета.
Виной засветкам являются монтажные ( и другие) емкости.
Попробуйте алгоритм (мультипликация построчная)
Паузой поиграться, возможно, и не потребуется.
Смысл в том, что строки должны зажигаться позже, а гаситься раньше столбцов.
Обратите внимание, что гасить и зажигать нужно не защелкой, а выбором (CS), т.е. в погашенном случае выходы регистра должны быть отключены.
Непременно опробую ваш совет, но если проблема в ёмкостях, то и при использовании каскада должна быть засветка.
UPD.
"CS" - это всмысле OE (pin 13) "Вход для переключения состояния выходов из высокоомного в рабочее"?
UPD2
По вашему алгоритму получается ооочень тускло. Однако, паразитная засветка исчезла сама собой. Я в замещательстве. Порядок передачи байта в регистры я менял много раз, сброс переносил в разные места и убирал... Непонятно.
В итоге, работает такой код:
UPD3. Не работает :) Просто засветка настолько яркая, что я не сразу заметил,что это засветка, а не часть моего "рисунка". А вот в вашем алгоритме если добавить паузу в конец, то всё отлично. Конечный вариант полностью рабочего кода привожу постом ниже.
P.S. На строках выводы можно и не отключать.
Если не секрет, зачем вы подключили каждый регистр к своим линиям данных? - это два....
И три - можно и без OE (CS) обойтись, достаточно перед и после вывода nowrow выводить 0 в регистр катодов.
Откровенно говоря,я так и не понял ваш код. Поэтому, не в состоянии "только изменить функцию Draw" под использование регистров. Но из кода извлёк идею (правильно или нет?) которая сподвигла меня на написание своего рабочего кода.
Если не секрет, зачем вы подключили каждый регистр к своим линиям данных? - это два....
Что бы удобнее было "раздвигать" матрицу. Сейчас она одна - можно и каскадом обойтись. Но увеличу её в ширину на 1 матрицы, а в длинну на 10 и мне при каждом расширении нужно помнить, в каком порядке и сколько регистров у меня в каскаде. А теперь мне нужно следить за каскадами строк и столбцов отдельно.
И три - можно и без OE (CS) обойтись, достаточно перед и после вывода nowrow выводить 0 в регистр катодов.
Отключать выводы... Логичнее что ли.
Отключать выводы... Логичнее что ли.
Это не логичнее - это еще один лишний провод (кстати так же как и ресет). Вы же катоды через транзисторы (сборку) подключаете поэтому послать 0 в регистр это и есть отключить катоды. То есть танзистору без разницы, что вы базу подключили на землю, что оставили в воздухе - он все равно останется закрытым.
OE (CS) применяется в других ситуациях, когда нужно освободить линии к которым подключены Q0 - Q7 тоесть когда к этим линиям подключено, что то еще, у вас же кроме баз транзисторов больше ничего не подключено. И если уж на то пошло, то использовать OE (CS) даже более не верно, чем посылать в регистры 0, так как если на базах транзисторов создастся емкость, то в первом случае емкость будет медленно разряжаться и так же может появиться засветка, тогда как во втором емкость будет быстро разряжена на землю. И уж темболее данный способ не применим при использовании полевых транзистров без дополнительных подтягивающих резисторов.
Я так подозреваю, что можно обойтись и без ресета.
Виной засветкам являются монтажные ( и другие) емкости.
Попробуйте алгоритм (мультипликация построчная)
Паузой поиграться, возможно, и не потребуется.
Смысл в том, что строки должны зажигаться позже, а гаситься раньше столбцов.
Обратите внимание, что гасить и зажигать нужно не защелкой, а выбором (CS), т.е. в погашенном случае выходы регистра должны быть отключены.
Уважаемый AlexFisher
Вижу что вы хорошо разбираетесь в теме бегущих строк и управлении светодиодными матрицами.
Помогите за финансовую благодарность реализовать небольшой проект.
Я так подозреваю, что можно обойтись и без ресета.
Виной засветкам являются монтажные ( и другие) емкости.
Попробуйте алгоритм (мультипликация построчная)
Паузой поиграться, возможно, и не потребуется.
Смысл в том, что строки должны зажигаться позже, а гаситься раньше столбцов.
Обратите внимание, что гасить и зажигать нужно не защелкой, а выбором (CS), т.е. в погашенном случае выходы регистра должны быть отключены.
Уважаемый AlexFisher
Вижу что вы хорошо разбираетесь в теме бегущих строк и управлении светодиодными матрицами.
Помогите за финансовую благодарность реализовать небольшой проект.
Тема закрыта.