Timecode Performance (aka Music Video Kit!) This new example sketch shows how to sequence

Timecode Performance (aka Music Video Kit!)
This new example sketch shows how to sequence a performance using timecode like HH,MM,SS.SSS. It’s specifically designed for synchronizing LED animations as part of a performance to other timed events, like music or video. Here’s part of what the relevant code inside looks like:

void Performance() {
FROM(0,0,00.100) { confetti(); }
FROM(0,0,03.375) { rainbowWithGlitter(); }
FROM(0,0,08.750) { confetti(); }
AT(0,0,11.000) { gHue = HUE_PINK; }
AT(0,0,12.000) { fill_solid(leds, NUM_LEDS, CRGB::Red); }
AT(0,0,15.000) { fill_solid(leds, NUM_LEDS, CRGB::Blue); }
FROM(0,0,16.500) { fadeToBlack(); }
FROM(0,0,18.000) { applause(); }
}

As you can see, there are two kinds of things you can specify: FROM and AT. Code inside FROM blocks is called repeatedly until the timecode for the next FROM block happens. AT blocks are called exactly once “at” the specified timecode.

As always, this is just a starting point: please feel free to dig in, tinker, tweak, modify, and play. (In fact, I recommend that. A lot.)

Special Thanks, again, to @Erin_St_Blaine for inspiration to turn this all around so that it looks like the sorts of timecode that performers are used to using!

Great stuff !

Looks like something I could use in the near future…

I see you do not make use of a Real Time Clock but the millis() function. I found problems with the accuracy of that function when building my clock and finally had to mount a RTC module. Can you provide any details as to the accuracy of this sketch running on Arduino Uno’s or Mega’s ?

I see cool show reels coming… :slight_smile:

So first of all, it’s trivial to change this code to use a different time base. There are only two calls to millis(), and both could be augmented with something else, like an RTC timebase, if needed.

But before we dive in there, it’s important to consider the intended scope here. These are all DELTA times, all relative to ‘the start of the performance’, which in this particular case (Hi, again, @Erin_St_Blaine !) is envisioned to be roughly as long as a few pop songs, e.g., less than an hour. If the performers all push their “start button” at the start of each song or performance piece, the amount that the clocks will de-sync over the course of the song is probably too small to worry about.

But this all turns us to the question of “clock drift”, and how much your typical Arduino’s millis() timer drifts over time. And for that, I always refer to this page:
“Arduino clock frequency stability”
http://jorisvr.nl/arduino_frequency.html

I’d sum up his (very detailed!) findings thus: if you have a crystal oscillator on your Arduino board, the timing of millis() is likely to be accurate to roughly one part in 10,000, or to put it another way, accurate to 99.99%.

So in a one-hour (3,600-second) performance, you probably will drift less than a third of a second using the internal timebase, so it’s probably totally sufficient for that. Over the course the KLF’s “What Time Is Love?”, which is 00:05:07 long, you can expect the clock to drift no more than about 30 milliseconds.

So while that’s probably fine for a delta-time for a performance with a synchronized start, as you found out, it’s definitely NOT good enough for a wall clock. One part in 10,000 is about nine seconds per day, or nearly a minute off per week, or half an hour off per month, aka terrible,-- and that’s assuming it’s calibrated to start with, which it isn’t. And FastLED disables interrupts on AVR chips, and performs a fix-up on the internal timer values afterwards, so there’s another small source of drift there.

So for a wall clock? You need a real-time chip. To synchronize two performers for ten minutes? A “Start!” button is probably sufficient.

As for real-time clocks, this shootout
“Benchmarks: Real Time Clocks – Results for Raspberry Pi/Arduino”
http://www.switchdoc.com/2014/09/real-time-clock-comparison-results/
seems to confirm what I’ve subjectively found myself: the DS3231 is great. Adafruit has them on breakout boards (as “Chronodots”) for US$17.50. Both wall clocks that I’ve built have used the DS3231, and both seem rock steady on timing.

Thanks @Mark_Kriegsman , for that detailed explanation.

However, I do remember significantly more differences between measured time and actual time when I started playing with millis() and it was a lot more than the crystal or ceramic resonators deviation numbers from the frequency stability page that you provided.

I do not know for sure why I got such frequency mismatch but only guessed that the internal millis() counter was somehow halted due to interrupt handling or something similar. I did not investigate further as the RTC option was for sure the way to go for a wall clock.

I agree with you that even with the millis() inaccuracies as I remember, it is very unlikely to have noticeable effects over the course of a only few minutes of running your sketch.

My best regards, JP

Thanks JP-
FastLED has monkeyed with the millis counter various over the years, but at this point the error should be pretty small on AVR – and nonexistent on ARM.
Please do let us know if you see serious problems in the future and we’ll take a look again!

This is REALLY awesome. Nice work.

Can you point me to the source file where the FROM and AT functions are? I’d love to see how you did that.

aaah it’s perfect!!! Thank you so much! I can’t wait to play with this and make some art. :slight_smile: :slight_smile:

@Alex_Wayne : everything is in that one source file linked above in the original post here.

@Erin_St_Blaine : let me know how it goes in practice as you try using it – and rock on!

@Mark_Kriegsman Ah so it is! I assumed this was in the library somewhere. That’s a neat trick with preprocessors, I really need to use those more.

Question though, if my loop is fast say < 1ms, would the same ATget called multiple times? Not that my code is ever that fast :slight_smile:

Hey @Mark_Kriegsman ,

I loaded and run a modified version of yourTimecode sketch on my Arduino Uno.

A part from pin numbers and no of LEDs to suit a short string on my bench, I modified the performance as such…

void Performance()
{
AT(0,0,00.001) { FastLED.setBrightness(BRIGHTNESS); }
FROM(0,0,00.100) { confetti(); }
AT(0,1,00.000) { Serial.println (gTimeCode); }
AT(0,2,00.000) { Serial.println (gTimeCode); }
AT(0,3,00.000) { Serial.println (gTimeCode); }
AT(0,4,00.000) { Serial.println (gTimeCode); }
AT(0,5,00.000) { Serial.println (gTimeCode); }
AT(0,6,00.000) { Serial.println (gTimeCode); }
AT(0,7,00.000) { Serial.println (gTimeCode); }
AT(0,8,00.000) { Serial.println (gTimeCode); }
AT(0,9,00.000) { Serial.println (gTimeCode); }
AT(0,10,00.000) { Serial.println (gTimeCode); }
AT(0,11,00.000) { Serial.println (gTimeCode); }
AT(0,12,00.000) { Serial.println (gTimeCode); }
AT(0,12,00.000) { Serial.println (gTimeCode); }
AT(0,13,00.000) { Serial.println (gTimeCode); }
AT(0,14,00.000) { Serial.println (gTimeCode); }
AT(0,15,00.000) { Serial.println (gTimeCode); }
FROM(0,15,23.000) { fadeToBlack(); }
}

I monitored the time on my PC when the serial monitor printed the Time code and got an average of 45 seconds between prints !!??

Are you getting accurate time transitions on your side ?

I believe that the AT’s are called exactly once each – but check it out and see…

Thanks for the time trial-- I’ll try that myself when I get home! ( 60 =! 45 :confused: )

I had to do it as the details of my initial test were fading from over a year ago although I remembered really bad / unacceptable differentials between real time and time derived from millis() !

I still don’t understand why it is so bad but, just in case, I repeated the same test on my other 2 Uno’s and also on my MEGA2560 and I am getting exactly the same results !!??

I am using Arduino 1.0.5 R2 IDE if that has anything to do with it !

How many of what kind of pixels are you using when you call show? Any?

I have a single short string of 25 WS2812

I could, if you want/need, setup a longer string for more tests ?

I’m curious what you see if you comment out the calls to show() and delay() entirely.

Basically, take FastLED out of the equation. We should either see things get more normal speed (in which case maybe we can work on this internally), or it’s still too fast… which will be interesting, too.

BINGO!! I just run it for 2 minutes and now it is bang on 1 minute !!!

Well, just uncommented only the line…

FastLED.delay(1000/FRAMES_PER_SECOND);

and found that I get LED animation without specifying show at all !?

And also got back to a ~ 45 seconds realtime between prints !

Next I try only show and no delay…