Стал глубже погружаться в мир театрального света и стало интересно, как же оно работает.
Световое оборудование сейчас управляется по DMX-512. Этот протокол работает на сетях RS-485. DMX-512 крайне простая штука. Представляет собой до 512 байт с данными о значении канала, передаваемых последовательно. И все. На самом деле вовсе не обязательно отправлять все 512 байт, но если нужно сказать, что изменилось значение на, допустим, 27 канале, то необходимо отправить значения не только измененного канала, но и все предыдущие. Остальные 485 каналов отправлять вовсе не нужно. Но в рамках данной статьи можно опустить эти подробности. Ведь мы собираемся читать, а не писать.
Для устройства я выбрал ATmega8, но, забегая вперед, скажу, что по объему памяти она бы поместилась и на Tiny13. Вот только Tiny13 не умеет тактироваться от кварца да и аппаратного UART в нем нет. Подошла бы Tiny2313, но разница в цене настолько мала, что можно и раскошелиться на более крутое железо.
Первым делом инициализируем USART на скорости 250 000.
#define USART_BAUDRATE 250000 #define UBRR_VALUE (F_CPU/16/USART_BAUDRATE-1) void USART_Init() { // Set baud rate UBRRH = (uint8_t)(UBRR_VALUE>>8); UBRRL = (uint8_t)UBRR_VALUE; /* Set frame format: 8data, 2stop bit */ UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); //enable reception UCSRB |= (1<<RXEN); // разрешаем прерывание по приему байта UCSRB |= (1<<RXCIE); }
Тут все достаточно просто. Не забываем включить прерывание, так как программно на такой скорости работать не рекомендуется.
#define COUNT_CHANNELS 6 unsigned char data[COUNT_CHANNELS]; unsigned int DMX_Current_Channel = 0; unsigned int DMX_Start_Channel = 0; ISR(USART_RXC_vect) { int index = DMX_Current_Channel - DMX_Start_Channel - 1; if ((index >= 0) && (index < COUNT_CHANNELS)){ data[index] = UDR; } DMX_Current_Channel++; }
Создаем глобальный массив под интересующие данные. Для этого нужно задать сколько каналов интересуют и начальный адрес. Глобальный массив позволяет задавать данные в прерывании и использовать эти данные в основном цикле программы.
В качестве средств визуализации на моей отладочной плате есть экран, семисегментные индикаторы или же полоска светодиодов. Экран слишком жирно. Полоска, конечно, вещь интересная и наглядная, но более информативным окажется отображение данных в виде числа. Что такое динамическая индикация думаю все здесь уже знают.
Но в данном виде, как сейчас, прошивка работать не будет. Самой сложной задачей является разделение посылок между собой. Для этих целей предусмотрен интервал тишины. Линия RX опускается в 0, что означает старт-бит. Далее микроконтроллер ждет данные и 2 стоп-бита. Последних он так и не дожидается, что генерирует ошибку «Frame Error», позволяющую определить начало новой передачи.
В итоге получаем следующий код:
ISR(USART_RXC_vect) { unsigned char UART_Status = UCSRA; unsigned char UART_Data = UDR; // Обнаружена ошибка (Frame error) if (UART_Status & (1<<FE)){ DMX_Current_Channel = 0; DMX_Break = 1; } else if (DMX_Break == 1){ int index = DMX_Current_Channel - DMX_Start_Channel - 1; if ((index >= 0) && (index < COUNT_CHANNELS)){ data[index] = UART_Data; } DMX_Current_Channel++; } }
Добавилась только переменная — флаг. Что сигнал break был пойман. Дополнительное условие (DMX_Break == 1) нужно для того, чтобы избежать ситуации, когда устройство включили в сеть прямо во время активной передачи. Тогда на линии идут корректные пакеты, но в данный момент идет вовсе не значение первого канала, а, допустим, 123. И мы получим ошибочное значение. Реальное же будет только в новой посылке.
К статье приложены два варианта устройств. первый — игрушка. Тестер линии с отображением данных первого канала на семисегментных индикаторах. Практической пользы от такого устройства мало, но для обучения можно и собрать на макетной плате.
Второе же устройство куда полезнее. В нем я использовал два канала с ШИМ, данные для которых поступают по DMX-512. Его можно использовать для оцифровки старых аналоговых диммеров, управляемых сигналом 0-10 Вольт (добавив операционный усилитель), или же для сборки собственных приборов. Например LED прожектор или даже, при наличии пары сервоприводов, полноценная голова! Тут только стоит проявить фантазию!
Минимальная схема будет следующей:
Список радиоэлементов
Обозначение | Тип | Номинал | Количество | Примечание | Магазин | Мой блокнот |
---|---|---|---|---|---|---|
IC1 | МК AVR 8-бит | ATmega8 | 1 | |||
IC2 | ИС RS-422/RS-485 интерфейсов | MAX485 | 1 | |||
Q1 | Кварц | 16 МГц | 1 | |||
R1 | Резистор | 10 кОм | 1 | |||
C1, C2 | Конденсатор | 22 пФ | 2 | |||