четверг, 24 января 2019 г.

Raspberry PI + DMX+MODBUS= Фонтан!


Как управлять фонтаном с помощью одноплатного компьютера

Часть 1
Электроника год от года становиться все более дешевой, что открывает большие возможности в ее применении в различных устройствах. Электроника везде, в кухонных комбайнах, автомобилях, стиральных машинах. Она окружает нас повсюду.
В последнее время широкое распространение получили одноплатные компьютеры. Ярким представителем этого семейства является raspberry pi.

                                               Raspberry pi Ver 3 B

Изначально разработанный по заказу Министерства Образования Великобритании он быстро обрел популярность среди инженеров и разработчиков, а также различного рода энтузиастов. Теперь можно встретить этот компьютер и его аналоги везде. От систем управления электрической сетью небольшого городка, до средств навигации яхт и катеров.

Я же попробую использовать это устройство еще в одной необычной сфере – танцующих фонтанах. Данный цикл статей последовательно ознакомит читателя со способами управления фонтанами, какие промышленные протоколы используются в фонтанах и какие устройства позволяют в итоге получить красивую игру воды и света, в добавок с музыкальным сопровождением.  
Прежде чем приступить к описанию алгоритма работы системы управления фонтаном обсудим каким образом будем управлять им.
Для управления светом и водой используются специальные устройства, для света диммеры, для насосов, качающих воду – частотные преобразователи.  Передача данных от контроллера к исполнительным устройствам осуществляется посредством различных протоколов. Есть два, наиболее распространённых, DMX 512 – используется для управления различными световыми устройствами и MODBUS – для управления частотными преобразователями, контролирующими работу насосов.
DMX 512 и MODBUS являются промышленными протоколами, которые широко распространены в системах управления. В этой статье мы рассмотрим протокол DMX и его программную реализацию на raspberry pi.
Оба протокола упомянутых выше являются надстройкой над протоколом физического уровня RS485. Рассмотрим более подробно протокол DMX.   



Сам протокол представляет набор импульсов, сгенерированных в определенной последовательности. Минимальная длительность одного импульса, согласно требованиям стандарта – 4 миллисекунды. Передача данных осуществляется пакетами. За один сеанс передачи данных можно передать 512 значений. Каждое значение в пакете состоит из 11 импульсов. 1 – стартовый бит, 8 бит данных и два стоп бита. Стартовый бит всегда низкого уровня, стоп биты – высокого уровня, их, согласно протоколу, всегда два.

Ниже приведена временная таблица протокола DMX512 (1990).
Описание
Минимум, мкс
Стандарт, мкс
Максимум, мкс
Break
88
88
1000000
МАВ
8
Длина Кадра Данных
44
Стартовый бит
4
Стоповый бит
4
Бит байта данных
4
MTBF
0
по усмотрению разработчика
1000000
МТВР
0
по усмотрению разработчика
1000000
        Теперь, когда мы подробно рассмотрели протокол перейдем к описанию физической реализации.  Наша задача управлять светимостью фонарей, которые подсвечивают струи. В настоящее время есть широкий ассортимент устройств, преобразующих DMX пакеты в ШИМ сигнал.  Я буду использовать устройство k16 DMX производства ООО «Световод».

       Как видно из рисунка приемное устройство имеет 16 выходных каналов. По умолчанию адресация каналов начинается с 1 и до 16, то есть приняв пакет с данными с DMX данными мы можем на выход выдать только 16 значений. Как быть, если у нас задействовано больше 16 каналов? В этом случае приемные устройства можно соединить между собой последовательно и каждому устройству задать адрес, начиная с которого оно будет обрабатывать принятые данные. К примеру, нам нужно обработать 32 канала. Начальный адрес первого устройства мы зададим равным 1, учитывая, что устройство обрабатывает 16 каналов, значит адрес, с которого будет обрабатывать входные данные второе устройство должен быть равным 1+16=17 и т.д. При этом необходимо помнить, что согласно стандарту DMX, возможно обработать не более 512 значений в одном пакете. На самом деле, в профессиональных устройствах, можно адресовать до 1536 значений. Мы же ограничимся стандартом и будем считать, что за один раз мы можем передать не более 512 значений.  
Для того, чтобы передать данные от RASPBERRY PI к управляющему устройству будем использовать преобразователь RS485-TTL, так как протокол DMX является надстройкой над протоколом RS485.
Raspberry  Pi может работать под управлением нескольких разновидностей операционных систем. В нашем случае это будет дистрибутив RASPBRIAN Linux. Он основан на широко распространенном дистрибутиве DEBIAN. ОС Linux, строго говоря, не является ОС реального времени, поэтому приходиться прибегать к различным ухищрениям что бы генерировать импульсы нужной нам длительности. Перед тем как приступить к проекту пришлось обратиться к Всемирной паутине, к моему удивлению я нашел всего лишь одну статью, посвященную генерации DMX сигнала на RASPBERRY PI. Статью можно прочесть здесь http://www.jonshouse.co.uk/rpidmx512.cgi.
Обычно для работы с шиной GPIO используют библиотеку WiringPi. К сожалению, данная библиотека не дает возможность генерации импульсов длительностью в 4 мкс.  Кроме того, мы не сможем воспользоваться стандартным UART, из-за того, что он не осуществляет передачу данных на скорости 250 бод.  Но решение есть, это библиотека pigpio. С помощью этой библиотеки можно сформировать импульсы нужной длительности.  В качестве основы я взял алгоритм предложенный Джонатаном Эндрю (Jonathan Andrew ), автора вышеупомянутой статьи.
Основная идея заключается в том, чтобы напрямую использовать DMA I/O. Фактически мы создаем виртуальный UART, который будет работать со скоростью 250 бод

Схема подключения RASPBERRY PI к контроллеру К16

Физически, мы подключаем выводы GPIO17, GPIO27 и GPIO22 к выводам микросхемы MAX485

                   GPIO22 – DI - вход, сюда мы передаем наши импульсы
                   GPIO27 – DE – если на этом входе высокий уровень, то
                                              передача разрешена.
                   GPIO17 – RE – если на входе низкий уровень, то прием данных
                                              разрешен. Поскольку мы не будем принимать
                                              данные, то на этот вход всегда подаем высокий
                                              уровень.

Поскольку данные от контроллера мы не принимаем, то вывод RO не используется.
Алгоритм инициализации DMX будет выглядеть так:




Функция build_dmx_packet() выглядит следующим образом:

int build_dmx_packet()
{
        int ch;
        int pidx;

        pidx=0;
#ifdef PREPACKET_IDLE_US
        output_high(&pidx,PREPACKET_IDLE_US); // idle
#endif
        output_low(&pidx,BREAK_US); // BREAK
        output_high(&pidx,MAB_US);  // MAB (Mark after break)
        output_serialbyte(&pidx,0); // "Стартовый код" всегда 0 плюс 2 стоп бита

        for (ch=1;ch<=512;ch++)  // для каждого DMX канала
               output_serialbyte(&pidx,dmx_values[ch]); //  DMX channels, 8
               //формируем все 512 DMX каналов по 8 бит плюс 2 стоп бита

        output_high(&pidx,POSTPACKET_IDLE_US); // idle
        return(pidx); // возвращаем значение кол-ва сформированных бит                                                                
}

И функция отправки данных send_dmx_packet():

send_dmx_packet(int numbits)
{
        int wave_id=0;
 
        gpioWaveAddGeneric(numbits, pulse);
        //printf("generated %d bits\n",numbits);
        gpioWrite_Bits_0_31_Set( (1<<DE) );
       // Разрешаем передачу, DE в высокий уровень                          
        wave_id = gpioWaveCreate();
        gpioWaveTxSend(wave_id, PI_WAVE_MODE_ONE_SHOT);
// Отправка битового паттерна через DMA IO
        
        while (gpioWaveTxBusy()==1) // Ждем пока DMA I/O завершит передачу данных 
               usleep(20);          // И еще немного ждем
 
        gpioWaveDelete(wave_id);    // завершаем работу с этим паттерном
        gpioWrite_Bits_0_31_Clear( (1<<DE) ); 
// DE в низкий уровень (завершаем передачу)
        //usleep(1000);               
}

Таким образом мы можем управлять светом. Поскольку наша задача управлять танцем света и воды, то создадим файл в котором будут записаны значения цветовой гаммы для каждого фонаря в фонтане в текущий момент времени, пусть квант времени будет равен 1/20  секунды.  Значения будут храниться в текстовом виде со следующей структурой:

Lamp1   R
               G
               B
               W
Lamp2   R
               G
               B
               W

и т.д.

И окончательный алгоритм работы будет выглядеть так :



         Исходный текст является лишь учебным примером, того, как может работать программа управления светом фонтана. Поэтому я ограничил длину световой композиции 200 единицами.  Кроме того, нет точного учета времени работы партитуры, просто все данные выводятся последовательно в цикле, без использования каких -либо таймеров.
Текст можно скачать по ссылке. Если Вы хотите познакомиться моими  другими проектами из этой области, то можете посетить мой сайт http://www.johnson-robot.ru
После того, как скачаете, необходимо распаковать архив в любую папку, извлеките из архива версию библиотеки PIGPIO, разархивируйте ее, или же скачайте более свежую версию библиотеки по ссылке которую я привел выше.
Далее заходим в каталог куда извлекли библиотеку и собираем ее:

                # cd PIGPIO
                # make
                # make install
                # cd ..


   Затем собираем нашу программу

               # gcc -Wall -pthread -o dmx_ctrl dmx_ctrl.c -lpigpio -lrt
              # sudo ./prog 1 l2.prt
   
и запускаем ее, в качестве параметров указываем стартовый DMX  адрес и файл с цветовой композицией. Обратите внимание, что программу запускаем из под sudo, так как иначе мы не получим доступ к DMA!!!
Ну и напоследок несколько фотографий с эксперимента:




а так же видео 

В следующей части я познакомлю читателя с протоколом MODBUS  и каким образом можно управлять с помощью него насосами. 









      




  

Комментариев нет:

Отправить комментарий