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!