include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 30
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.show();
}
void loop() {
uint32_t colors[] = {strip.Color(255, 0, 0), strip.Color(0, 255, 0), strip.Color(0, 0, 255)}; // Red, Green, Blue
BouncingBalls(colors, 3);
}
void BouncingBalls(uint32_t ballColors[], int BallCount) {
float Gravity = -9.81;
int StartHeight = 1;
float Height[BallCount];
float ImpactVelocityStart = sqrt(-2 * Gravity * StartHeight);
float ImpactVelocity[BallCount];
float TimeSinceLastBounce[BallCount];
int Position[BallCount];
long ClockTimeSinceLastBounce[BallCount];
float Dampening[BallCount];
for (int i = 0; i < BallCount; i++) {
ClockTimeSinceLastBounce[i] = millis();
Height[i] = StartHeight;
Position[i] = 0;
ImpactVelocity[i] = ImpactVelocityStart;
TimeSinceLastBounce[i] = 0;
Dampening[i] = 0.90 - float(i) / pow(BallCount, 2);
}
while (true) {
for (int i = 0; i < BallCount; i++) {
TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i];
Height[i] = 0.5 * Gravity * pow(TimeSinceLastBounce[i] / 1000, 2.0) + ImpactVelocity[i] * TimeSinceLastBounce[i] / 1000;
if (Height[i] < 0) {
Height[i] = 0;
ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
ClockTimeSinceLastBounce[i] = millis();
if (ImpactVelocity[i] < 0.01) {
ImpactVelocity[i] = ImpactVelocityStart;
}
}
Position[i] = round(Height[i] * (NUM_LEDS - 1) / StartHeight);
}
for (int i = 0; i < BallCount; i++) {
setPixel(Position[i], ballColors[i]);
}
showStrip();
setAll(0, 0, 0);
}
}
void showStrip() {
strip.show();
}
void setPixel(int Pixel, uint32_t color) {
strip.setPixelColor(Pixel, color);
}
void setAll(byte red, byte green, byte blue) {
for (int i = 0; i < NUM_LEDS; i++) {
setPixel(i, strip.Color(red, green, blue));
}
showStrip();
}
//This is the First code
#include <Adafruit_NeoPixel.h>
#define PIN 6 // Define the pin for the LED strip
#define NUM_LEDS 30 // Define the number of LEDs in your strip
#define BRIGHTNESS 70 // Set the brightness (0-255)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.setBrightness(BRIGHTNESS);
strip.show();
}
void loop() {
fireEffect(55, 120);
delay(50); // Adjust the delay for the desired fire effect speed
}
void fireEffect(int cooling, int sparking) {
static byte heat[NUM_LEDS];
int cooldown;
// Step 1: Cool down every cell a little
for (int i = 0; i < NUM_LEDS; i++) {
cooldown = random(0, ((cooling * 10) / NUM_LEDS) + 2);
if (cooldown > heat[i]) {
heat[i] = 0;
} else {
heat[i] = heat[i] - cooldown;
}
}
// Step 2: Heat from each cell drifts 'up' and diffuses a little
for (int k = NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
}
// Step 3: Sparking
if (random(255) < sparking) {
int y = random(7);
heat[y] = heat[y] + random(160, 255);
}
// Step 4: Set the LEDs based on the heat (using only red color)
for (int j = 0; j < NUM_LEDS; j++) {
strip.setPixelColor(j, strip.Color(heat[j], 0, 0));
}
strip.show();
}
//this is the second code
//can anyone help me in combining both
Hello @shyamauno - You did a good job posting a sketch/code. The two sketches you want have a lot in common...
- both use Adafruit_NeoPixel library. Good.
- both have the number of LEDs as 30. Good.
- both have the data output pin as 6. Good.
- both create the instance/object "strip" with the same parameters. Good.
- BRIGHTNESS is different - "fire" defines this as 70, the other has no value. Easy to fix.
void setup()is nearly identical, except for using the BRIGHTNESS definition. Easy to fix.
The problem happens when the function calls (fireEffect and BouncingBalls) are placed inside the same void loop() function. One runs, then the next. If BouncingBalls is first, it goes through its part of the sketch without letting Fire do its function. That is called a "blocking" function. And, if Fire goes first, it takes one step to light one section of the Neopixels, then lets anything else do what it needs to do (called Non-Blocking)... but then BB does its blocking thing and blocks Fire... then when Fire gets to play again, it only does one step before letting BB go again.
You would have to make BouncingBalls only do ONE step, just like Fire, then let Fire do one step, and then both can share time lighting up the pixels they need.
Here is your combined code with Fire going first:
Here is your combined code with BB going first:
Just taking the "blocking" code away from BouncingBalls lets FireEffect over-write BB.
#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 30
#define BRIGHTNESS 255
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(115200);
strip.begin();
strip.setBrightness(BRIGHTNESS);
strip.show();
}
void loop() {
uint32_t colors[] = {strip.Color(255, 0, 0), strip.Color(0, 255, 0), strip.Color(0, 0, 255)}; // Red, Green, Blue
BouncingBalls(colors, 3);
// Serial.println("after BouncingBalls, running fireEffect");
fireEffect(55, 120);
// Serial.println("after fireEffect, running BouncingBalls");
}
void BouncingBalls(uint32_t ballColors[], int BallCount) {
float Gravity = -9.81;
int StartHeight = 1;
float Height[BallCount];
float ImpactVelocityStart = sqrt(-2 * Gravity * StartHeight);
float ImpactVelocity[BallCount];
float TimeSinceLastBounce[BallCount];
int Position[BallCount];
long ClockTimeSinceLastBounce[BallCount];
float Dampening[BallCount];
for (int i = 0; i < BallCount; i++) {
ClockTimeSinceLastBounce[i] = millis();
Height[i] = StartHeight;
Position[i] = 0;
ImpactVelocity[i] = ImpactVelocityStart;
TimeSinceLastBounce[i] = 0;
Dampening[i] = 0.90 - float(i) / pow(BallCount, 2);
}
// while (true) {
for (int i = 0; i < BallCount; i++) {
TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i];
Height[i] = 0.5 * Gravity * pow(TimeSinceLastBounce[i] / 1000, 2.0) + ImpactVelocity[i] * TimeSinceLastBounce[i] / 1000;
if (Height[i] < 0) {
Height[i] = 0;
ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
ClockTimeSinceLastBounce[i] = millis();
if (ImpactVelocity[i] < 0.01) {
ImpactVelocity[i] = ImpactVelocityStart;
}
}
Position[i] = round(Height[i] * (NUM_LEDS - 1) / StartHeight);
}
for (int i = 0; i < BallCount; i++) {
setPixel(Position[i], ballColors[i]);
}
showStrip();
setAll(0, 0, 0);
// }
}
void showStrip() {
strip.show();
}
void setPixel(int Pixel, uint32_t color) {
strip.setPixelColor(Pixel, color);
}
void setAll(byte red, byte green, byte blue) {
for (int i = 0; i < NUM_LEDS; i++) {
setPixel(i, strip.Color(red, green, blue));
}
showStrip();
}
void fireEffect(int cooling, int sparking) {
static byte heat[NUM_LEDS];
int cooldown;
// Step 1: Cool down every cell a little
for (int i = 0; i < NUM_LEDS; i++) {
cooldown = random(0, ((cooling * 10) / NUM_LEDS) + 2);
if (cooldown > heat[i]) {
heat[i] = 0;
} else {
heat[i] = heat[i] - cooldown;
}
}
// Step 2: Heat from each cell drifts 'up' and diffuses a little
for (int k = NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
}
// Step 3: Sparking
if (random(255) < sparking) {
int y = random(7);
heat[y] = heat[y] + random(160, 255);
}
// Step 4: Set the LEDs based on the heat (using only red color)
for (int j = 0; j < NUM_LEDS; j++) {
strip.setPixelColor(j, strip.Color(heat[j], 0, 0));
}
strip.show();
}
But this code is also not working
Yes, it IS working. It is just a bad idea to "combine" codes. You (you, not me) would need to change "fire" to finish its routine before passing the semaphore to "bounce."
Yes, I also dont want to combine both. But want to run the effects one after another