Hello PB Community,
TLDR… skip to the second paragraph.
I’m currently working on a sunrise alarm clock to get myself some experience with PB before the holiday lighting season. Initially I was using my raspberry Pi and the neopixel library to drive the two 8x32 LED panels I’ll be using for the light-up portion of the alarm function. The animations I created worked fine during initial testing running all the python scripts direct from the terminal. I developed a web interface for scheduling the alarms and was able to use it to kick off animations on the LED panel, the problem I ran into was I was not able to stop an animation once it begins executing. Rather than continuing to try to recreate the wheel and create my own API, I did some research and invested in a PB. So far this has worked great and resolved my initial issues. I use my web interface and Pi to make API calls to the PB to start up animations, most importantly, I can also stop them (turn off the alarm). At this point you are probably wondering what the issue is, mainly I think I bit off a bit more than I could chew with my first animation, but I’d like to get this project knocked out so I can move onto experimenting/learning with PB on some strip lights for the holidays.
So onto the nuts and bolts of why we are here. I caught the Tasks postings Scruffynerf had been posting for a while and stumbled on the sunrise animations. I ended up poaching one of them for my own purposes, however I need to make some tweaks to step through the animation over a set interval of time. This animation will act as the wake-up light, with each frame of the animation, the panel will get a bit brighter, eventually pausing on the last frame of the animation. I want this timer to be configurable so the user can choose the period the animation unfolds over. For example, let’s say there are 10 frames, at T0, you would see Frame 1. When Tn<T<Tn+30, where n is a value between 1-30 in minutes selected by the user, you would see frame 10. When T>Tn+30 the panel would turn back off. So far I’ve been able to change how fast the animation plays but haven’t been able to do it in at any sort of predictable rate. I’ve definitely not figured out how to make the animation pause on the last frame. Anyone willing to help a newb with a timed animation?
Side note, thanks to @jeff for the original animation I used as the basis of my code. I’ll paste my most recent (non-working) edits for reference.
var hueSun = .10, hueEdges = 0.01
var sharpness = 3, spread = .8
var location = 0.5 // the centre of the sunrise
export var t1 // main time cycling variable, from 0 to 1
var sunRadius = 0.5
var rimToWhite = 0.01
var interval
var step = 0
export function inputNumberWakeTimer(WakeTime){
interval = (clamp(WakeTime,1,30) * 60000)/96 //96 is a WAG for the number of frames
return interval
}
// over-simplified, given that the HSV colorspace almost allows for a reasonable sunset color gradient. Ideally, this would be a proper gradient calculation
// this will be fed a value from 0 to 0.5. at 0, it should return hueSun ,and at 0.5 (or more, error correction), it should return hueEdges
function sunsetGradient(distFromSun) {
var returnHue = hueSun
if (distFromSun <=0) returnHue = hueSun
else if (distFromSun >=0.4) returnHue = hueEdges
else {
// safely have a value of cDist between 0 and 0.4. calculate slope of higher-lower/horizontal, plus lower, to give line between higher and lower, over the given horizontal distance.
returnHue = ((hueEdges-hueSun)/0.4)*distFromSun + hueSun
}
return returnHue
}
// Only here for the v2
function hypot(a, b) { return sqrt(a * a + b * b) }
//https://www.gizma.com/easing/
function easeOutQuad(t, b, c, d) {
t /= d
return -c * t * (t-2) + b
}
// time loops every 65.54*interval seconds, and interval 0.015 = 1 second apprx.
export function beforeRender(delta) {
step += delta
if (step > interval){
t0 = clamp(1.5 * time(.2) - .25, 0, 1)
t1 = easeOutQuad(t0, 0, 1, 1)
sunRadius = .3 + t0 / 3
}
}
export function render2D(index, x, y) {
x -= .5; y = 4 - y - t1
var cDist = hypot(x, y - 2 * t1)
var distFromSun = clamp((cDist-sunRadius)/2,0, 1)
var sat, hue
var va = spread * pow((1/spread)-cDist, sharpness) + t1
va = clamp(va, 0, .5) //clamp the value
// calculate white (desaturated) centre of sun
sat = (cDist<(sunRadius-rimToWhite)) ?.5/(sunRadius-rimToWhite)*cDist + .5 : 1
// calculate gradient,as a functin of the distance from the sun centre.
hue = sunsetGradient(distFromSun)
hsv(hue, sqrt(sat), va * va * va)
}
export function render3D(index, x, y, z) {
render2D(index,x,y)
}
export function render(index) {
render2D(index, .5, index / pixelCount)
}