PIC16F1938でDMX送信に挑戦

この記事では、
DMX512の簡易送信機を作成したので、
その回路図やコードを解説しています。

はじめに

DMXとは…

DMX512とは、照明操作卓と照明器具や調光器間をつなぐ
信号方式のことで、主に照明の業界で使用されています。
照明卓などの操作器1つに対して複数個の照明器具を
数珠つなぎに器具をつないで行き、
使用するケーブルはツイスト1ペアとGNDの
合計3本だけで、
512chも制御することが可能です。

差動通信であるRS485を応用した通信方式であるため、
200mぐらいの長距離まで通信させることができ、
ノイズにも強いです。

DMX512の信号は、
1bit = 4μsが決められています。
さらに、DMX信号は次のような構成となっています。

  1. Break (>88μs)
  2. MAB (>8μs)
  3. Start code
  4. 1ch – 512ch data code

今回はこの信号をテスト的に作っていきます。

今回の回路図

前回のPIC16F1938でRS485通信(送信・受信)をやってみる
使用したものをそのまま流用しています。
ただし、RA1にLEDを繋げていますが、
今回は光らせてはいません。

このADM1485の6, 7番ピンがDMXのデータ-とデータ+となります。

また前回のPIC16F1938でRS485通信(送信・受信)をやってみるでは、
上記の物を2つ用意しましたが、
今回はオシロスコープとDMXテスターを使用するので、
1つだけとしました。

接続方法ですが、
一般的にはDMXは、XLRコネクタの3pin や 5pinを使用します。
いずれの場合もピンアサインは以下の通りです。

1 : GND
2 : Data-
3 : Data+
4 : NC
5 : NC
※NC = No Connect

XLRコネクタ以外にもLANコネクタであるRJ45を使う場合や、
単純にネジ式や差込み式の端子台を使用することもあります。

今回も前回同様、LANケーブルを使用し、
RS485トランシーバのData-, Data+を
DMX受信器のData-, Data+にそれぞれ接続し、
GNDは別途LANを使用せずに接続しました。

詳しくはLTC1485のデータシート等にも記載されているので、
配線の方法はこちらもご参考にしてください。

また、今回は完全に送信機として使用するため、
DEと/REをショートさせて、
RA2でhighとしています。

実際のコード

初期設定

ピンの初期設定やUSARTの初期設定は
前回とほぼ同じ内容です。

c

void Pin_Init(void) {
    ANSELA = 0x00;           //デジタルにセット
    ANSELB = 0x00;           //デジタルにセット

    TRISAbits.TRISA2 = 0;    //RA2を送信にセット
    LATAbits.LATA2 = 1;      //RA2をhigh(受信モード)

    TRISCbits.TRISC6 = 1;    //USART使用時はRC6はUSARTに制御される
    TRISCbits.TRISC7 = 1;    //RC7(RX)を受信にセット

}

void USART_Init(void) {
    TXSTAbits.SYNC = 0;       //EUSARTモード選択 0:非同期  1:同期
    TXSTAbits.BRGH = 1;       //高baudレート選択 1:非同期高速モード
    BAUDCONbits.BRG16 = 1;    //0:8ビットbaudレート 1:16ビットbaudレート

    SPBRG = 7;                //baudレートを250,000
    SPBRGH = 0;
    
    RCSTAbits.SPEN = 1;       //シリアルポート有効
    TXSTAbits.TXEN = 1;       //送信イネーブル
}

Baudレートの計算式です。
DMXは1bit = 4μsという決まりがあります。
そのため、Baudレートは4μsの逆数を取って

4μs=0.000004s4\mu s = 0.000 004s
10.000004=250,000bps\frac{1}{0.000004}\\=\\250,000\\bps

Baudレートは250,000となります。
今回もFocsは8MHzです。それらを

SPBRG=Fosc4×Baudrate1 SPBRG = \frac{F_{osc}}{4 \times Baudrate}-1\\

に代入して

SPBRG=8000000÷(4×250000)1=7SPBRG\\=\\8000000\\÷\\(4 × 250000)\\-\\1\\=7

となります。

長いBreakとそのあとのMAB

DMX512の信号の特徴は、
通常のRS485と異なる点がいくつかあります。
はじめにでも少し触れましたが、
その大きな違いの一つが
データ送信前の88μs以上という
長いBreakや8μs以上のMAB(MARK After Break)です。

これをUSARTでその88μsの間中ずっと
LOWという出力が出来ません。
250bps = 4μsで、0x00を出力した場合は
16bitのLOW = 64μs の Low となりますが、
そのあと必ず1bit又は2bit分の Stop bit として
Highが入ってしまいます。

そのため、 このBreakとMABの出力の時は、
USART出力をOFFにして、
これらの出力が終わってから
USART出力をONにして、
データを送るという方法を今回は考えました。
コードは次の通りです。

c

void dmx_send_break_mab(void)
{
    TXSTAbits.TXEN = 0;       //USARTのトランスミッタをOFF
    TRISCbits.TRISC6 = 0;     //RC6を出力
    LATCbits.LATC6 = 0;       //RC6の出力をlow
    __delay_us(100);          //100μs待つ
    
    LATCbits.LATC6 = 1;       //RC6の出力をhigh
    __delay_us(12);           //12μs待つ
    
    TXSTAbits.TXEN = 1;       //USARTのトランスミッタをON
    __delay_us(1);            //1μs待つ
}

これ以降はUSARTの出力となります。

データ送信

c

void dmx_send_byte(unsigned char data)
{
    while(!PIR1bits.TXIF);   //書き込み保留中でなくなるまで待つ
    TXREG = data;            //"data"を送信
}

データ送信はこれだけです。

DMX信号の送信

c

/********DMX信号に乗せるチャンネル数を設定*********/
#define DMX_CHANNELS 16     //16, 32, 64, 128, 256 を試した

unsigned char dmx_data[DMX_CHANNELS]
= {
  255, 125, 0, 255, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0
};

unsigned int dmx_length = sizeof(dmx_data) / sizeof(dmx_data[0]);


/*********DMXの1フレームの作成***********/
void dmx_send_frame(void)
{
    dmx_send_break_mab();       //上のBreakとMABの出力
    
    dmx_send_byte(0x00);        //スタートコードの送信
    

    for(unsigned char i = 0; i < dmx_length; i++){
        dmx_send_byte(dmx_data[i]);
    }
    
    while(!TXSTAbits.TRMT);     //送信完了まで待つ

/***************************************
1フレームの長さをそろえるためのdelay
    __delay_ms(5); 
***************************************/
}

以上で、DMX512信号の完成となります。

DMX512は必ずしも512chを送らなければならないわけではないため、
必要数だけ送ることも可能です。
今回は、16ch, 32ch, 64ch, 128ch, 256ch, 512chといろいろ試してみました。
その結果は実際の波形や、DMXテスターでの結果も示していきます

結果と考察


一番初めは、16chだけを送ってオシロスコープで波形の確認をしました。

Breakはdelayで100μsにセットしおり、
実際にオシロスコープで確認すると101.5μsでした。
左上の”Cursors”の中のΔXを見てください。

MABはdelayで12μsにセットしていましたが、
実際は23.5μsとなっていました。
想定の約2倍の長さとなっています。
おそらくこれはGPIOからUSARTに切り替えるのに
時間がかかっているのだと思います。

baudレートは今回250,000bps = 4μs/bit

1byte = start 1bit + data 8bit + stop 2bit = 11bit

11bit × 4μs = 44μs

オシロスコープでも44.2μsとなっているので、
計算通りの結果となりました。

DMXテスターで受信した結果の写真です。
PICに書き込んだ数値と全く同じ数値が表示されていることが分かります。
DMX送信成功です!!

defineで定義しているDMX_CHANNELSの数値を
16、32、64、128、256、512と2の累乗の値を試しましたが、
256と512はうまく送信できませんでした。

これは、今回使用しているPICのRAMが1Kであるためと
考えられます。
256や512は、単純に256byte、512byte使ってしまうため、
重すぎるのが原因であると考えられます。
256ではなく、255だとうまく動いてくれました。

また単純に

D+とD-を逆に接続

してしまって、
全く動かない…
なんてことも今回経験しました💦

次回予告

今回は、DMX512信号を送信することにチャレンジし、
成功しました。

次回は、DMX512の受信にチャレンジしたいと思います!!

コメント

タイトルとURLをコピーしました