当初、AVRマイコンでCで書いてNeoPixelを制御するか??と考えていたけど、使っていないArduino Nanoがあったので、これを使ってNeoPixelを制御することにした。下が俺ArduinoNano(自作)
幸い、Adafruitが提供しているNeoPixel用ライブラリがあるので、これを使うと、簡単に制御できる。実際に動かしてみると、非常に安定している。すばらしい。NeoPixelは発色がウリなので動画も撮ってしまった。。テストした結果が以下。
youtu.be
Arduinoのテストプログラムは以下
#include <Adafruit_NeoPixel.h> #define PIN 6 #define NUMPIXELS 24 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); uint32_t tmpl_color= pixels.Color(0, 0, 0); void setup() { pixels.begin(); Serial.begin(9600); } void loop() { int i,j; uint32_t color; Serial.print("circle"); color = pixels.Color(0,0,20); circle(color); color = pixels.Color(0,10,10); circle(color); color = pixels.Color(0,20,0); circle(color); color = pixels.Color(10,10,0); circle(color); color = pixels.Color(20,0,0); circle(color); color = pixels.Color(10,0,10); circle(color); } void circle(uint32_t color){ int i,n; for(i=0; i<3; i++){ for(n=0; n<NUMPIXELS; n++){ pixels.setPixelColor(n,color); pixels.show(); delay(4); pixels.clear(); pixels.show(); delay(4); } } }
これまで誤動作していたのは、3.3Vでだましながら制御していたせいか、あるいは、タイミングの精度が悪くて、LEDを正しく制御できなかったのいずれかと思う。
Arduinoで制御できる目途が立ったけど、、RaspberryPiとArduinoを接続する必要がある。Arduino NanoにはUSB-Serial変換ICが載っているので、ラズパイとArduinoをUSBで接続できるはずだ。。多分。ラズパイ側にドライバいるかもしれないけど。
多少modprobeとかしてしまったのではっきりわからないけど、多分ドライバを追加しなくてもFT232Hはつながると思う。ただ、パーミッションを正しく設定する必要があり、rootでいきなり/dev/ttyUSB0とやるとエラーになる。
$ sudo su - # cu -l /dev/ttyUSB0 cu: open (/dev/ttyUSB0): Permission denied cu: /dev/ttyUSB0: Line in use
以下のようなコマンドで、dialoutグループに自分自身を追加する
$ sudo usermod -a -G dialout $USER
dialoutグループに自分が足されているのを確認する (UID:piのまま使っていたら問題なく使えたかも)
自分の名前が太郎冠者(tarokaja)とした場合の例
$ grep dialout /etc/group dialout:x:20:pi,tarokaja
cuコマンドで接続できたことを確認
RaspberryPiからArduino Nanoと通信するのはUSB-Serialを介して行うが、RaspberryPi側はPySerialを使おう。
pyserialモジュールをインストールすると以下で操作できるらしい
import serial ser = serial.Serial('/dev/ttyUSB0',9600, timeout=None) line = ser.readline() print(line) ser.close()
Arduino側はNeoPixelを制御しながら、シリアルで'circle'と出力している。
[RaspberryPi Zero]---usb---[Arduino]-----[NeoPixel]
ラズパイ側のSerial受信サンプル
import serial import time ser = serial.Serial('/dev/ttyUSB0',9600, timeout=None) while True: str = ser.read_all() print(str) time.sleep(1)
実行結果(Arduinoから送られてくる)
b'circlecirclecirclecirclecirclecirclecirclecirclecircle' b'' b'' b'' b'circle' b'' b'' b'' b'circle'
次は、、Arduino側のNeoPixel制御ソフトにSirial入力ルーチンを追加して、要求があったらLED点灯パターンを変えるようにする。そうすれば、、「Alexa。。。LEDをON」と発話すると、NeoPixelがグルグル回るはず。。
■追記
シリアルで制御できるNeoPixel Contorllerを試作
#include <Adafruit_NeoPixel.h> #define PIN 6 #define NUMPIXELS 24 #define OFF 0 #define ON 1 #define RED 2 #define BLUE 3 #define GREEN 4 #define CIRCLE 5 #define CMD_NONE -1 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); int current_state; void led_fill(uint32_t color); void setup() { pixels.begin(); Serial.begin(9600); Serial.print("====================\n"); Serial.print("Neo Pixel Controller\n"); Serial.print("====================\n"); Serial.print(">"); led_off(); current_state = OFF; } void loop() { int i,j,cmd; uint32_t color; String str; if (Serial.available() > 0){ str = Serial.readStringUntil('\n'); Serial.print("---target---\n"); Serial.print(str); Serial.print("-------------\n"); }else{ str = ""; } if(str.indexOf("ON")> -1){ Serial.print("\n->ON!\n"); cmd = ON; }else if(str.indexOf("OFF")> -1){ Serial.print("\n->OFF!\n"); cmd = OFF; }else if(str.indexOf("RED")> -1){ Serial.print("\n->RED!\n"); cmd = RED; }else if(str.indexOf("BLUE")> -1){ Serial.print("\n->BLUE!\n"); cmd = BLUE; }else if(str.indexOf("GREEN")> -1){ Serial.print("\n->GREEN!\n"); cmd = GREEN; }else if(str.indexOf("CIRCLE")> -1){ Serial.print("\n->CIRCLE!\n"); cmd = CIRCLE; }else{ cmd = CMD_NONE; } if(cmd == CMD_NONE || current_state == cmd){ ; }else{ switch(cmd){ case ON: case RED: Serial.print("turn on RED"); color = pixels.Color(20,0,0); led_fill(color); current_state = RED; break; case OFF: Serial.print("SW OFF"); led_off(); current_state = OFF; break; case GREEN: Serial.print("switch to GREEN"); color = pixels.Color(0,20,0); led_fill(color); current_state = GREEN; break; case BLUE: Serial.print("switch to BLUE"); color = pixels.Color(0,0,20); led_fill(color); current_state = BLUE; break; case CIRCLE: current_state = CIRCLE; break; default: ; } } if(current_state == CIRCLE){ circle(); } if (cmd != CMD_NONE){ Serial.print("\n>"); } } void circle(){ uint32_t color; Serial.print("circle"); color = pixels.Color(0,0,20); circle3(color); color = pixels.Color(0,10,10); circle3(color); color = pixels.Color(0,20,0); circle3(color); color = pixels.Color(10,10,0); circle3(color); color = pixels.Color(20,0,0); circle3(color); color = pixels.Color(10,0,10); circle3(color); } void circle3(uint32_t color){ int i,n; for(i=0; i<3; i++){ for(n=0; n<NUMPIXELS; n++){ pixels.setPixelColor(n,color); pixels.show(); delay(4); pixels.clear(); pixels.show(); delay(4); } } } void led_fill(uint32_t color){ pixels.fill(color,0,NUMPIXELS); pixels.show(); } void led_off(void){ pixels.clear(); pixels.show(); }
USB-SerialからArduinoにコマンドを送るとNeoPixelが制御できる。使えるコマンドは、ON,RED,BLUE,GREEN,CIRCLE,OFF。これを、USB接続したラスパイから叩くと。。
以下の操作でNeoPixelが赤色で点灯する
import serial ser = serial.Serial('/dev/ttyUSB0',9600, timeout=None) ser.write(b"RED\n")