Собираю устройство, которое подключается к DMX-512 контроллеру, получает от него данные и отображает уровни каналов на дисплее. Использован двухстрочный символьный дисплей, подключенный через SPI-драйвер. В первой строке отображаются уровни каналов в виде столбиков, во второй - первый отображаемый на дисплее канал и общее количество каналов, на которые контроллер выдает данные. Есть возможность листать диапазон отображаемых каналов вдумя кнопками. Все собрал, прошил, и даже работает, но есть один косяк. В момент запуска микроконтроллера в первом отображаемом кадре вся информация верна, при отображении последующих кадров, arduino кудато-съедает несколько каналов. Т.е. если контроллер выдает 60 каналов, то в момент включения или перезагрузки arduino, отображается общее количество каналов 60 и первый канал на дисплее является действительно первым. Но сразу после смены кадров, отображается количество кадров 57, а первым отображается, в реальности пятый. Пробовал еще загонять сигнал на 30 каналов - тоже самое, только сначала все правильно, а потом показывает общее количество каналов 29, а на месте первого показывает вообще непонятно что. Все остальное работает без проблем - прокрутка листает. У же целый день смотрю в код и не пойму в чем косяк. Может кто-нибудь свежим взглядом увидит... Вот код: Код (C++): #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() { //проверка таймера для обработки нажатий клавиатуры KeyBoardTime2=micros(); if ((KeyBoardTime2-KeyBoardTime1)>KeyBoardTimeInterval) { KeyBoardTime1=KeyBoardTime2; KeyBoardCalculate(); } if (lastFrameReceivedTime > lastFrameTranceivedTime){ printLevel (outAr); // Вывод значений на дисплей lastFrameTranceivedTime = millis(); } } void OnFrameReceiveComplete (unsigned short channelsReceived) { chRx = int(channelsReceived); for (int i=0; i<chRx; i++){ lvAr = dmx_slave.getChannelValue (i+1); } for (int i=0; i<16; i++){ outAr=lvAr[i+start]; } lastFrameReceivedTime = millis(); } void printLevel(int lv[16]) { byte dispLv[16]; for (int i=0; i<16; i++){ switch (lv/32) { //// добавить регулировку чувствительности case 0: dispLv=0; break; case 1: dispLv=1; break; case 2: dispLv=2; break; case 3: dispLv=3; break; case 4: dispLv=4; break; case 5: dispLv=5; break; case 6: dispLv=6; break; case 7: dispLv=7; break; } } lcd.setCursor(0, 0); for (int i=0; i<16; i++){ lcd.write(dispLv); } lcd.setCursor(0, 1); // lcd.print("^"); // Вывод общего количества lcd.print(" Total:"); // принятых каналов lcd.print(chRx); // lcd.setCursor(1, 1); // и номер первого канала на дисплее lcd.print(start+1); // } 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 каналов, то отображается все коректно.
Какой контроллер DMX используете? Меня смущает фраза " и общее количество каналов, на которые контроллер выдает данные.". Могу ошибаться но протокол DMX 512 подразумевает выдачу сигнала сразу на все 512 каналов от 0 до 255. Ведь если вы подключаете пульт с задранными каналами предположим от 1 до 100, а остальные в ноль , то приборы стоящие на адресе от 101 до 512 послушненько молчат не из-за того что к ним не чего не приходит , а из-за того что к ним приходят нули по адресам.
Интересен другой момент!!! Если Arduino дружит с этим протоколом , то возможно ли создания на ее основе контроллера который будет выдавать DMX 512 совместимый через usb c популярными программами типа Daslight Virtual Controller 3 ( 2) ( 1) или Sunlite Suite 2 (1)
Ради интереса цены http://musicbase.ru/item/443909 -- старая кстати цена сейчас около 40000руб. http://www.nicolaudie.com/ru/suite2ec.htm
Что сразу бросилось в глаза, вот это вот можно написать одной строкой: Код (C++): switch (lv/32) { //// добавить регулировку чувствительности case 0: dispLv=0; break; case 1: dispLv=1; break; case 2: dispLv=2; break; case 3: dispLv=3; break; case 4: dispLv=4; break; case 5: dispLv=5; break; case 6: dispLv=6; break; case 7: dispLv=7; break; } А именно: Код (C++): dispLv = lv/32; Код с китайского сайта?
Стандарт DMX512 не обязывает выдавать данные на все 512 каналов. Важна стартовая последовательность бит (импульс break, Mark-After-Break и стартовый код), а за ней могут быть данные хоть всего на 1 канал... И так по кругу...
Это мой код. Просто он еще в процессе разработки, и я пока эксперементировал со способами отображения информации на дисплее, поэтому встречаются подобные нелепости. Суть вопроса это не меняет и ни на что не влияет...