5
3

More than 5 years have passed since last update.

ArduinoOSCとI2C通信でNeoPixels複数台制御

Last updated at Posted at 2019-02-16

実装

準備

ハードウェア
-Arduino Uno * 5台
https://www.switch-science.com/catalog/789/
-NeoPixels 1m * 4本, 2m * 4本 
https://www.switch-science.com/catalog/1399/
-細径3心並列線(必要な分だけ)
https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=4A8P-MDLY
-ACアダプター * 4本
https://www.amazon.co.jp/gp/product/B075132TRK/ref=ppx_yo_dt_b_asin_title_o00__o00_s01?ie=UTF8&psc=1

ソフトウェア
-Max8 (8.0.0)
-Arduino (1.8.8)
-ArduinoOsc (0.2.1)
-Adafruit NeoPixel (1.1.8)

プログラムの概要

1.ArduinoOSC
Max-MSPとArduino間でSerial通信を行い、Maxからの値をArduinoに受け渡します。ファイルの保存場所は注意が必要で、jsonやjsファイルも同じファイルに入れておく必要があります。
スクリーンショット 2019-02-17 0.37.13.png

2.I2C通信
master_writerとslave_receiverの関係のI2C通信を用いて、Arduino1台(master)の指令をArduino4台(slave)に渡します。
LAC_Brain_Orchestra.png
上記の黒、黄色、緑のワイヤーがI2C通信になります。masterにはパソコンから電源供給を行い、slave一つ一つは5V2AのACアダプターを接続します。

3.NeoPixels
led@4x.png

1台のArduinoから1mのNeoPixelsと2mのNeoPixelsの二つに指令を与えます。5V電力とGNDはそれぞれ1mのテープと2mのテープに分岐させ接続します。

プログラムの流れ

Max-MSP -> Serial通信 -> Arduino -> I2C通信 -> Arduino -> NeoPixels制御
Maxで受け取った数値をArduino(master) -> Arduino(slave)へ受け渡していくプログラムになっています。最終的には数値によってLEDの点灯パターンが変化します。それぞれのArduinoには前もってプログラムを書き込んでおき、ACアダプターから電源をもらって稼働させます。

プログラム

Max

MaxからSerial通信で"/light1 0"の形でArduinoにメッセージを送ります。たまに調子が悪い時があり、その時はserialオブジェクト(serial d 9600)のportのアルファベットを一度変更してから行うと良さそうです。
スクリーンショット 2019-02-16 22.56.07.png

Arduino(master)

Maxからラベル付けされて来る数値を各SlaveのArduinoへ送ります。
/light1 -> slave1(I2C通信のDevice_Id1)
/light2 -> slave2(I2C通信のDevice_Id2)
/light3 -> slave3(I2C通信のDevice_Id3)
/light4 -> slave4(I2C通信のDevice_Id4)

master.ino
#include <ArduinoOSC.h>
#include <Wire.h>

// Wire ID 
#define DEVICE_ID1 1
#define DEVICE_ID2 2
#define DEVICE_ID3 3
#define DEVICE_ID4 4

OscSerial osc;

void setup() {
  Serial.begin(9600);
  osc.attach(Serial);
  osc.subscribe("/light1", callbackLight1);
  osc.subscribe("/light2", callbackLight2);
  osc.subscribe("/light3", callbackLight3);
  osc.subscribe("/light4", callbackLight4);
  Wire.begin();
}

void loop() {
  osc.parse();
}

void callbackLight1(OscMessage& m){
  Wire.beginTransmission(DEVICE_ID1);
  Wire.write(m.getArgAsInt32(0));
  Wire.endTransmission();
}

void callbackLight2(OscMessage& m){
  Wire.beginTransmission(DEVICE_ID2);
  Wire.write(m.getArgAsInt32(0));
  Wire.endTransmission();
}

void callbackLight3(OscMessage& m){
  Wire.beginTransmission(DEVICE_ID3);
  Wire.write(m.getArgAsInt32(0));
  Wire.endTransmission();
}

void callbackLight4(OscMessage& m){
  Wire.beginTransmission(DEVICE_ID4);
  Wire.write(m.getArgAsInt32(0));
  Wire.endTransmission();
}

Arduino(slave)

masterから送られた値によってLEDの光るパターンを変更するプログラムです。1mと2mのLEDテープを9つのパターンで点灯させています。1mのLEDテープは6ピンで、2mのLEDテープは7ピンに接続をします。
slave2の場合はWire.begin(1)がWire.begin(2)になります。slave3、slave4も同じ要領で考えてください。

slave1.ino
#include <Adafruit_NeoPixel.h>
#include <Wire.h>

#ifdef __AVR__
#include <avr/power.h>
#endif

#define PIN1            6
#define PIN2            7

#define NUMPIXELS1      60
#define NUMPIXELS2      120


Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS1, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS2, PIN2, NEO_GRB + NEO_KHZ800);

int pattern = 0;
int delayval = 20;

void setup() {
  Wire.begin(1);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);

#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif

  pixels1.begin();
  pixels2.begin();
  pixels1.setBrightness(100);
  pixels2.setBrightness(100);
  pixels1.show();
  pixels2.show();
}

void receiveEvent(int howMany) {
  pattern = Wire.read();
  Serial.print(pattern);
}

void loop() {
  switch (pattern) {
    case 0:
    //No Light
      noLight(pixels1.Color(0, 0, 0), pixels2.Color(0, 0, 0), delayval);
      break;
    case 1:
    //dualStraight
      straight(pixels1.Color(255, 255, 255), pixels2.Color(255, 255, 255), delayval);
      break;
    case 2:
    //Short Straight, Long No Light
      straight(pixels1.Color(255, 255, 255), pixels2.Color(0, 0, 0), delayval);
      break;
    case 3:
    //Short No Light, Long Straight
      straight(pixels1.Color(0, 0, 0), pixels2.Color(255, 255, 255), delayval);      
      break;
    case 4:
    //dualReverse
      reverse(pixels1.Color(255, 255, 255), pixels2.Color(255, 255, 255), delayval);
      break;
    case 5:
    //Short Reverse, Long No Light
      reverse(pixels1.Color(255, 255, 255), pixels2.Color(0, 0, 0), delayval);
      break;
    case 6:
    //Short No Light, Long Reverse
      reverse(pixels1.Color(0, 0, 0), pixels2.Color(255, 255, 255), delayval);
      break;
      case 7:
      //Short Straight, Long Reverse
      sSt_lRe(pixels1.Color(255, 255, 255), pixels2.Color(255, 255, 255), delayval);
      break;
      case 8:
      //Short Reverse, Long Straight
      sRe_lSt(pixels1.Color(255, 255, 255), pixels2.Color(255, 255, 255), delayval);
    default:
      break;
  }
}

void straight(const uint32_t& c1, const uint32_t& c2, uint8_t wait) {
  for (int j = 0; j < 10; j++) {
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i + q, c1);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i + q, c2);
      }
      pixels1.show();
      pixels2.show();

      delay(wait);

      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i + q, 0);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i + q, 0);
      }
    }
  }
}

void reverse(const uint32_t& c1, const uint32_t& c2, const uint8_t& wait) {
  for (int j = 0; j < 10; j++) {
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i - q, c1);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i - q, c2);
      }
      pixels1.show();
      pixels2.show();

      delay(wait);

      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i - q, 0);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i - q, 0);
      }
    }
  }
}

void sSt_lRe(const uint32_t& c1, const uint32_t& c2, const uint8_t& wait) {
  for (int j = 0; j < 10; j++) {
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i + q, c1);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i - q, c2);
      }
      pixels1.show();
      pixels2.show();

      delay(wait);

      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i + q, 0);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i - q, 0);
      }
    }
  }
}

void sRe_lSt(const uint32_t& c1, const uint32_t& c2, const uint8_t& wait) {
  for (int j = 0; j < 10; j++) {
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i - q, c1);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i + q, c2);
      }
      pixels1.show();
      pixels2.show();

      delay(wait);

      for (uint16_t i = 0; i < pixels1.numPixels(); i = i + 3) {
        pixels1.setPixelColor(i - q, 0);
      }
      for (uint16_t i = 0; i < pixels2.numPixels(); i = i + 3) {
        pixels2.setPixelColor(i + q, 0);
      }
    }
  }
}

void noLight(const uint32_t& c1, const uint32_t& c2, const uint8_t& wait) {
  for (uint16_t i = 0; i < pixels1.numPixels(); i = ++i) {
    pixels1.setPixelColor(i, 0);
  }
  for (uint16_t i = 0; i < pixels2.numPixels(); i = ++i) {
    pixels2.setPixelColor(i, 0);
  }
  pixels1.show();
  pixels2.show();

  delay(wait);
}

参考文献

ArduinoOSCの説明についてはこちらを参考にしました。(本家)
-https://qiita.com/hideakitai/items/f50f99e38b520a0ace37
Qiitaの記事からのアップデートもありましたので、下記のGithubもチェックしてください。
-https://github.com/hideakitai/ArduinoOSC

Node.jsのインストール方法等(brewインストール済みの場合)
-https://qiita.com/jaxx2104/items/2277cec77850f2d83c7a

I2Cの説明についてはこちらの方を参考にしました。
- https://qiita.com/MergeCells/items/20c3c1a0adfb222a19cd
- https://qiita.com/hikoalpha/items/7bf563ee286a59bfd2f4

NeoPixelsの購入方法や説明についてはこちらに記載されています。
-https://www.switch-science.com/catalog/1399/

おわりに

質問やアドバイスがありましたら、ぜひコメントをください。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3