概要

Arduinoを使って照明用のDMX512を制御します。
以前に、DmxSimpleを使ってプログラムを作成しました(https://qiita.com/Ina3/items/9af8e14d991e8b1791d4 )が、DMX512の仕様書を読んで、仕様書通りにプログラムを作成して、DmxSimpleを使わずに制御できるようになりました。

DMX512のプロトコル

ウィキペディア(https://ja.wikipedia.org/wiki/DMX512-A )の技術的解説の中から引用すると『DMX512のデータは EIA-485 の電気的仕様を使っている。DMXの仕様では、電気信号については EIA-485 を参照することになっている。データは250kbit/sでシリアルに伝送され、1度に連続転送されるのは最大513バイトのパケットである。1バイトを DMX512-A では「スロット」と呼ぶ。このプロトコルでは1ビットのスタートビットと2ビットのストップビットを使い、データはリトルエンディアンである。パケットの先頭には最低でも88μ秒のブレーク信号があり、それに最低でも8μ秒の "Mark After Break" (MAB) が続く(1986年の規格では4μ秒だったが1990年に拡張された)。ブレーク信号は受信側にデータが後に続くことを予告するものである。ブレーク信号の後に最大513スロットが送信される。最初のスロットは「開始コード」であり、後に続くデータの種類を知らせるものである。照明や調光器向けの開始コードはゼロである。』となっている。

プログラムのポイント解説

文章ではわかりにくにので、図であらわすと、次のようになる。
DMXframe.jpg

Arduinoのシリアル転送を使って、基本的には、速度は250000bps、8ビットでストップビットは2ビットに設定すると動く。しかし、88μ秒という長いLowのBreak信号と8µ秒というHighの "Mark After Break" (MAB)はシリアルではタイミング的に作りにくい。そこで、デジタルに設定したピンからLowの信号とHighの信号を出力した後で、そのピンをシリアルに設定しなおして、必要なデータを送り、データ転送が終わったら、シリアル通信を終了することで実現できた。

ハードウェア(シールド)

DMX512を使うためには電気的にEIA-485に合わす必要があり、そのためにLT1785,SN75176,LTC485等のRS485トランシーバICをArduinoに接続する必要があります。
引用した回路図
fig04.jpg

引用元( https://playground.arduino.cc/DMX/DMXShield )
作成したシールド
100均で買ったプラスチックの箱に、USBとキャノンの穴をあけました。Arduino Unoがぴったり入ります。LTC485はキャノンコネクタに直接ハンダ付して空中配線しています。
fig11.jpg

DmxSimpleライブラリーのプログラムの移植

DmxSimple内のスケッチであるFadeUpDownをDmxSimleを使わずに,
同じ動作をするプログラムを紹介します。

まずは、オリジナルのDmxSimple内のFadeUpDownです。DMXの出力はPin1です。

#include <DmxSimple.h>
int brightness = 0;
void setup() {
 DmxSimple.usePin(1);
 DmxSimle.maxChannnel(4);
}
void loop() {
  for (brightness = 0; brightness <= 255; brightness++) {
    DmxSimple.write(1, brightness);
    delay(15);
  }
  for (brightness = 0; brightness <= 255; brightness++) {
    DmxSimple.write(1,255- brightness);
    delay(15);
  }
 delay(400); 
}

以下は、DmxSimpleライブラリを使わずに動くようにしたFadeUpDownです。DMXの出力はPin1です。

int brightness = 0;
int Tx = 1;//DMXoutputPin
void setup() {
}
void loop() {
    for (brightness = 0; brightness <= 255; brightness++) {
       writeDMX( brightness);
       delay(15);
      }

    for (brightness = 0; brightness <= 255; brightness++) {
       writeDMX(255- brightness);
       delay(15);
      }    
      delay(400);
}

void writeDMX(int x){
      pinMode(Tx,OUTPUT);
        digitalWrite(Tx,0);//Break as LOW
        delayMicroseconds(88);
        digitalWrite(Tx,1);//MAB as HIGH
        delayMicroseconds(8);
        Serial.begin(250000,SERIAL_8N2);
        Serial.write(0x0);//Start Code as 0
        Serial.write(x);//Ch1 Data
        Serial.end( );
 }

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.