x、y、z軸(0、2、4ピン)のanalogRead Valueを取得し、モーション状態であれば、Adafruit Neopixelライブラリを使って虹、サイロン、カスケードLEDシーケンスを実行したいと思っています。
シリアル接続で、x,y,z軸は約300の値で読み込まれていることが確認できました。
コードを実行すると、3つのNeopixelシーケンス(3番ピンのredPin、5番ピンのGreenPin、6番ピンのBluePin)を実行し、加速度センサーの位置に変化がない場合でも、継続されます。
何が間違っているのでしょうか? 私はArduino Trinket Pro 5Vを使用しており、x軸とRGBストリップを3ピンのみで動作させて開始しています。
よろしくお願いします。
#include <Adafruit_NeoPixel.h>
#include "WS2812_Definitions.h"
#define PIN1 3
#define LED_COUNT1 5
#define PIN2 5
#define LED_COUNT2 5
#define PIN3 6
#define LED_COUNT3 5
// Create an instance of the Adafruit_NeoPixel class called "leds".
// That'll be what we refer to from here on...
Adafruit_NeoPixel RedPin = Adafruit_NeoPixel(LED_COUNT1, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel GreenPin = Adafruit_NeoPixel(LED_COUNT2, PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel BluePin = Adafruit_NeoPixel(LED_COUNT3, PIN3, NEO_GRB + NEO_KHZ800);
const int sensorPinRed = A0;
const int sensorPinGreen = A2;
const int sensorPinBlue = A4;
int analogValue = 0;
void setup()
{
RedPin.begin(); // Call this to start up the LED strip.
//GreenPin.begin();
//BluePin.begin();
clearLEDs(); // This function, defined below, turns all LEDs off...
RedPin.show(); // ...but the LEDs don't actually update until you call this.
//GreenPin.show();
//BluePin.show()}
void loop()
{
do{
analogValue = analogRead(sensorPinRed);
// Ride the Rainbow Road
for (int i=0; i<LED_COUNT1*10; i++)
{
rainbow(i);
delay(100); // Delay between rainbow slides
}
// Indigo cylon
// Do a cylon (larson scanner) cycle 10 times
for (int i=0; i<10; i++)
{
// cylon function: first param is color, second is time (in ms) between cycles
cylon(INDIGO, 500); // Indigo cylon eye!
}
// A light shower of spring green rain
// This will run the cascade from top->bottom 20 times
for (int i=0; i<20; i++)
{
// First parameter is the color, second is direction, third is ms between falls
cascade(MEDIUMSPRINGGREEN, TOP_DOWN, 100);
}
} while (analogValue>300);
}
// Implements a little larson "cylon" sanner.
// This'll run one full cycle, down one way and back the other
void cylon(unsigned long color, byte wait)
{
// weight determines how much lighter the outer "eye" colors are
const byte weight = 4;
// It'll be easier to decrement each of these colors individually
// so we'll split them out of the 24-bit color value
byte red = (color & 0xFF0000) >> 16;
byte green = (color & 0x00FF00) >> 8;
byte blue = (color & 0x0000FF);
// Start at closest LED, and move to the outside
for (int i=0; i<=LED_COUNT1-1; i++)
{
clearLEDs();
RedPin.setPixelColor(i, red, green, blue); // Set the bright middle eye
// Now set two eyes to each side to get progressively dimmer
for (int j=1; j<3; j++)
{
if (i-j >= 0)
RedPin.setPixelColor(i-j, red/(weight*j), green/(weight*j), blue/(weight*j));
if (i-j <= LED_COUNT1)
RedPin.setPixelColor(i+j, red/(weight*j), green/(weight*j), blue/(weight*j));
}
RedPin.show(); // Turn the LEDs on
delay(wait); // Delay for visibility
}
// Now we go back to where we came. Do the same thing.
for (int i=LED_COUNT1-2; i>=1; i--)
{
clearLEDs();
RedPin.setPixelColor(i, red, green, blue);
for (int j=1; j<3; j++)
{
if (i-j >= 0)
RedPin.setPixelColor(i-j, red/(weight*j), green/(weight*j), blue/(weight*j));
if (i-j <= LED_COUNT1)
RedPin.setPixelColor(i+j, red/(weight*j), green/(weight*j), blue/(weight*j));
}
RedPin.show();
delay(wait);
}
}
// Cascades a single direction. One time.
void cascade(unsigned long color, byte direction, byte wait)
{
if (direction == TOP_DOWN)
{
for (int i=0; i<LED_COUNT1; i++)
{
clearLEDs(); // Turn off all LEDs
RedPin.setPixelColor(i, color); // Set just this one
RedPin.show();
delay(wait);
}
}
else
{
for (int i=LED_COUNT1-1; i>=0; i--)
{
clearLEDs();
RedPin.setPixelColor(i, color);
RedPin.show();
delay(wait);
}
}
}
// Sets all LEDs to off, but DOES NOT update the display;
// call leds.show() to actually turn them off after this.
void clearLEDs()
{
for (int i=0; i<LED_COUNT1; i++)
{
RedPin.setPixelColor(i, 0);
}
}
// Prints a rainbow on the ENTIRE LED strip.
// The rainbow begins at a specified position.
// ROY G BIV!
void rainbow(byte startPosition)
{
// Need to scale our rainbow. We want a variety of colors, even if there
// are just 10 or so pixels.
int rainbowScale = 192 / LED_COUNT1;
// Next we setup each pixel with the right color
for (int i=0; i<LED_COUNT1; i++)
{
// There are 192 total colors we can get out of the rainbowOrder function.
// It'll return a color between red->orange->green->...->violet for 0-191.
RedPin.setPixelColor(i, rainbowOrder((rainbowScale * (i + startPosition)) % 192));
}
// Finally, actually turn the LEDs on:
RedPin.show();
}
常にLEDに何かを表示するようにコーディングしているように見えますが。
void loop()
{
do {
analogValue = analogRead(sensorPinRed);
// display stuff
} while (analogValue > 300);
}
AnalogValue` が <= 300 のときに LED を消したいのだと仮定すると、テストの場所が間違っています。これでは必ず最低一回はループしてしまいます。どうでしょう。
void loop()
{
analogValue = analogRead(sensorPinRed);
if (analogValue > 300)
{
// display stuff
}
else
{
clearLEDs(); // Turn all LEDs off...
RedPin.show();
BluePin.show();
GreenPin.show();
}
}
私のコードをデバッグしてくれた @nick-gammon に感謝します。
以下は動作サンプルです。加速度センサーのX軸はRGB LEDストリップのPWMピン3、Y軸はピン5、Z軸はピン6と関連しています。
LEDのシーケンスは、方向の傾きに応じて春の緑色で一回カスケードします。
#include <Adafruit_NeoPixel.h>
#include "WS2812_Definitions.h"
#define PIN1 3
#define LED_COUNT1 5
#define PIN2 5
#define LED_COUNT2 5
#define PIN3 6
#define LED_COUNT3 5
// Create an instance of the Adafruit_NeoPixel class called "XPin", "YPin" and "ZPin".
// That'll be what we refer to from here on...
Adafruit_NeoPixel XPin = Adafruit_NeoPixel(LED_COUNT1, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel YPin = Adafruit_NeoPixel(LED_COUNT2, PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel ZPin = Adafruit_NeoPixel(LED_COUNT3, PIN3, NEO_GRB + NEO_KHZ800);
const int sensorPinX = A0;
const int sensorPinY = A2;
const int sensorPinZ = A4;
int analogValueX = 0;
int analogValueY = 0;
int analogValueZ = 0;
void setup()
{
XPin.begin(); // Call this to start up the LED strip.
YPin.begin();
ZPin.begin();
clearLEDs(); // This function, defined below, turns all LEDs off...
}
void loop()
{
analogValueX = analogRead(sensorPinX);
analogValueY = analogRead(sensorPinY);
analogValueZ = analogRead(sensorPinZ);
if ((analogValueX > 400) || (analogValueY > 400) || (analogValueZ > 400) )
{
// A light shower of spring green rain
// This will run the cascade from top->bottom i times
for (int i=0; i<1; i++)
{
// First parameter is the color, second is direction, third is ms between falls
cascade(MEDIUMSPRINGGREEN, TOP_DOWN, 100);
}
}
else
{
clearLEDs(); // Turn all LEDs off
}
}
// Cascades a single direction. One time.
void cascade(unsigned long color, byte direction, byte wait)
{
if (direction == TOP_DOWN)
{
for (int i=0; i<LED_COUNT1; i++)
{
clearLEDs(); // Turn off all LEDs
XPin.setPixelColor(i, color); // Set just this one
XPin.show();
delay(wait);
}
for (int i=0; i<LED_COUNT2; i++)
{
clearLEDs(); // Turn off all LEDs
YPin.setPixelColor(i, color); // Set just this one
YPin.show();
delay(wait);
}
for (int i=0; i<LED_COUNT3; i++)
{
clearLEDs(); // Turn off all LEDs
ZPin.setPixelColor(i, color); // Set just this one
ZPin.show();
delay(wait);
}
}
else
{
for (int i=LED_COUNT1-1; i>=0; i--)
{
clearLEDs();
XPin.setPixelColor(i, color);
XPin.show();
delay(wait);
}
for (int i=LED_COUNT2-1; i>=0; i--)
{
clearLEDs();
YPin.setPixelColor(i, color);
YPin.show();
delay(wait);
}
for (int i=LED_COUNT3-1; i>=0; i--)
{
clearLEDs();
ZPin.setPixelColor(i, color);
ZPin.show();
delay(wait);
}
}
}
// Sets all LEDs to off, but DOES NOT update the display;
// call leds.show() to actually turn them off after this.
void clearLEDs()
{
for (int i=0; i<LED_COUNT1; i++)
{
XPin.setPixelColor(i, 0);
}
for (int i=0; i<LED_COUNT2; i++)
{
YPin.setPixelColor(i, 0);
}
for (int i=0; i<LED_COUNT3; i++)
{
ZPin.setPixelColor(i, 0);
}
}