You can definitely do this, the secret is not to use delays in your code because they block everything.
What you want is timers, which use the millis function. Or alternatively use a library like TimedAction which handles this for you, basically saying “run this code every X milliseconds”. That way your power cell and Cyclotron can run at entirely different intervals.
Here’s an example Arduino sketch which uses two strips of RGB Neopixels (addressable LEDs), one for the Cyclotron and one for the Power Cell:
#include <Adafruit_NeoPixel.h>
#define CYCLOTRON_PIN 7
#define PCELL_PIN 6
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel cyclotron = Adafruit_NeoPixel(4, CYCLOTRON_PIN, NEO_RGB + NEO_KHZ800);
Adafruit_NeoPixel powercell = Adafruit_NeoPixel(15, PCELL_PIN, NEO_GRB + NEO_KHZ800);
uint16_t cyclotronDelay = 500;
uint16_t currentCyclotron = 3;
unsigned long previousCyclotronMillis=0;
uint16_t powercellDelay = 70;
uint16_t currentPowercell = 0;
unsigned long previousPowercellMillis=0;
uint32_t red = cyclotron.Color(255,0,0);
uint32_t blue = cyclotron.Color(41, 187, 234);
void setup() {
cyclotron.setBrightness(255); // set brightness
powercell.setBrightness(255); // set brightness
cyclotron.begin();
cyclotron.show(); // Initialize all pixels to 'off'
powercell.begin();
powercell.show(); // Initialize all pixels to 'off'
}
void loop() {
tickCyclotron();
tickPowercell();
}
void tickCyclotron() {
if (
((unsigned long)(millis() - previousCyclotronMillis) >= cyclotronDelay)
|| previousCyclotronMillis == 0
) {
previousCyclotronMillis = millis();
cyclotron.clear();
cyclotron.setPixelColor(currentCyclotron, red);
if (currentCyclotron < (cyclotron.numPixels() -1)) {
currentCyclotron++;
} else {
currentCyclotron = 0;
}
cyclotron.show();
}
}
void tickPowercell() {
if ((unsigned long)(millis() - previousPowercellMillis) >= powercellDelay) {
previousPowercellMillis = millis();
powercell.clear();
for(uint16_t i=0; i<powercell.numPixels(); i++) {
if (i <= currentPowercell) {
powercell.setPixelColor(i, blue);
}
}
currentPowercell++;
if (currentPowercell >= powercell.numPixels()) {
currentPowercell = 0;
}
powercell.show();
}
}
This uses millis().
You could simplify this significantly by using TimedAction GitHub - Glumgad/TimedAction: A fork of Alexander Brevig's TimedAction library for Arduino https://playground.arduino.cc/Code/TimedAction · GitHub
Edit: Here’s how that would look:
#include <Adafruit_NeoPixel.h>
#include "TimedAction.h"
#define CYCLOTRON_PIN 7
#define PCELL_PIN 6
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel cyclotron = Adafruit_NeoPixel(4, CYCLOTRON_PIN, NEO_RGB + NEO_KHZ800);
Adafruit_NeoPixel powercell = Adafruit_NeoPixel(15, PCELL_PIN, NEO_GRB + NEO_KHZ800);
uint16_t cyclotronDelay = 500;
uint16_t currentCyclotron = 3;
uint16_t powercellDelay = 70;
uint16_t currentPowercell = 0;
uint32_t red = cyclotron.Color(255,0,0);
uint32_t blue = cyclotron.Color(41, 187, 234);
void tickCyclotron() {
cyclotron.clear();
cyclotron.setPixelColor(currentCyclotron, red);
if (currentCyclotron < (cyclotron.numPixels() -1)) {
currentCyclotron++;
} else {
currentCyclotron = 0;
}
cyclotron.show();
}
void tickPowercell() {
powercell.clear();
for(uint16_t i=0; i<powercell.numPixels(); i++) {
if (i <= currentPowercell) {
powercell.setPixelColor(i, blue);
}
}
currentPowercell++;
if (currentPowercell >= powercell.numPixels()) {
currentPowercell = 0;
}
powercell.show();
}
TimedAction cyclotronTimer = TimedAction(cyclotronDelay, tickCyclotron);
TimedAction powercellTimer = TimedAction(powercellDelay, tickPowercell);
void setup() {
cyclotron.setBrightness(255); // set brightness
powercell.setBrightness(255); // set brightness
cyclotron.begin();
cyclotron.show(); // Initialize all pixels to 'off'
powercell.begin();
powercell.show(); // Initialize all pixels to 'off'
}
void loop() {
cyclotronTimer.check();
powercellTimer.check();
}