概要
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スロットが送信される。最初のスロットは「開始コード」であり、後に続くデータの種類を知らせるものである。照明や調光器向けの開始コードはゼロである。』となっている。
プログラムのポイント解説
Arduinoのシリアル転送を使って、基本的には、速度は250000bps、データが8ビットでストップビットは2ビットに設定すると動く。しかし、1ビット当たり4μ秒のデータに対し、88μ秒という長いLowのBreak信号と8µ秒というHighの "Mark After Break" (MAB)はシリアルではタイミング的に作りにくい。そこで、デジタルに設定したピンからLowの信号とHighの信号を出力した後で、そのピンをシリアルに設定しなおして、必要なデータを送り、データ転送が終わったら、シリアル通信を終了することでDMX信号を作成できた。
ハードウェア(シールド)
DMX512を使うためには電気的にEIA-485に合わす必要があり、そのためにLT1785,SN75176,LTC485等のRS485トランシーバICをArduinoに接続する必要があります。
引用した回路図
引用元( https://playground.arduino.cc/DMX/DMXShield )
作成したシールド
100均で買ったプラスチックの箱に、USBとキャノンの穴をあけました。Arduino Unoがぴったり入ります。LTC485はキャノンコネクタに直接ハンダ付して空中配線しています。
DmxSimpleライブラリーのプログラムからの移植
DmxSimpleライブラリ内のスケッチであるFadeUpDownを基に、DmxSimleライブラリを使わずに,同じ動作をするプログラムを移植していきます。
まずは、オリジナルのDmxSimpleライブラリ内にあるFadeUpDownです。
1行目でDmxSimleライブラリを読み込み、4行目で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ライブラリを使わずに、DMXの定義に従って動くようにした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( );
}