DMX-512送信されたチャンネルレベルの視覚化





職業ごとに、私はあらゆる種類の照明効果制御システムを開発する必要があります。 市場に出回っているコントローラーの機能が顧客にとって冗長である場合、ほぼ膝の上にある特定のオブジェクト用のシンプルなコントローラーを発明する必要があります。 課題は毎回ユニークです。 心臓のように脈動する1つのチャネルから始まり、DMX-512プロトコルまたはWS28xxチップで動作するデコーダーの「ガーランド」を制御します。



最も単純なDMXデコーダー




彼らは中国人からの小銭です。 私はこれらのデコーダーが大好きです。 彼らの助けを借りて、3〜512チャンネルのシステムを簡単に拡張できます。



私にとって最も便利なオプションは、有名なArduinoボードです。 Arduino Pro Miniの1ダースまたは2クローンをボックスに入れて、必要に応じてそのようなプロジェクトで使用すると非常に便利です。 私は彼が大好きです。なぜなら、そのベースでかなりコンパクトなデバイスをすばやく組み立てることができ、これらのクローンは裸のAtmaga328とほぼ同じ中国にあるからです。



そのため、DMX-512プロトコルで実行される次の16チャンネルコントローラーのエフェクトを開発するとき、エフェクトを1回デバッグして再度並べ替えるために、テーブルのツイストにワイヤーのウェブをレイアウトすることにうんざりしていました。 DMXパケットを分析するための機器の検索に戸惑いましたが、これらは非常にまれで非常に高価な機器であることがわかりました。 これにより、独自のDMXテスターを作成するようになりました。



最初に、リアルタイムでチャネルレベルを表示できるデバイスが必要であると判断しましたが、それで十分でしたが、少し考えてから、次のタスクリストを定義しました。





チャンネルレベルを列の形で表示するのが一般的でした。つまり、16x2文字のLCDディスプレイを使用している場合は、一度に1行で16チャンネルをすでに見ることができます。 なぜなら チャンネルは最大512まで使用できますが、表示されているチャンネル範囲をスクロールできると便利です。



さて、タスクが設定されたら、ハードウェアに移りましょう。 私が書いたように、コアにはArduino Pro Miniのクローンがあります:



MAX485に基づいて、最も単純なTTL-RS-485アダプタを介してデータを受信します。




さて、16x2 LCDディスプレイに情報を表示します(開発時に、最終的なデバイスに収まる同様の40x2ディスプレイをすでに注文したことをすぐに予約します)。 このすべてを、同志kumbr_87が説明するキーボードを使用して管理します。



すぐに言ってやった。



ブレッドボード上でプロトタイプを組み立てました




スケッチを書いた
#include <Wire.h> #include <LiquidCrystal.h> #include <Conceptinetics.h> #define DMX_SLAVE_CHANNELS 512 #define LCD_W 16 //     (     ) LiquidCrystal lcd(12, 11, 5, 4, 3, 2); DMX_Slave dmx_slave ( DMX_SLAVE_CHANNELS ); unsigned long lastFrameReceivedTime = 0; //    unsigned long lastFrameTranceivedTime = 0; //     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 }; byte outAr [LCD_W]; //  ,    unsigned short chRx; //    #define KEY_BUTTON_1_PIN A2 //     unsigned int KeyButton1Value=0; //   unsigned long KeyButton1TimePress=0; //       unsigned long KeyButton1Latency=100; //        unsigned int KeyButton1WasChecked=0; //       unsigned long KeyButton1RepeatLatency=1500; //           unsigned long KeyButton1RepeatTimePress=0; //      unsigned long KeyButton1TimeFromPress=0; //              unsigned long KeyBoardTime1=0; // unsigned long KeyBoardTime2=0; //         unsigned long KeyBoardTimeInterval=25; // byte start = 0; // +1  ,      void setup() { lcd.begin(LCD_W, 2); dmx_slave.enable (); dmx_slave.setStartAddress (1); dmx_slave.onReceiveComplete ( OnFrameReceiveComplete ); 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); pinMode (KEY_BUTTON_1_PIN, INPUT); pinMode (10, OUTPUT); pinMode (9, OUTPUT); digitalWrite(9, LOW); } void loop() { //      KeyBoardTime2=millis(); if ((KeyBoardTime2-KeyBoardTime1)>KeyBoardTimeInterval) { KeyBoardTime1=KeyBoardTime2; KeyBoardCalculate(); } if (lastFrameReceivedTime > lastFrameTranceivedTime){ //    printLevel (outAr); //     lastFrameTranceivedTime = millis(); } else if ((lastFrameReceivedTime==0 && lastFrameTranceivedTime ==0)||(KeyBoardTime2-lastFrameReceivedTime>2000)) { lcd.clear(); delay (500); lcd.setCursor(0, 0); lcd.print("NO SIGNAL"); delay (500); } } void OnFrameReceiveComplete (unsigned short channelsReceived) // ,      { chRx = channelsReceived; //  ,       for (byte i=0; i<LCD_W; i++){ //           outAr[i]=dmx_slave.getChannelValue (i+start+1); } lastFrameReceivedTime = millis(); } void printLevel(byte lv[LCD_W]) //      { byte dispLv[LCD_W]; for (byte i=0; i<LCD_W; 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; } } lcd.setCursor(0, 0); for (byte i=0; i<LCD_W; i++){ // lcd.write(dispLv[i]); //     } // lcd.setCursor(0, 1); lcd.print("^"); // if ((start+1)<10) { // lcd.print((start+1)); // lcd.print(" "); //      } else if ((start+1)<100 && (start+1)>9) { // lcd.print((start+1)); // lcd.print(" "); // } else lcd.print((start+1)); // lcd.setCursor(5, 1); lcd.print("V:"); // if (lv[0]<10) { // lcd.print("00"); // lcd.print(lv[0]); //         } else if (lv[0]<100 && lv[0]>9) { // lcd.print("0"); // lcd.print(lv[0]); // } else lcd.print(lv[0]); // lcd.setCursor(11, 1); lcd.print("T:"); //      lcd.print(chRx); // } void ButtonPress() // ,    { if ((KeyButton1Value>200) and (KeyButton1Value<500)) { if((start) < (chRx-LCD_W) && chRx>LCD_W) start++; //     } if ((KeyButton1Value>500) and (KeyButton1Value<1000)) { if(start > 0) start--; //     } } void KeyBoardCalculate() { //    KeyButton1Value=analogRead(KEY_BUTTON_1_PIN); //          if ((KeyButton1Value<=50) or (KeyButton1Value>=1000)) { //       KeyButton1TimePress=millis(); KeyButton1WasChecked=0; KeyButton1RepeatTimePress=0; } KeyButton1TimeFromPress=millis()-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+100; } } }
      
      







そして奇妙なことに、うまくいきました! 列は、受信したデータに従って「ジャンプ」しました。 この時までに、40x2ディスプレイが到着しました。 私はそれを接続し、40文字のディスプレイ用にスケッチを再編集し、アップロードしましたが、説明できないことが起こりました。



最初に表示されたフレームでマイクロコントローラーを起動した時点で、すべての情報が正しく、後続のフレームが表示されると、arduinoはどこかでいくつかのチャネルを使い果たします。 つまり コントローラーが60チャネルでデータを提供する場合、arduinoのスイッチオンまたはリブート時に、60チャネルの総数が表示され、ディスプレイの最初のチャネルが実際に最初になります。 しかし、フレームの変更直後には、フレーム数が57表示され、最初のフレームが表示され、実際には5番目が表示されます。 また、信号を30のチャネルに送り込もうとしました-同じこと、最初はすべてが正しく、次にチャネルの総数29が表示されますが、最初のチャネルの代わりに何が完全に不明なのか。



他のすべては問題なく動作します-スクロールスクロール。 たぶん誰かが新鮮な目で見るでしょう...はい、ちなみに、<17チャンネルに信号を送ると、すべてが正しく表示されます。



私はこの問題について一週間考えましたが、それでも解決策を見つけることができませんでした。 最終的に、私は最初の16文字のディスプレイにとどまることにしました。 彼はケースを洗い流し、組み立て、今日まですべてが機能しています。



All Articles