照明ネットワーク

照明のネットワークに関する記事を書きます。照明の通信を行うのに使えるツールなども作成していく予定です。

【実験部屋】M5StackでArt-Netをブロードキャスト出力する【M5Stack】


f:id:aisakakun:20200209141647p:plain

目的

M5Stackを使用しArt-NetのDMXパケット「ArtDMX」をWi-Fiで送信させること。

要求仕様

・メニュー画面の操作で「ブロードキャスト」「ユニキャスト」の選択をすることができる。
・メニュー画面の遷移を行うことができる。
・Art-Net出力(ArtDMX)の送信・停止を行うことができる。

結果

f:id:aisakakun:20200209141729p:plain

準備物

・通信確認用のPC(M5Stackが2つある場合は、前回作成のプログラム使用し、ユニバースを合わせれば受信可能です。)
・M5Stack Basic development kit

通信確認用PC

wiresharkが入っていれば、起動させることで準備完了です。その際PCの設定をIPアドレスサブネットマスクをArt-Net規格に従った設定とすることを忘れないようにしてください。

M5Stack側(ソースコード)

ソースコードについてですが、要求仕様にも記載しましたように、メニュー選択も付け加えました。コードとしては、下記のような構成になっています。それぞれ機能毎にファイルを分けておりますので、必要に応じてコード削減など行えば、自由に使用することができますのでご活用ください。

コード名 役割
ArtNetSend_Broad_Uni.ino mainコード
connectWifi.cpp Wifi接続用のコード
firstMenuOpration.cpp 最初のメニュー:ブロードキャスト・ユニキャスト選択を行う画面
secondMenuOperation.cpp 二つ目のメニュー:ブロードキャスト・ユニキャスト選択に応じた送信内容画面の表示を行う画面
thirdMenuOperation.cpp 三つ目のメニュー:Art-Net(ArtDMX)出力を行うことができる画面。ボタン押下により、送信・停止が可能
ArtNetSend_Broad_Uni.ino : mainコード

mainコードです。各メニューに遷移する中心のコードになっています。

#include <M5Stack.h>

int menuPhase = 0;
int firstMenuSelectNum = 0;
int secondMenuSelectNum = 0;
//int thirdMenuSelectNum = 0;
int artnetSendFlag = 0;

void FirstMenu(void);
int SelectButton(int firstMenuSelectNum);
void SecondMenu(int firstMenuSelectNum);
int SecondSelectButton(int secondMenuSelectNum);
int ThirdMenu(int firstMenuSelectNum,int artnetSendFlag);
void ThirdSelectButton(void);

void setup() {
  // put your setup code here, to run once:
  M5.begin();
  M5.Lcd.setTextSize(3);
  firstMenuSelectNum = 0;
  secondMenuSelectNum = 0;
//  thirdMenuSelectNum = 0;
  FirstMenu();
}

void loop() {
  // put your main code here, to run repeatedly:
  //ボタン情報をアップデート
  M5.update(); 
  ///メニュー切り替え
  //メニュ-画面:0(FirstMenu)でボタンCが押された時、メニュー画面:1(Second Menu)へ遷移
  if(menuPhase == 0 && M5.BtnC.wasPressed()){
    M5.Lcd.clear();
    menuPhase = 1;
  //メニュ-画面:1(SecondMenu)でボタンCが押された時、メニュー画面:2(Third Menu)へ遷移
  }else if(menuPhase == 1 && M5.BtnC.wasPressed()){
    M5.Lcd.clear();
    //Sendが選択されたらメニュー画面:2へ、modoruが選択されたらメニュー画面:0へ
    if(secondMenuSelectNum == 1){
         menuPhase = 2; 
    }else{
         menuPhase = 0;
    }
  //メニュ-画面:2(ThirdMenu)でボタンCが押された時、メニュー画面:1(Second Menu)へ遷移
  }else if(menuPhase == 2 && M5.BtnB.wasPressed()){
    M5.Lcd.clear();
    artnetSendFlag = 0;
    menuPhase = 1;
  }else{
    //
  }
  //メニューごとの機能表示
  switch(menuPhase){
    case 0:
      FirstMenu();
      firstMenuSelectNum = SelectButton(firstMenuSelectNum);
      break;
    case 1:
      SecondMenu(firstMenuSelectNum);
      secondMenuSelectNum = SecondSelectButton(secondMenuSelectNum);
      break;
    case 2:
      artnetSendFlag = ThirdMenu(firstMenuSelectNum,artnetSendFlag);
      ThirdSelectButton();
      break;
    default:
      break;
  }
}
connectWifi.cpp : Wifi接続用のコード

Wi-Fi接続を行う用のコードです。M5StackのIP、ゲートウェイサブネットマスクを設定し、Wi-Fiに接続します。

#include <WiFi.h>
#include <M5Stack.h>

boolean ConnectWifi(const char* ssid,const char* password){
  //my IP setting
  IPAddress ip(2,21,1,1); //for fixed IP Address
  IPAddress gateway(2,21,1,254);
  IPAddress subnet(255,0,0,0);
  
  boolean state = true;
  int i = 0;
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    M5.Lcd.print(".");
    if (i > 20){
      state = false;
      break;
    }
    i++;
  }
  if (state){
    M5.Lcd.println("");
    M5.Lcd.print("Connected to ");
    M5.Lcd.println(ssid);
    M5.Lcd.print("IP address: ");
    M5.Lcd.println(WiFi.localIP());
  } else {
    M5.Lcd.println("");
    M5.Lcd.println("Connection failed.");
  }
  return state;
}
firstMenuOpration.cpp:最初のメニュー:ブロードキャスト・ユニキャスト選択を行う画面

f:id:aisakakun:20200209132413p:plain
最初のメニュー

#include <M5Stack.h>

void FirstMenu(){
  M5.Lcd.setTextColor(0xFFFF);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setCursor(40,80);
  M5.Lcd.print("Broadcast");
  M5.Lcd.setCursor(40,160);
  M5.Lcd.print("Unicast");
}

int SelectButton(int firstMenuSelectNum){
  if( firstMenuSelectNum == 0 && M5.BtnA.wasPressed()){//一行目が選択されている状態なら
      M5.Lcd.clear();
      M5.Lcd.fillTriangle(10,160,10,170,20,165,RED);
      firstMenuSelectNum = 1;
  }else if(firstMenuSelectNum == 1 && M5.BtnA.wasPressed()){//二行目が選択されている状態なら
      M5.Lcd.clear();
      M5.Lcd.fillTriangle(10,80,10,90,20,85,RED);
      firstMenuSelectNum = 0;
  }else{
  }
  return firstMenuSelectNum;
}
secondMenuOperation.cpp:二つ目のメニュー:ブロードキャスト・ユニキャスト選択に応じた送信内容画面の表示を行う画面

f:id:aisakakun:20200209133020p:plain
二つ目のメニュー

#include <M5Stack.h>

void SecondMenu(int firstMenuSelectNum){
  M5.Lcd.setTextColor(0xFFFF);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(40,180);
  M5.Lcd.print("Send");
  M5.Lcd.setCursor(160,180); 
  M5.Lcd.print("modoru");
  if(firstMenuSelectNum == 0){
    M5.Lcd.setCursor(40,40);
    M5.Lcd.println("dst:IP Address:");
    M5.Lcd.setCursor(120,60);
    M5.Lcd.println("2.255.255.255");
    M5.Lcd.setCursor(40,120);
    M5.Lcd.print("Universe:");
    M5.Lcd.setCursor(120,140);
    M5.Lcd.println("127:15:15");
  }else if(firstMenuSelectNum == 1){
    M5.Lcd.setCursor(40,40);
    M5.Lcd.println("dst:IP Address:");
    M5.Lcd.setCursor(120,60);
    M5.Lcd.println("2.21.21.2");
    M5.Lcd.setCursor(40,120);
    M5.Lcd.print("Universe:");
    M5.Lcd.setCursor(120,140);
    M5.Lcd.println("127:15:13");
  }
}

int SecondSelectButton(int secondMenuSelectNum){
  if( secondMenuSelectNum == 0 && M5.BtnA.wasPressed()){//一行目が選択されている状態なら
      M5.Lcd.clear();
      M5.Lcd.fillTriangle(10,180,10,190,20,185,RED);
      secondMenuSelectNum = 1;
  }else if(secondMenuSelectNum == 1 && M5.BtnA.wasPressed()){//二行目が選択されている状態なら
      M5.Lcd.clear();
      M5.Lcd.fillTriangle(130,180,130,190,140,185,RED);
      secondMenuSelectNum = 0;
  }else{
  }
  return secondMenuSelectNum;
}
thirdMenuOperation.cpp:三つ目のメニュー:Art-Net(ArtDMX)出力を行うことができる画面。ボタン押下により、送信・停止が可能

f:id:aisakakun:20200209133506p:plain
三つ目のメニュー

#include <M5Stack.h>
#include <ArtnetWifi.h>

// Artnet settings
ArtnetWifi artnet;
const int startUniverse = 32767; // CHANGE FOR YOUR SETUP most software this is 1, some software send out artnet first universe as 0.
const char broadcastHost[] = "2.255.255.255"; // CHANGE FOR YOUR SETUP your destination
const char unicastHost[] = "2.21.21.1"; // CHANGE FOR YOUR SETUP your destination
const char* ssid = "ssid"; // CHANGE FOR YOUR SETUP
const char* password = "password"; // CHANGE FOR YOUR SETUP

boolean ConnectWifi(const char* ssid,const char* password);

int ThirdMenu(int firstMenuSelectNum, int artnetSendFlag){
  if(artnetSendFlag == 0){
    ConnectWifi(ssid,password);
    if(firstMenuSelectNum == 0){
      artnet.begin(broadcastHost);
    }else if(firstMenuSelectNum == 1){
      artnet.begin(unicastHost);
    }else{
      //
    }
    artnet.setLength(3);
    artnet.setUniverse(startUniverse);
    M5.Lcd.setCursor(0, 50);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setTextColor(GREEN);
    M5.Lcd.print("Please push the C button");
    delay(2000);
    artnetSendFlag = 1;
  }else{
    //
  }
  return artnetSendFlag = 1;
}

void drawLine(){
  int start_x = 0;
  int start_y = 100;
  int max_x = 320;
  int max_y = 240;
  M5.Lcd.fillRect(start_x,start_y,max_x - start_x, max_y - start_y,BLACK);
  for(int y = start_y; y < max_y ; y += 10){
    M5.Lcd.drawLine(start_x,start_y,max_x - 1,y,0x7BE0);
    delay(10);
  }
}

void ThirdSelectButton(){
  if(M5.BtnC.wasPressed()){//一行目が選択されている状態なら
    M5.Lcd.clear();
    M5.Lcd.setCursor(0, 50);
    M5.Lcd.setTextColor(RED);
    M5.Lcd.print("Art-Net Sending..");
    // set the first 3 byte to all the same value. A RGB lamp will show a ramp-up white.
    for (uint8_t j = 0; j < 255; j++) {
      for (uint8_t i = 0; i < 3; i++) {
        artnet.setByte(i, j);
      }  
      artnet.write();
    }
    drawLine();
  }else if(M5.BtnA.wasPressed()){//二行目が選択されている状態なら
    M5.Lcd.clear();
    M5.Lcd.setCursor(0, 50);
    M5.Lcd.setTextColor(0xB7E0);
    M5.Lcd.print("Art-Net Stopped");
    
  }else{
    //
  }
}
現状と今後の変更予定内容:

【現状】Art-Net出力の送信はボタンCを押下してから一定時間で停止します。
【変更予定内容】ボタンによる割り込み処理を加え、ボタンAの押下により強制停止できるように変更加えていきます。
【現状】Unicastで送信するIPアドレスは固定のIPアドレスです。
【変更予定内容】IPアドレスも変更できるように変更加えていきます。
【現状】ユニバースは32767の固定ユニバースです。
【変更予定内容】ユニバースを可変とするように変更加えていきます。

まとめ

M5Stackで画面遷移・ArtDMX出力を行う物を作りました。簡単な受信確認などに使用可能と思いますのでこの内容を改良して使用してみてください。

参照サイト:
固定IPアドレスの設定:
qazsedcftf.blogspot.com
参照本:

みんなのM5Stack入門

みんなのM5Stack入門

使用したM5Stackはこちら。