DMX-512 Визуализация уровней каналов

siplix
Offline
Зарегистрирован: 05.04.2014

Собираю устройство, которое подключается к 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;
        }
    }
  
}

 

siplix
Offline
Зарегистрирован: 05.04.2014

Да, кстати, если выдавать сигнал на 16 каналов, то отображается все коректно. 

Sh0a1m0a0n1
Offline
Зарегистрирован: 16.09.2016

UP!