DMX-512 Визуализация уровней каналов
- Войдите на сайт для отправки комментариев
Собираю устройство, которое подключается к DMX-512 контроллеру, получает от него данные и отображает уровни каналов на дисплее. Использован двухстрочный символьный дисплей, подключенный через SPI-драйвер.
В первой строке отображаются уровни каналов в виде столбиков, во второй - первый отображаемый на дисплее канал и общее количество каналов, на которые контроллер выдает данные.
Есть возможность листать диапазон отображаемых каналов вдумя кнопками.
Все собрал, прошил, и даже работает, но есть один косяк. В момент запуска микроконтроллера в первом отображаемом кадре вся информация верна, при отображении последующих кадров, arduino кудато-съедает несколько каналов.
Т.е. если контроллер выдает 60 каналов, то в момент включения или перезагрузки arduino, отображается общее количество каналов 60 и первый канал на дисплее является действительно первым. Но сразу после смены кадров, отображается количество кадров 57, а первым отображается, в реальности пятый.
Пробовал еще загонять сигнал на 30 каналов - тоже самое, только сначала все правильно, а потом показывает общее количество каналов 29, а на месте первого показывает вообще непонятно что.
Все остальное работает без проблем - прокрутка листает.
У же целый день смотрю в код и не пойму в чем косяк. Может кто-нибудь свежим взглядом увидит...
Вот код:
#include <Conceptinetics.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #define DMX_SLAVE_CHANNELS 100 //ЕСЛИ БУДУТ ПРОБЛЕМЫ ТО УМЕНЬШИТЬ LiquidCrystal_I2C lcd(0x27,16,2); DMX_Slave dmx_slave ( DMX_SLAVE_CHANNELS ); unsigned long lastFrameReceivedTime; unsigned long lastFrameTranceivedTime; byte qa[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111 }; byte ws[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111 }; byte ed[8] = { B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111 }; byte rf[8] = { B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111 }; byte tg[8] = { B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111 }; byte yh[8] = { B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111 }; byte uj[8] = { B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; byte ik[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; int lvAr[DMX_SLAVE_CHANNELS]; // Входящие значения DMX-512 каналов int outAr [16]; // Значения каналов, выводимые на дисплей int chRx; // количество принятых каналов /////////////////////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #define KEY_BUTTON_1_PIN A2 //пин к которому подключена панель управления int KeyButton1Value=0; //значение с панели управления long KeyButton1TimePress=0; //последнее время когда на панели не было нажатых кнопок long KeyButton1Latency=100000; //задержка перед считыванием состояния панели управления после нажатия int KeyButton1WasChecked=0; //метка означающая что нажатие кнопки на панели было обработано long KeyButton1RepeatLatency=1500000; //время после которого удерживание кнопки начинает засчитываться как многократные быстрые нажатия long KeyButton1RepeatTimePress=0; //вспомогательная переменная для обработки повторных нажатий long KeyButton1TimeFromPress=0; //переменная для хранения времени между временем когда не было зажатых кнопок и временем проверки long KeyBoardTime1=0; // long KeyBoardTime2=0; // Переменные для обработки времени для обработки событий клавиатуры long KeyBoardTimeInterval=25000; // int start = 0; // +1 номер канала, который выводится на экран первым void setup() { dmx_slave.enable (); dmx_slave.setStartAddress (1); dmx_slave.onReceiveComplete ( OnFrameReceiveComplete ); Wire.begin(); lcd.init(); lcd.backlight(); lcd.home(); lcd.createChar(0,qa); lcd.createChar(1,ws); lcd.createChar(2,ed); lcd.createChar(3,rf); lcd.createChar(4,tg); lcd.createChar(5,yh); lcd.createChar(6,uj); lcd.createChar(7,ik); lcd.clear(); pinMode (KEY_BUTTON_1_PIN, INPUT); pinMode (10, OUTPUT); pinMode (11, OUTPUT); pinMode (12, OUTPUT); pinMode (13, OUTPUT); } void loop() { digitalWrite(10, 1); // 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 //проверка таймера для обработки нажатий клавиатуры KeyBoardTime2=micros(); if ((KeyBoardTime2-KeyBoardTime1)>KeyBoardTimeInterval) { KeyBoardTime1=KeyBoardTime2; KeyBoardCalculate(); } digitalWrite(10, 0); // 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 digitalWrite(13, 1); // 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 if (lastFrameReceivedTime > lastFrameTranceivedTime){ printLevel (outAr); // Вывод значений на дисплей lastFrameTranceivedTime = millis(); } digitalWrite(13, 0); // 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 } void OnFrameReceiveComplete (unsigned short channelsReceived) { digitalWrite(11, 1); // 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 chRx = int(channelsReceived); for (int i=0; i<chRx; i++){ lvAr[i] = dmx_slave.getChannelValue (i+1); } for (int i=0; i<16; i++){ outAr[i]=lvAr[i+start]; } lastFrameReceivedTime = millis(); digitalWrite(11, 0); // 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 } void printLevel(int lv[16]) { digitalWrite(12, 1); // 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 byte dispLv[16]; for (int i=0; i<16; i++){ switch (lv[i]/32) { //// добавить регулировку чувствительности case 0: dispLv[i]=0; break; case 1: dispLv[i]=1; break; case 2: dispLv[i]=2; break; case 3: dispLv[i]=3; break; case 4: dispLv[i]=4; break; case 5: dispLv[i]=5; break; case 6: dispLv[i]=6; break; case 7: dispLv[i]=7; break; } } digitalWrite(12, 0); // 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 digitalWrite(12, 1); // 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 lcd.setCursor(0, 0); for (int i=0; i<16; i++){ lcd.write(dispLv[i]); } lcd.setCursor(0, 1); // lcd.print("^"); // Вывод общего количества lcd.print(" Total:"); // принятых каналов lcd.print(chRx); // lcd.setCursor(1, 1); // и номер первого канала на дисплее lcd.print(start+1); // digitalWrite(12, 0); // 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 } void UpPress() { if((start) < (chRx-15)) start++; } void DownPress() { if(start > 0) start--; } void ButtonPress() { if ((KeyButton1Value>150) and (KeyButton1Value<300)) { UpPress(); } if ((KeyButton1Value>350) and (KeyButton1Value<650)) { DownPress(); } } void KeyBoardCalculate() { //Часть отработки нажатия клавиши KeyButton1Value=analogRead(KEY_BUTTON_1_PIN); //если сигнал с кнопки нулевой то обнуляем метку обработки нажатия if ((KeyButton1Value<=50) or (KeyButton1Value>=1000)) { //Сохраняем время последнего сигнала без нажатой кнопки KeyButton1TimePress=micros(); KeyButton1WasChecked=0; KeyButton1RepeatTimePress=0; } KeyButton1TimeFromPress=micros()-KeyButton1TimePress; //исключаем шумы if ((KeyButton1Value>50) and (KeyButton1Value<1000)) { //отработка первого нажатия if ( ((KeyButton1TimeFromPress)>KeyButton1Latency) and (KeyButton1WasChecked==0)) { KeyButton1Value=analogRead(KEY_BUTTON_1_PIN); ButtonPress(); KeyButton1WasChecked=1; KeyButton1RepeatTimePress=0; } //отработка повторных нажатий if ( ((KeyButton1TimeFromPress)>(KeyButton1RepeatLatency+KeyButton1RepeatTimePress)) and (KeyButton1WasChecked==1)) { KeyButton1Value=analogRead(KEY_BUTTON_1_PIN); ButtonPress(); KeyButton1RepeatTimePress=KeyButton1RepeatTimePress+100000; } } }
Да, кстати, если выдавать сигнал на 16 каналов, то отображается все коректно.
UP!