Управление светодиодный кубом.
- Войдите на сайт для отправки комментариев
Чт, 13/09/2012 - 18:20
Здравствуйте. Спаял кубик 2Х2, чисто для оценки возможности управления.
Примерно так выглядит схема куба:
То есть слой с общим анодом, "столбики" с общим катодом. Очевидно, что я не могу зажечь LED6 и LED3 отдельно, потому как "в нагрузку" загорятся LED2 и LED7. Это действительно так или я неверно понял схему по сборке кубика?
Посмотрел статьи про светодиодные матрицы. Там ведь аналогичная проблема: нельзя зажечь светодиод в 1 столбце и 1 строке и вместе с ним 2 столбец, 2 строка, ведь вместе с ними загорятся 1 столбец, 2 строка и 2 столбец, 1 строка, так?
А ещё я нагуглил, что такое "динамическая индикация". Не допёр, правда, как это применить к кубу, но вопрос снят...
Как вы расположите в пространстве диоды - не важно. Хоть кубом, хоть шаром, хоть пирамидой.
Главная проблема - невозможно зажигать одновременно.
Решается это примерно так: заводим массив в котором храним, для каждого диода, состояние (включен или выключен). И когда нам нужно "что-то зажечь" - меняем в этом массиве значение.
Далее, как можно чаще, в loop, пробегаемся по этому массиву. Если видим что ячейка содержит 1 - зажигаем соотвествующий ей диод. Ждем некоторое время. И гасим его. Переходим к следующей ячейке... и так все по кругу.
В результате, у нас одномоментно горит только один диод. Но если достаточно быстро бегать по этому кругу и "зажигать диод" на не очень продолжительное время, то благодаря инерции зрения будеть казатся что диоды горят "одновременно".
Что-бы "понять" можете просто на три пина подключить три диода. Например на пины 5,6,7.
И выполнить такой скетч.
Вначале вы увидите как диоды по очереди горят (по одной секунде), потом постепенно время горения будет сокращатся. все быстрее и быстрее будут менятся. Через какой-то время вам уже будет казатся что они светят все три одновременно.
Как вы расположите в пространстве диоды - не важно. Хоть кубом, хоть шаром, хоть пирамидой.
Главная проблема - невозможно зажигать одновременно.
Решается это примерно так: заводим массив в котором храним, для каждого диода, состояние (включен или выключен). И когда нам нужно "что-то зажечь" - меняем в этом массиве значение.
Далее, как можно чаще, в loop, пробегаемся по этому массиву. Если видим что ячейка содержит 1 - зажигаем соотвествующий ей диод. Ждем некоторое время. И гасим его. Переходим к следующей ячейке... и так все по кругу.
В результате, у нас одномоментно горит только один диод. Но если достаточно быстро бегать по этому кругу и "зажигать диод" на не очень продолжительное время, то благодаря инерции зрения будеть казатся что диоды горят "одновременно".
Что-бы "понять" можете просто на три пина подключить три диода. Например на пины 5,6,7.
И выполнить такой скетч.
Вначале вы увидите как диоды по очереди горят (по одной секунде), потом постепенно время горения будет сокращатся. все быстрее и быстрее будут менятся. Через какой-то время вам уже будет казатся что они светят все три одновременно.
Я понимаю, как это работает. Я тут в соседней теме как раз "программный ШИМ" пытаюсь реализовать. Я просто не очень представляю, как это оптимально под куб закодить. Тоесть осмысленно вовремя зажигать и строки и столбцы. Но я соображу, думаю.
Вернее я представляю, как это сделать с "прямым" подключением. Но у меня ещё сдвиговые регистры. Думаю сделать 2 массива (у меня 2 регистра) и в них записать "кадры", а потом просто пробегать по массивам и писать в регистры значения.
Прошу оценить говнокод (по опыту предущих подобных вопросов, я сейчас получу аналог в 10 раз короче :)).
Идея такая:
задаётся количество кадров, "атомов" в кадре, задержка между кадрами. "атомов" взял 8 - по числу светодиодов. В основном цикле по кругу на регистры передаются значения атомов, если атомы показываются уже столько времени, сколько указана задержка, переходим к следующему кадру.
"Атомный" подход, кажется, достойно реализует динамическую индикацию для моей конструкции.
P.S. Предложение leshak: "заводим массив в котором храним, для каждого диода, состояние" я отверг по той причине, что накладные расходы по преобразованию значения из массива в байт, который будет передан на регистр превзойдут мой текущий код в несколько раз (или я просто не умею чего то?). Плюс, мой вариант легко оборачивается в "кодогенератор" на любом скриптовом языке, что бы "руками" не подбирать значения в массиве для создания желаемых эффектов.
Данные действительно нужно хранить кадрами. 1 кадр - 8, 16 или 32 бита, каждому биту соответствует светодиод. Типы масивов будут uint8_t, uint16_t или uint32_t соответственно. Это зависит от количества включенных последовательно регистров сдвига.
У Вас заданы двумерные массивы, которые инициализируются одномерными - ошибка. Достучаться до отдельных битов через индекс массива нельзя!
Посмотрите http://arduino.ru/Reference/ShiftOut - там есть "замечания по использованию", где показано, как выводятся многобайтовые величины.
Данные действительно нужно хранить кадрами. 1 кадр - 8, 16 или 32 бита, каждому биту соответствует светодиод. Типы масивов будут uint8_t, uint16_t или uint32_t соответственно. Это зависит от количества включенных последовательно регистров сдвига.
Вы предлагаете хранить состояние каждого светодиода в кубе? Тоесть я могу написать нечто вроде "uint16_t cube_state = 13107" (11001100110011), передать это с помощью shiftOut и установить значения сразу на 2 регистрах? В примере есть оператор >>, нагуглилось, что это побитовый сдвиг вправо. Я правильно понимаю, что "cube_state >> 8" выводит 11001100 (старший байт), а затем, при повторной передаче в shiftOut cube_state будет выведен "остаток"?
У Вас заданы двумерные массивы, которые инициализируются одномерными - ошибка. Достучаться до отдельных битов через индекс массива нельзя!
А как правильно инициализировать двумерный массив? Такую конструкцию я подсмотрел в статье про подключение светодиодной матрицы. Она мне тоже показалась странной, но...она работает.
По поводу сдвига - Вы правильно поняли.
По поводу объявления массива, запись var[][] фактически воспринимается как **var и при инициализации линейным массивом компилятор раскладывает значения построчно. Правильно записывать:
Самое логичное - куб выводить послойно. Один слой (он же кадр) - один элемент массива. Для куба 4х4х4 нужно 2 регистра, массив, хранящий текущее состояние куба будет
Индекс массива - номер слоя.
Ардуино не поддерживает битовый формат.