What started out as an just excuse to tinker with the ESP32 turned into

fastled-showtell
gplus
(Dave Plummer) #1

What started out as an just excuse to tinker with the ESP32 turned into a more extensive project. Since the ESP32 support wasn’t great before I had been using custom code on the RMT channel to drive the LEDs, but now have moved back to FastLED which makes my life a lot simpler! This video was made before the port to FastLED, so it lacks fades and a few effects I’ve added since. Most of these came from Tweaking4All, some are original.

I’m now making the web UI and REST API for interfacing with the box.
https://www.youtube.com/watch?v=3gwKMuuCgJI

(Marc Miller) #2

The bouncing balls are always fun! I like your spin on them. Flame is great looking too.

(Dave Plummer) #3

Thanks! Since going back to FastLED I’ve added palette based effects like puffy clouds, rainbow stripe animations, and so on. The fire is still my favorite. Wish I knew who wrote the original, it’s clever.

(Kyle bostick) #4

any chance you want to share your code? those are some awesome effects! I am finishing up a holiday light show I put on the outside of my house, and I would love to add some of your effects to it.

(Dave Plummer) #5

It’ll take me some time to package the whole controller up but I’m happy to share some of the effect code. Any few in particular?

(Kyle bostick) #6

I really liked the fire effect, the bouncing balls are cool too!

(Dave Plummer) #7

The bouncing balls are pretty self contained, so here’s an example. It relies on a base class you won’t have to set pixels and so on but it should be easy to reuse.

(Dave Plummer) #8

//+------------------------------------------------------------------------
//
// ESP32LEDStrip - © 2018 Dave Plummer. All Rights Reserved. See license.txt.
//
// File: BouncingBallsEffect.h
//
// Description:
//
// Displays N bouncing colored balls, optiponally from both sides.
//
// Origin: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects
// No license årequirements listed
//
// History: Aug-1-2018 Davepl Adapted
//
//-------------------------------------------------------------------------

#pragma once

#if !defined(max)
#define max(a,b) (a > b ? a : b)
#endif

class BouncingBallsEffect : public LEDStripEffect
{
protected:

virtual const char * FriendlyName() const
{
	return "Bouncing Balls";
}

void BouncingColoredBalls(int BallCount, bool bStaggered) 
{
	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];
	CRGB  Color[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);  

		// The first up to N balls have their initial colors set, the rest are random.  When they
		// get kicked for lack of velocity, their color will be randomized as well either way.

		if (i == 0)
			Color[i] = CRGB::Red;
		else if (i == 1)
			Color[i] = CRGB::Green;
		else if (i == 2)
			Color[i] = CRGB::Blue;
		else if (i == 3)
			Color[i] = CRGB::Violet;
		else
			Color[i] = RandomRainbowColor();
	}

	while (true) 
	{
		for (int i = 0; i < BallCount; i++) 
		{
			TimeSinceLastBounce[i] = (millis() - ClockTimeSinceLastBounce[i]) / 6;
			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)			// Ball is almost motionless, so kick it hard
				{
					ImpactVelocity[i] = ImpactVelocityStart;
					Color[i] = RandomRainbowColor();
				}
			}
			Position[i] = round(Height[i] * (_cLEDs - 1) / StartHeight);
		}

		for (int i = 0; i < BallCount; i++) 
		{
			int x = (bStaggered && (i % 2 == 1)) ? Position[i] : (_cLEDs - Position[i]);

			setPixel(x,
				Color[i].r,
				Color[i].g,
				Color[i].b);
			/*
			setPixel(x + 1,
				max(128, Color[i].r),			// This works becaue it's a fully saturated color in one of r/g/b
				max(128, Color[i].g),
				max(128, Color[i].b));
			setPixel(x + 2,
				Color[i].r,
				Color[i].g,
				Color[i].b);
			*/
		}
		if (gStopEffect)
			return;
		delay(5);
		showStrip();
		setAll(0, 0, 0);
	}
}
virtual void Draw(float fSecondsElapsed, byte baseHue)
{
	BouncingColoredBalls(3, false);
}

};

class DoubleBouncingBallsEffect : public BouncingBallsEffect
{
virtual const char * FriendlyName() const
{
return “Double Balls”;
}

virtual void Draw(float fSecondsElapsed, byte baseHue)
{
	BouncingColoredBalls(6, true);
}

};

(Marc Miller) #9

@Dave_Plummer Please post code to http://gist.github.com and share a link to it here so G+ doesn’t accidently mangle it, it can be viewed correctly on all devices, and line numbers can be referenced for discussion.
http://gist.github.com