Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Светодиодный куб RGB 8x8x8

Компоненты и расходные материалы

Общий анод, рассеянный RGB
× 512
Драйвер светодиода DM13A
× 12
74HC138 3–8 строчное декодирование
× 1
МОП-транзистор IRF9640 с P-каналом
× 8
Arduino UNO
Вы также можете создать макетную версию только с ATmega328, кристаллом 16 МГц и 2 конденсаторами 22 пФ
× 1
Импульсный источник питания Digilent 5 В, 2,5 А
× 1
Резистор 10 кОм
× 8
Резистор 1 кОм
× 8
Резистор 100 Ом
× 8

Приложения и онлайн-сервисы

IDE Arduino

Об этом проекте

Видео

Сборка

Эта сборка была вдохновлена ​​кубом Кевина Дарра RGB.

Глядя на телосложение Кевина, его терпение должно быть безграничным - к сожалению, мое терпение.

Я решил заменить 24 сдвиговых регистра, 192 транзистора и 640 резисторов на 12 светодиодных драйверов DM13a (около 1 доллара США каждый на eBay).

Сам куб был построен, как описывает Кевин в следующем видео:

После того, как куб был сделан, я создал печатную плату, используя метод тонера, чтобы удерживать микросхемы драйвера DM13A и сам куб. Вместо того, чтобы оплачивать стоимость серийно выпускаемой платы с покрытием для сквозных отверстий, я решил вручную подключить каждое соединение светодиода к соответствующему выводу DM13A с помощью проволочной обмотки. Включенные файлы Eagle содержат версию с ручной проводкой, а также версию с автоматической маршрутизацией (непроверенную).

На плате микропроцессора и анода также есть MSGEQ7 - семиполосный графический эквалайзер и микрофонный предусилитель, с которыми я планирую экспериментировать в будущем. Прямо сейчас они не используются. Если вы хотите использовать коммерческую плату UNO или Nano, все, что вам нужно, - это декодер от 3 до 8 строк 74HC138 и 8 полевых МОП-транзисторов с P-каналом и соответствующие резисторы. Вы можете просто подключить их к какой-нибудь прототипной плате, если хотите.

Блок питания 5В 20Вт был куплен на eBay. Я сделал корпус из выделанной сосны размером 40 х 9 мм.

Я добавил пару анимаций в программу куба Кевина, но в основном она осталась без изменений.

Заключение

Вы должны иметь возможность купить светодиоды RGB с общим анодом 600 x 5 мм на eBay примерно за 30 долларов США. Даже после упрощения электроники создание куба было очень трудоемким, но, в конце концов, полезным.

Код

  • Куб_8x8x8_V1.ino
Cube_8x8x8_V1.ino C / C ++
 / * Светодиодный куб 8x8x8 RGB, автор Джон Брэднам, на основе работы Кевина Дарра, последнее V12, 17 апреля 2013 г. Примечания к выпуску:V11 - Исправлена ​​ошибка с синхронизацией BAM - Установка пустого контакта перемещена в ISR, поэтому контакты не работают до тех пор, пока они не будут записаны в V12побитовая операция для установки pins LOW был неверным, должен быть PORTx &=~ (1 < // Библиотека SPI используется для синхронизации данных с регистрами сдвига # define LATCH_PIN 2 // может использовать любой вывод, который вы хотите заблокировать регистры сдвига # определить BLANK_PIN 4 // то же самое, можно использовать любой вывод, который вы хотите для этого, просто убедитесь, что вы потянули через от 1k до 5V # define DATA_PIN 11 // используется SPI, должен быть контакт 11 # define CLOCK_PIN 13 // используется SPI, должен быть 13 # define LAYER_A 5 // 74138 A Input # define LAYER_B 6 // 74138 A Input # define LAYER_C 7 // 74138 A Input # define SWITCH_PGM 10 // PB2 #define SWITCH_SEQ 9 // PB1 #define CUBE_SIZE 8 // Количество столбцов, строк или уровней в кубе # define CUBE_MAX (CUBE_SIZE - 1) // Максимальное количество кубов в dex # define LEDS_PER_LEVEL (CUBE_SIZE * CUBE_SIZE) // Количество светодиодов на уровень // *** переменные *** переменные *** переменные *** переменные *** переменные *** переменные *** переменные *** переменные // Эти переменные используются мультиплексированием и кодом модуляции битового угла // Так сохраняется яркость каждого светодиода, // Каждому светодиоду нужен только бит, чтобы знать, должен ли он быть включен или выключен, поэтому 64 байта дает you 512 бит =512 светодиодов // Поскольку мы модулируем светодиоды, используя 4-битное разрешение, каждый цвет имеет 4 массива по 64 бита в каждом байте red0 [LEDS_PER_LEVEL], red1 [LEDS_PER_LEVEL], red2 [LEDS_PER_LEVEL], red3 [LEDS_PER_LEVEL]; byte синий0 [LEDS_PER_LEVEL], синий1 [LEDS_PER_LEVEL], синий2 [LEDS_PER_LEVEL], синий3 [LEDS_PER_LEVEL]; байт зеленый0 [LEDS_PER_LEVEL], зеленый1 [LEDS_PER_LEVEL], зеленый2 [LEDS_PER_LEVEL], зеленый3 [LEDS_PER_LEVEL], увеличится разрешение] больше вашего драгоценного RAMint level =0; // отслеживает, на какой уровень мы смещаем данные int anodeLevel =0; // это увеличивается через уровни анода int BAM_Bit , BAM_Counter =0; // Переменные модуляции битового угла для отслеживания событийint animation =0; // Отслеживает анимацию в основном цикле // **** setup **** setup **** setup **** setup **** setup **** setup **** setup **** setup **** setup **** setup **** setup **** setup **** setupvoid setup () {SPI.setBitOrder (MSBFIRST); // Первый старший бит SPI.setDataMode (SPI_MODE0); // Режим 0 Нарастающий фронт данных, сохраняйте низкую частоту SPI.setClockDivider (SPI_CLOCK_DIV2); // Запускаем данные с частотой 16 МГц / 2-8 МГц //Serial.begin(115200);// если вам это нужно? noInterrupts (); // уничтожаем прерывания до тех пор, пока все не будут настроены // Мы используем Таймер 1 для обновления куба TCCR1A =B00000000; // Регистрируем все 0, так как мы не переключаем никакие контакты TCCR1B =B00001011; // бит 3 установлен для перехода в режим CTC вызовет прерывание при совпадении счетчика // биты 0 и 1 настроены для деления тактовой частоты на 64, поэтому 16MHz / 64 =250kHz TIMSK1 =B00000010; // бит 1 установлен для вызова прерывания на OCR1A соответствует OCR1A =30; // вы можете поиграть с этим, но я установил его на 30, что означает:// наши часы работают на частоте 250 кГц, что составляет 1/250 кГц =4 мкс // с OCR1A, установленным на 30, это означает, что прерывание будет вызываться каждые ( 30 + 1) x4us =124us, // что дает частоту мультиплексирования около 8 кГц // наконец настраиваем выводы pinMode (LATCH_PIN, OUTPUT); // фиксируем pinMode (DATA_PIN, OUTPUT); // MOSI DATA pinMode (CLOCK_PIN, OUTPUT); // SPI Clock pinMode (LAYER_A, OUTPUT); // 74138 A Вход pinMode (LAYER_B, OUTPUT); // 74138 B Вход pinMode (LAYER_C, OUTPUT); // 74138 C Вход digitalWrite (LAYER_A, LOW); digitalWrite (СЛОЙ_B, НИЗКИЙ); digitalWrite (LAYER_C, LOW); pinMode (SWITCH_PGM, INPUT); // Переключение PGM 1 / PGM 2 pinMode (SWITCH_SEQ, INPUT); // Переключение SEQ / COLOR // pinMode (BLANK_PIN, OUTPUT); // Разрешение вывода важно, чтобы сделать это последним, поэтому светодиоды делают не мигает при загрузке SPI.begin (); // запускаем библиотеку SPI interrupts (); // позвольте шоу начаться, это позволяет начать мультиплексирование} // *** start loop *** start loop *** start loop *** start loop *** start loop *** start loop *** start loop *** start loop *** start loopvoid loop () {// Каждая анимация, находящаяся в подпрограмме // Для управления LED, вы просто:// LED (уровень, который вы хотите 0-CUBE_MAX, строка, которую вы хотите 0-CUBE_MAX, столбец, который вы хотите 0-CUBE_MAX, яркость красного 0-15, яркость зеленого 0-15, яркость синего 0-15); если (digitalRead (SWITCH_PGM) ==HIGH) test_leds (); else {clean (); анимация =анимация + 1; переключатель (анимация) {case 1:rainVersionTwo (20); ломать; случай 2:папка (10); ломать; случай 3:sinwaveTwo (15); ломать; случай 4:randomColor (10); ломать; случай 5:wipe_out (10); ломать; случай 6:bouncyvTwo (15); ломать; case 7:color_wheelTWO (10); ломать; случай 8:harlem_shake (); ломать; корпус 9:рябь (10); ломать; случай 10:анимация =0; ломать; }}} // **** LED Routine **** LED Routine **** LED Routine **** LED Routinevoid LED (int level, int row, int column, byte red, byte green, byte blue) { // Здесь все начинается. либо 0, либо 7 для местоположения, и 0 или 15 для уровня яркости =ограничение (level, 0, CUBE_MAX); строка =ограничение (строка, 0, CUBE_MAX); столбец =ограничение (столбец, 0, CUBE_MAX); красный =ограничение (красный, 0, 15); зеленый =ограничение (зеленый, 0, 15); синий =ограничение (синий, 0, 15); // В кубе есть светодиоды (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE), поэтому, когда мы пишем на уровень 2, столбец 5, строку 4, это нужно преобразовать в число от 0 до (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) - 1 // Светодиоды первого уровня идут первыми в последовательности, затем 2-й уровень, затем третий и так далее // Для куба 4 x 4 x 4 (level * (4 * 4)) - это то, что индексирует начальную позицию уровня, поэтому уровень 0 - это светодиоды 0-15, уровень 1 - светодиоды 16-31 и так далее // если вы смотрели на куб, а смотрели только на нижний уровень // 00 01 02 03 // 04 05 06 07 / / 08 09 10 11 // 12 13 14 15 // Для куба 8 x 8 x 8 (level * (8 * 8)) - это то, что индексирует начальную позицию уровня, поэтому уровень 0 - это светодиоды 0-63, уровень 1 это светодиоды 64-127 и т. д. // если вы смотрели на куб сверху вниз и смотрели только на нижний уровень // 00 01 02 03 04 05 06 07 // 08 09 10 11 12 13 14 15 // 16 17 18 19 20 21 22 23 // 24 25 26 27 28 29 30 31 // 32 33 34 35 36 37 38 39 // 40 41 42 43 44 45 46 47 // 48 49 50 51 52 53 54 55 // 56 57 5 8 59 60 61 62 63 // Затем, если вы увеличили уровень, верхний правый угол сетки выше начнется с (CUBE_SIZE * CUBE_SIZE) // Причина этого в том, что вам не нужно запоминать число для каждого светодиода, что позволяет использовать уровень, строку, столбец // А как насчет деления на 8? //... ну, у нас 8 бит на байт, и у нас есть 64 байта в памяти для всех 512 бит, необходимых для каждого светодиода, поэтому // мы делим только что найденное число на 8 и берем его целое число, Итак, мы знаем, в каком байте находится этот бит // запутались? это нормально, давайте возьмем пример, если бы мы хотели записать в светодиод до последнего светодиода в кубе, мы бы написали 7, 7, 7 // давая (7 * 64) + (7 * 8) =7 =511, что верно, но теперь давайте разделим его на 8, 511/8 =63,875 и возьмем int, чтобы получить 63, // это последний байт в массиве, что верно, поскольку это последний светодиод // Получить номер светодиода 0-511 int allbyte =(level * LEDS_PER_LEVEL) + (row * CUBE_SIZE) + column; // Получаем индекс в массив. Каждая проиндексированная ячейка содержит один байт или 8 бит; int whichbyte =int (целый байт / 8); int whichbit =(весь байт &7); // Все это обретет смысл через секунду // Это 4-битное цветовое разрешение, поэтому каждый цвет содержит массивы x4 по 64 байта, объяснение ниже:bitWrite (red0 [whichbyte], whichbit, bitRead (red, 0)); bitWrite (красный1 [whichbyte], whichbit, bitRead (красный, 1)); bitWrite (красный2 [whichbyte], whichbit, bitRead (красный, 2)); bitWrite (red3 [whichbyte], whichbit, bitRead (красный, 3)); bitWrite (green0 [whichbyte], whichbit, bitRead (зеленый, 0)); bitWrite (зеленый1 [whichbyte], whichbit, bitRead (зеленый, 1)); bitWrite (зеленый2 [whichbyte], whichbit, bitRead (зеленый, 2)); bitWrite (зеленый3 [whichbyte], whichbit, bitRead (зеленый, 3)); bitWrite (blue0 [whichbyte], whichbit, bitRead (синий, 0)); bitWrite (blue1 [whichbyte], whichbit, bitRead (синий, 1)); bitWrite (blue2 [whichbyte], whichbit, bitRead (синий, 2)); bitWrite (blue3 [whichbyte], whichbit, bitRead (синий, 3)); // Вы еще больше запутались? Не должно быть! Теперь это начинает обретать смысл. Обратите внимание на то, что каждая строка представляет собой bitWrite, // bitWrite (байт, который вы хотите записать, бит байта, который нужно записать, и 0 или 1, которые вы хотите записать) // Это означает, что 'whichbyte' это байт от 0 до 63, в котором бит соответствует светодиоду от 0 до 511 // Теперь имеет смысл, почему мы это сделали? принимает значение от 0 до 511 и преобразует его в значение от 0 до 63, поскольку каждый светодиод представляет собой // бит в массиве из 64 байтов. // Затем следующая строка - это какой бит 'allbyte- (8 * whichbyte)' // Это просто берет значение светодиода 0-511 и вычитает его из БАЙТА, ​​его бит был расположен в 8 раз // Подумайте об этом, байт 63 будет содержать светодиоды от 504 до 511, поэтому, если вы взяли 505- (8 * 63), вы получите 1, что означает, что // светодиод номер 505 находится в бите 1 байта 63 в массиве // это то, что Это? Нет, вам все равно нужно выполнить бит Считывание яркости 0-15, которую вы пытаетесь записать, // если вы написали 15 в КРАСНЫЙ, все 4 массива для этого светодиода будут иметь 1 для этого бита, что означает, что он будет включен 100% // Вот почему четыре массива читают 0-4 значения, введенного для КРАСНОГО, ЗЕЛЕНОГО и СИНЕГО // надеюсь, все это имеет какой-то смысл?} // *** MultiPlex BAM *** MultiPlex BAM ** * MultiPlex BAM *** MultiPlex BAM *** MultiPlex BAM *** MultiPlex BAM *** MultiPlex BAMISR (TIMER1_COMPA_vect) {// Эта процедура вызывается в фоновом режиме автоматически с частотой, установленной OCR1A // В этом коде я установил OCR1A до 30, поэтому это вызывается каждые 124 мкс, давая каждому уровню в кубе 124 мкс времени включения // Есть 8 уровней, поэтому у нас есть максимальная яркость 1/8, так как уровень должен отключиться до того, как будет достигнут следующий уровень. включен // Частота мультиплексирования равна 124 мкс * 8 =992 мкс, или 1/992 мкс =около 1 кГц PORTD | =1 < =CUBE_SIZE) {fx =CUBE_MAX; fxm =-1; } ломать; случай 1:fy =fy + fym; если (fy <0) {fy =0; fym =1; } если (fy> =CUBE_SIZE) {fy =CUBE_MAX; фим =-1; } ломать; случай 2:fz =fz + fzm; если (fz <0) {fz =0; fzm =1; } если (fz> =CUBE_SIZE) {fz =CUBE_MAX; fzm =-1; } ломать; } переключатель (случайный (3)) {case 0:ftx =ftx + ftxm; если (ftx <0) {ftx =0; ftxm =1; } если (ftx> =CUBE_SIZE) {ftx =CUBE_MAX; ftxm =-1; } ломать; случай 1:fty =fty + ftym; если (fty <0) {fty =0; ftym =1; } если (fty> =CUBE_SIZE) {fty =CUBE_MAX; ftym =-1; } ломать; случай 2:ftz =ftz + ftzm; если (ftz <0) {ftz =0; ftzm =1; } если (ftz> =CUBE_SIZE) {ftz =CUBE_MAX; ftzm =-1; } ломать; }} // while clean ();} // wipeout // **** rainVersionTwo **** rainVersionTwo **** rainVersionTwo **** rainVersionTwo **** rainVersionTwovoid rainVersionTwo (int runtimeInSeconds) {int x [LEDS_PER_LEVEL ], y [LEDS_PER_LEVEL], z [LEDS_PER_LEVEL], ledcolor; int xx [LEDS_PER_LEVEL], yy [LEDS_PER_LEVEL], zz [LEDS_PER_LEVEL], xold [LEDS_PER_LEVEL], yold [LEDS_PER_LEVEL], zold [LEDS_PER_LEVEL]; для (int addr =0; addr  =200 &&ledcolor <300) {for (int addr =0; addr  =300 &&ledcolor <400) {} if (ledcolor> =500 &&ledcolor <600) {} ledcolor ++; если (ledcolor> =300) ledcolor =0; для (int addr =0; addr  

Схема

eagle_files_WfqPEUP7Mp.zip

Производственный процесс

  1. Сигнал тревоги для растений, предупреждающий о жажде
  2. Светодиодный куб 5x5x5
  3. Итальянские часы со словами
  4. Счетчик кВтч Sigfox
  5. Цветовой микшер Arduino RGB
  6. Монитор температуры Bluetooth
  7. Светодиодный уличный светодиод DMX RGB
  8. Блокировка, управляемая жестами
  9. Изолированный аналоговый вход для Arduino
  10. Измерьте время реакции