Hello Arduino forum,
Working to get an Adafruit Neopixel Ring 24
to run from the SEEED Studio XAIO SAMD21
microcontroller.
(We tried using the ATtiny85 but the 8MHZ
speed was too slow for the Neopixel's
data transfer.)
Using a switch and a PIR to control the
operation of Neopixel.
The designed operation
has three modes:
-
When the switch is closed the Neopixel
runs until the switch is opened. -
When the switch is open the the Neopixel
runs for an interval (ten seconds used for testing,
production usage will be 60 seconds) when the PIR is
triggered. -
When the switch is open and the PIR is
not triggered or the PIR is triggered
and the interval has elapsed the Neopixel
is dark.
LED3 is an indicator light and should
oscillate at 1 hertz whenever power
is applied.
This the schematic used to build a
breadboard as prelim to ordering
a PCB.
The code on the XAIO is a sketch
developed in the Arduino IDE
copied herewith below.
Test 1. Power on with the SW1 closed.
Neopixel runs rainbow function as expected.
LED2 stays on constant, does not oscillate.
After 15 seconds Neopixel lit but not
in rainbow function.
After 15 seconds LED3 blinks at
1 second interval, as designed.
Test 2. Power on with the SW1 open.
Neopixel runs a rainbow functions for 15 seconds.
LED3 dark for 15 seconds.
After 15 seconds LED3 dark for 15 seconds.
After 30 seconds Neopixel dark.
After 30 seconds LED3 blinks at
1 second interval.
Test 3. Complete Test 1 and open SW1.
Run Test 1 for 20 secs, that is,
after 20 seconds the
Neopixel lit, not moving.
and
LED3 blinking at 1 second intervals.
Action: Open SW1.
Neopixel runs rainbow function.
LED3 on constant.
After 15 seconds Neopixel dark.
After 15 seconds blinking at 1 second intervals.
Retriggering SW1 results in repeatable
operation:
Neopixel runs rainbow function.
LED2 on constant.
After 15 seconds Neopixel dark.
After 15 seconds blinking at 1 second intervals.
Test 4. Test 3 complete and system retriggering
Action: Close switch
Neopixel runs rainbow function as expected.
LED3 stays on constant, does not oscillate.
After 15 seconds Neopixel lit but not
in rainbow function.
After 15 seconds LED3 blinks at
1 second interval, as designed.
The Neopixel operates pretty much as designed
except with SW1 closed the NeoPixel stays lit but
stops moving after 15 seconds.
What is more baffling is LED3. It was surmised
that the LED3 would oscillate without regard
to the NeoPixel, the switch or the PIR.
But, as shown in all the tests, LED3 is
affected by events that are caused by
constructs contained in the runNeoPixel()
function. LED3 only operates as expected when
the NeoPixel is dark.
How to isolate the runNeoPixel() function
from the runLED3()?
Why does the NeoPixel stop moving after
15 seconds when SW1 is closed?
Thanks.
Allen Pitts
****** Neopixel Rainbow XAIO 240513 sketch******
// Rainbow_240130.ino is based on.
// strandTest_240116_rainbow.ino
// Rainvow_240130.ino removes the trinket code
// and the void theaterChaseRainbow(int wait) at the end
// to focus solely on the Rainbow effect using the NeoPixel Ring 24.
#include <Adafruit_NeoPixel.h>
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 24
// Which pin on the Arduino is connected to the NeoPixels?
#define LED_PIN 4
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// constants won't change. Used here to set a pin number :
const int ledPin3 = A3; // the number of the LED pin
const int neoPixelPin = A4; // Which pin on the Arduino is connected to the NeoPixels?
const int PIN_PIR_SENSOR_INPUT = A7; //the number of the PIR PIN **********************
const int switchPin = A5;
// Variables will change :
int ledState3 = LOW;
int neoPixelState = LOW; // A variable to track whether the Neopixel is currently showing color (ON) or not showing color (OFF)
int pirState = LOW; //State of the PIR input to the Attiny
bool pirWasTriggered = false; // A bool variable (True/False) to track whether the PIR went HIGH and the Attiny registered that the PIR went HIGH
bool switchIsClosed = false;
unsigned long previousMillis3 = 0; // will store last time LED was updated
unsigned long previousMillis4 = 0;
const long interval3 = 1000;
const long interval4 = 10000; // interval LED4 stays on after a trigger from PIR
// setup() function -- runs once at startup --------------------------------
void setup() {
// set the pin as output:
pinMode(neoPixelPin, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(PIN_PIR_SENSOR_INPUT, INPUT); //Define the pin input from the PIR sensor to the Attiny and INPUT *********************
pinMode(switchPin, INPUT); //240430 pinMode(switchPin, INPUT_PULLUP);
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}
void loop() {
//runLED3 will perform the toggling ON/OFF of LED3 and the timing
runLED3();
//Every loop this logic will be evaluated
//If the PIR wasn't triggered recently (A HIGH hasn't been read), then check the PIR for HIGH/LOW
if(pirWasTriggered == false){
pirState = digitalRead(PIN_PIR_SENSOR_INPUT); //Read whether the input from the PIR sensor is LOW or HIGH and set that value to pirState ****************
if(pirState == HIGH){ //If the input is HIGH, record that it was triggered
pirWasTriggered = true;
}
}
//runNeoPixel will perform the toggling ON/OFF of NEOPIXEL and the timing
runNeoPixel();
}
void runLED3() {
unsigned long currentMillis3 = millis();
if (currentMillis3 - previousMillis3 >= interval3) {
// save the last time you blinked the LED
previousMillis3 = currentMillis3;
// if the LED is off turn it on and vice-versa:
if (ledState3 == LOW) {
ledState3 = HIGH;
} else {
ledState3 = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin3, ledState3);
}
}
void runNeoPixel(){
//Read the logic level of the Switch (HIGH/LOW), The Switch will read HIGH when OPEN and LOW when closed
/*
There are 4 Combinations and their states:
1.) currentSwitchValue == LOW and switchIsClosed == false -> Switch is now CLOSED after having been OPEN
2.) currentSwitchValue == LOW and switchIsClosed == true -> Switch is still CLOSED after having already been CLOSED
3.) currentSwitchValue == HIGH and switchIsClosed == true -> Switch is now OPEN after having been CLOSED
4.) currentSwitchValue == HIGH and switchIsClosed == false -> Switch is still OPEN after having already been OPEN
*/
bool currentSwitchValue = digitalRead(switchPin); //Read the current value of the Switch Pin (HIGH/LOW)
//This is combination 1 from the above list
if( currentSwitchValue == LOW && switchIsClosed == false){ //If the Switch is CLOSED (LOW) and the switchIsClosed variable was set to False before, set switchIsClosed to True and turn ON LED4
switchIsClosed = true;
rainbow(10); // Set the neopixel to Green
pirWasTriggered = false; //Set this false in case the PIR was triggered and then the Switch is CLOSED.
//Setting pirWasTriggered to false prevents the light turning back on from the interval4 timer after the Siwtch is OPEN again
return; //exit the runLED4 function for this round of the loop
}
//This is combination 3 from the above list
if( currentSwitchValue == HIGH && switchIsClosed == true){ //If the Switch is now OPEN (HIGH) and the switchIsClosed variable was set to True before,
//set switchIsClosed to False and turn OFF the neopixel ring
switchIsClosed = false;
//neopixel_off(); //Turn off the neopixel display by showing Black
colorWipe(strip.Color(0,0,0)); // Set the neopixel to Black/Off
pirWasTriggered = false; //Set this false in case the PIR was triggered and then the Switch is CLOSED.
//Setting pirWasTriggered to false prevents the light turning back on from the interval4 timer after the Siwtch is OPEN again
return; //exit the runLED4 function for this round of the loop
}
//This is combination 2 from the above list
if(switchIsClosed == true){
return; //exit the function because LED4 is already ON and the PIR signal does not need to be read because LED4 is on because the Switch is CLOSED
}
//Combination 4 is the default state of the Switch being OPEN and we will proceed to the PIR logic below for this condition
//If PIR wasn't triggered (didn't go HIGH), exit out of this function altogether with the 'return' command since nothing else needs to be done on LED4
if(pirWasTriggered == false){
return;
}
//It is here that the Neopixel is turned on when the PIR is triggered
if(neoPixelState == LOW){ //Check if the neopixel state is currently LOW, set it HIGH and turn on the LED.
//This prevents taking time and resources to digitalWrite ledPin4 HIGH every loop when it is already HIGh
previousMillis4 = millis(); //set the time of previousMillis4
neoPixelState = HIGH;
rainbow(10); // Set the neopixel to Blue
}
//This timer is now tracking how long until LED4 is turned OFF
unsigned long currentMillis4 = millis();
if (currentMillis4 - previousMillis4 >= interval4) { //Once interval4 amount of time has passed since the LED4 was turned ON, it will enter this IF statement
//set the LED to OFF
neoPixelState = LOW;
//neopixel_off(); //Turn off the neopixel display by showing Black
colorWipe(strip.Color(0,0,0)); // Set the neopixel to Black/Off
pirWasTriggered = false;
}
}
// What does this do?
void colorWipe(uint32_t color) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
}
}
void neopixel_off(){
strip.clear(); //Set all color values of the Neopixels to Black
strip.show(); //Update and display the Black color (effectively this means the LEDs are OFF)
}
// 3. Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
// Hue of first pixel runs 5 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
// means we'll make 5*65536/256 = 1280 passes through this loop:
for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
// strip.rainbow() can take a single argument (first pixel hue) or
// optionally a few extras: number of rainbow repetitions (default 1),
// saturation and value (brightness) (both 0-255, similar to the
// ColorHSV() function, default 255), and a true/false flag for whether
// to apply gamma correction to provide 'truer' colors (default true).
strip.rainbow(firstPixelHue);
// Above line is equivalent to:
// strip.rainbow(firstPixelHue, 1, 255, 255, true);
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
3 posts - 3 participants