Анимация LED матрицы - Постепенное включение всех светодиодов матрицы в случайном порядке
- Войдите на сайт для отправки комментариев
Вс, 30/09/2018 - 19:57
Добрый день всем.
Такой вопрос возник: есть у меня матрица 16х32. И вот встал вопрос: как так сделать анимацию на ней, чтобы в случайном порядке загорались светодиоды, но так, чтобы в окончании выполнения горели они все?
Просто моргать светодиодами через random не проблема. Не могу понять, кк сделать так, чтобы выполнялось сразу две функции: включение случайного светодиода и проверка матрицы на то, сколько уже горит и сколько нет, чтобы random дважды не обращался к одному и тому же светодиоду, а плавно зажёг все.
Может, кто сталкивался с чем-то подобным?
Ну, есть 100500 способов, например, очень простой, но довольно дорогой по ресурсам. Всего у Вас 512 светодиодов. Пронумеруйте их от 0 до 511, заведите массив leds[512], заполните его числами от 0 до 511 (в смысле, что leds[i] = i), заведите некую переменную N изначально равную 511.
Далее в цикле ровно 512 раз делаете следующее:
1. Генерируете псевдослучайное число R от 0 до N включительно
2. Зажигаете светодиод номер leds[R]
3. Присваиваете leds[R] = leds[N]
4. Уменьшаете N на 1
После, после 512 проходов - все горят. Зажигались в случайном порядке.
Если нет свободного килобайта - можно по-другому, но ... ограничения на память заданы не были, так что чего пальцы-то бить?
А подумать. А прикинуть.А мозгой пошевелить. А включить логику. Понятно что бы в конце все
умерли в один деньзажглись надо больше зажигать и меньше гасить. Нужен рандом, так рандомно и зажигай. А если уже зажжена, так следующую соседнюю по ходу не зажженую.зажигай. А если уже зажжена, так следующую соседнюю по ходу не зажженую.
В условии не сказано, что есть возможность узнать горит уже или нет. Да и вообще, не узнаю Вас. А где подходящий к случаю класс?
Так можно же перемешать сначала по random() массив на 512 элементов, а потом пробежаться по нему... Ну, понятное дело, класс написать с методами для перемешивания и для поджигания очередного светодиода. И чтобы метод, стало быть, возвращал количество незадействованных элементов...
Всё просто: 64 байта - на флаги - горит светодиод или нет. Плюс - random. Примерно вот так:
Дописать функцию проверки на то - горит светодиод или нет - элементарно ;)
Ну, есть 100500 способов, например, очень простой, но довольно дорогой по ресурсам. Всего у Вас 512 светодиодов. Пронумеруйте их от 0 до 511, заведите массив leds[512], заполните его числами от 0 до 511 (в смысле, что leds[i] = i), заведите некую переменную N изначально равную 511.
Далее в цикле ровно 512 раз делаете следующее:
1. Генерируете псевдослучайное число R от 0 до N включительно
2. Зажигаете светодиод номер leds[R]
3. Присваиваете leds[R] = leds[N]
4. Уменьшаете N на 1
После, после 512 проходов - все горят. Зажигались в случайном порядке.
Если нет свободного килобайта - можно по-другому, но ... ограничения на память заданы не были, так что чего пальцы-то бить?
Матрица вот так выглядит:
Задачка на Меге выполняется, потому памяти вроде не совсем уж мало, но хотелось бы оптимального решения, а не в лоб. Да и в случае необходимости, оптимальное решение может быть масштабируемо.
Пользуюсь библиотекой RGBmatrixPanel, у неё есть функция drawPixel(x,y). То есть каждый пиксель(светодиод) имеет свою координату. И вот как создать таблицу координат, чтобы после каждого прохода через random значение это (из random'а) вычиталось из таблицы и так пока не останется ни единого элемента в массиве.
Или как-то можно проще это исполнить?
Подсказываю: нужны две операции - деление и взятие остатка.
Подсказываю: нужны две операции - деление и взятие остатка.
Будьте добры, подскажите, пожалуйста, чуть подробнее.
Подсказываю: нужны две операции - деление и взятие остатка.
Будьте добры, подскажите, пожалуйста, чуть подробнее.
Если у Вас есть номера от 0 до 511, то поделите номер на длину строки - получите номер строки, а остаток от деления номера на длину строки - номер столбца. Вы в каком классе учитесь? В в шестом это уже, вроде, знают.
Но если хотите по уму, то забудьте про то, что я писал, а внимательнее отнеситесь к посту DIYMan.
Матрица вот так выглядит:
Если надо не просто ВСЕ 512 светодиодов зажигать, а какие-нибудь фигуры, при этом знать, зажжены ли все - то надо будет ещё один массив - эталонный, итого - два массива по 64 байта (см. мой пример выше). Перед пуском заполняем эталонный массив, где биты установлены в тех позициях, какие светодиоды надо зажечь. При проверке, завершено ли зажигание - сравниваем не с 0xFF, а с байтом из эталонного массива.
Подсказываю: нужны две операции - деление и взятие остатка.
Будьте добры, подскажите, пожалуйста, чуть подробнее.
В моём примере выше - это операторы "/" и "%", соответственно. Что именно в примере непонятно?
Всё в кучу ))
Про деление и взятие остатка эт я понимаю.
Не очень понятно, как включать светодиоды, если они включаются не digitalWrite'ом, а командой matrix.drawPixel(x,y,Color) и надо указывать 2 координаты, которые могут повторяться сами по себе, но не должны повторяться вместе.
Пример: светодиоды по адресу 44х1 и 44х5.
Пользуюсь библиотекой RGBmatrixPanel, у неё есть функция drawPixel(x,y). То есть каждый пиксель(светодиод) имеет свою координату.
Допустим, у нас матрица размером 16 строк х 32 диода в строке. И нам надо найти, в какой строке и каком столбце находится светодиод номер 200. Тогда:
Проверка: поскольку у нас 32 диода в строке, то, чтобы не превысить число 200, целых строк до 200 поместится 6, т.е. 32*6 = 192. Остаётся 8, т.е. - в восьмом столбце нужный светодиод.
Простая арифметика. Нумерация строк/столбцов - ессно, с нуля.
Всё в кучу ))
Про деление и взятие остатка эт я понимаю.
Не очень понятно, как включать светодиоды, если они включаются не digitalWrite'ом, а командой matrix.drawPixel(x,y,Color) и надо указывать 2 координаты, которые могут повторяться сами по себе, но не должны повторяться вместе.
Пример: светодиоды по адресу 44х1 и 44х5.
А в чём проблема-то? Рассматривайте светодиоды в матрице при помощи СКВОЗНОЙ нумерации, слева-направо и сверху вниз. Первый светодиод в первой строке - первый (кэп!), последний светодиод в последней строке - последний (снова кэп!). Нумеруются по порядку. Как высчитать строки и столбцы из тупого номера светодиода - написал выше.
Это вы понимаете?
Про деление и взятие остатка эт я понимаю.
Судя по следующей фразе
Не очень понятно, как включать светодиоды, если они включаются не digitalWrite'ом, а командой matrix.drawPixel(x,y,Color) и надо указывать 2 координаты, которые могут повторяться сами по себе, но не должны повторяться вместе.
Ни хрена на самом деле не понимаете.
Если Вы пронумерованли все светодиоды от 0 до 511, и номер уникален - как ему может соответствовать неуникальная пара строка/столбец? ну, как?
Яволь! :)
Яволь! :)
Всё же, прощу Вас внести некоторые вспомогательные комментарии к Вашему коду выше.
Вот Ваш код в моём. Или наоборот, кто как скажет.
Так и не понял, как мне вычёркивать уже включенные светодиоды.
Вот Ваш код в моём.
Нет, это не мой код. Вы его испортили, т.к. в моём коде return true было ВНЕ цикла for. Копируйте правильно.
Так и не понял, как мне вычёркивать уже включенные светодиоды.
Флаг включения светодиода устанавливается в функции ledOn. Проверить светодиод на включение - просто, достаточно проанализировать нужный бит в нужном байте массива. Смотрите код, там всё прозрачно.
Я приведу ещё один пример, в котором код отрабатывает только после того, если светодиод включился (т.е. не был включен ранее):
delay будет срабатывать только после того, как светодиод включится. Повторные включения ранее включенного светодиода - производиться не будут (т.е. не отработает digitalWrite в примере).
Не очень ясно, что должно присвоиться в 17 строке.
result у меня всё время равен false, хотя сами переменные byte и bit постоянно меняются.
Потому что у вас код неправильный. Почему вы делите на X, а остаток от деления делаете на Y? Арифметику расчёта - я приводил, неужели так сложно понять, что там фигурирует ОДНО число НОМЕРА светодиода, и КОНСТАНТА 8? Зачем вы туда впихиваете ваши x и y ????????
Похоже, вы не понимаете простейших вещей, к сожалению.
Про х и у увидел, да, уже изменил, спасибо. Работать матрица начала, но есть один нюанс:
рандом выдаёт числа и одни и те же и новые. Повторные чаще. Из-за этого время заполнения матрицы светодиодами весьма велико.
Подскажите, пожалуйста, как при каждом проходе можно уменьшать список светодиодов, чтобы он рандомно выдавал каждый раз новое значение, без повторов?
Про х и у увидел, да, уже изменил, спасибо. Работать матрица начала, но есть один нюанс:
рандом выдаёт числа и одни и те же и новые. Повторные чаще. Из-за этого время заполнения матрицы светодиодами весьма велико.
Подскажите, пожалуйста, как при каждом проходе можно уменьшать список светодиодов, чтобы он рандомно выдавал каждый раз новое значение, без повторов?
В примере, что я приводил - какие-то действия (например, задержка между зажиганиями) происходит только после того, как ledOn вернёт true, что, в свою очередь, значит, что на вход ledOn поступило новое число, сгенерированное random (т.е. число, которого до этого не было).
Всё остальное: проблема равномерного распределения псевдослучайных чисел. Мой подход - просто демонстрация того, как можно обойтись меньшим кол-вом оперативки, НЕ генеря все числа при старте. Если генерить все числа при старте, то вам понадобится
512*2 = 1024 байта
массив данных. Тогда код будет выглядеть примерно так:
Недостаток - время инициализации, плюс - огромный расход оперативки. Можно вместо оперативки писать куда-нибудь, например, в EEPROM. И после инициализации массива случайных чисел - вычитывать уже оттуда.
Короче, вариантов генерирования - много, предложенный в куске кода выше - алгоритмически самый позорный, к слову. Лучшим вариантом было бы применить тот же set или unordered_set, а после - random_shuffle - эта связка алгоритмически будет работать на порядок быстрее, пмсм.
З.Ы. set и unordered_set - контейнеры STL, порт которого есть и под дуню. random_shuffle - алгоритм из STL.
Про х и у увидел, да, уже изменил, спасибо. Работать матрица начала, но есть один нюанс:
рандом выдаёт числа и одни и те же и новые. Повторные чаще. Из-за этого время заполнения матрицы светодиодами весьма велико.
Подскажите, пожалуйста, как при каждом проходе можно уменьшать список светодиодов, чтобы он рандомно выдавал каждый раз новое значение, без повторов?
В примере, что я приводил - какие-то действия (например, задержка между зажиганиями) происходит только после того, как ledOn вернёт true, что, в свою очередь, значит, что на вход ledOn поступило новое число, сгенерированное random (т.е. число, которого до этого не было).
Всё остальное: проблема равномерного распределения псевдослучайных чисел. Мой подход - просто демонстрация того, как можно обойтись меньшим кол-вом оперативки, НЕ генеря все числа при старте. Если генерить все числа при старте, то вам понадобится
512*2 = 1024 байта
массив данных. Тогда код будет выглядеть примерно так:
Недостаток - время инициализации, плюс - огромный расход оперативки. Можно вместо оперативки писать куда-нибудь, например, в EEPROM. И после инициализации массива случайных чисел - вычитывать уже оттуда.
Короче, вариантов генерирования - много, предложенный в куске кода выше - алгоритмически самый позорный, к слову. Лучшим вариантом было бы применить тот же set или unordered_set, а после - random_shuffle - эта связка алгоритмически будет работать на порядок быстрее, пмсм.
З.Ы. set и unordered_set - контейнеры STL, порт которого есть и под дуню. random_shuffle - алгоритм из STL.
Огромное спасибо!
Огромное спасибо!
Да незчт. Только вы это - всё-таки не копируйте бездумно, а попытайтесь понять, что делается и, главное - как это делается. Только так можно чуть продвинуться в программировании, пмсм ;)
Возможен и следующий подход - заполнить массив последовательными числами от 1 до cols*rows, массив хорошо перемешать, меняя между собой случайно выбранные элементы вот этим алгоритмом.
Огромное спасибо!
Да незчт. Только вы это - всё-таки не копируйте бездумно, а попытайтесь понять, что делается и, главное - как это делается. Только так можно чуть продвинуться в программировании, пмсм ;)
Это я понимаю, спасибо. Этим, собственно, сегодня и займусь.
Возможен и следующий подход - заполнить массив последовательными числами от 1 до cols*rows, массив хорошо перемешать, меняя между собой случайно выбранные элементы вот этим алгоритмом.
Только вчера вечером эту статью читал. Для начала разберусь с вариантом DIYMan'а, а дальше посмотрим.