当初、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")