[time-nuts] Re: metronome

Bob kb8tq kb8tq at n1k.org
Sat Jul 3 20:40:46 UTC 2021


Hi

MIDI gear spans many decades at this point. Some of it will have “interesting”
digital sub systems. It might be interesting to send a metronome sequence to 
various instruments and see how they measure up to your home brew device. 
You *might* find that your ADEV is “state of the art” already ….

Bob

> On Jul 3, 2021, at 4:00 PM, folkert <folkert at vanheusden.com> wrote:
> 
> Hello,
> 
> As an aspiring musician I decided to build my own metronome.
> 
> Musical devices (keyboards, synthesizers) were and even are connected
> via a MIDI interface. MIDI is a current loop, 5v, can be implemented
> with an Arduino (or ESP8266 running Arduino) with only a resistor (and a
> levelshifter in case of the ESP8266). MIDI then transmits and receives
> serial data (1 start bit, 8 data bits and a stop bit) at the lightning
> speed of 31250 bps (yes: this is 1981 technology). This all takes place
> over thick cables connected to DIN-5 connectors.
> 
> As my musical undertakings only happen on electronic devices with MIDI,
> I thought it would be fun to create a MIDI metronome. That's supposedly
> only two hours works. I picked the ESP8266 (in a Wemos D1 mini setup)
> so that I could add a nice little WiFi enabled configuration interface.
> 
> My metronome emits every beat two types of messages:
> - a clock message (0xf8)
> - a touch message (0x99 instrument velocity, where 0x99 means: play a
>   tone on channel 9 which is usually the percussion channel (MIDI has
>   16 channels))
> 
> Then I remembered that there's also MIDI-over-networks which uses
> multicast UDP. Half an hour hacking and that was also implemented and
> worked - nice!
> 
> Because I wanted to keep the regular ESP8266 UART for the ESP SDK
> debug messages (and my own), I used the SoftwareSerial library to
> produce a serial bit-stream on one of the other GPIO pins.
> 
> So then it was all finished I thought: maybe I can make it very precise.
> Maybe even extremely precise. I doubt a regular human can notice delays
> or jitter of less than, say, a few milliseconds but that doesn't stop
> me.
> 
> To see how well it behaved (it sounded good (for my untrained ears)).
> I took 4000 samples of 120bpm (beats per minute), calculated average
> and standard deviation and an allan deviation plot:
> 
> n: 4065, average: 0.517166, std.dev.: 0.001250
> 
> (time is in seconds)
> 
> This is HORRIBLE. After 4k beats, the timing was a bit more than 17ms
> off! (on average) I won't even bother show how the Allan plot looks.
> Luckily that was only a stupid bug and overcomplicated way of tracking
> when the next beat was due (I did not use a timer but determed how
> long the main-loop iteration took (more on that later) and
> compensating for rounding errors).
> 
> Next version used a regular timer on the ESP8266. With only the DIN-5
> connection used (no multicast UDP over WiFi):
> n: 4357, average: 0.500010, std.dev.: 0.000131
> 
> Looks promising!
> Even the graph looks what I hoped for (see attached 1783.png).
> 
> But now I switched on the WiFi output, and took a bit more samples
> (as I fell asleep behind the keyboard):
> 
> n: 152199, average: 0.520018, std.dev.: 0.040506
> 
> Not so good anymore (1783-wifi.png).
> 
> The problem here is that Arduino has a void loop() { } in which you
> constantly should do your things but not in a loop: the loop() function
> is your loop. This allows the Arduino environment to check if the WiFi
> subsystem needs attention or that e.g. the serial ports need to be read.
> The developer unfortunately has not control over what happens when
> outside that 'loop()' function.
> 
> You need to transmit the beat-messages in the loop-function (can't do
> (software-)serial nor wifi in the timer interrupt handler) so if you're
> unlucky, the moment that you 'see' that a flag was set in the timer
> interrupt function might be sometimes delayed milliseconds. On average
> that is 0.02 seconds or 20 milliseconds!
> 
> My next step will be: move to the ESP32 platform. That platform can
> still do everything the Arduino way, but the ESP32 also exports an RTOS
> SDK and has 2 processors to spread your processing over. This
> implementation will take a bit due to circumstances so don't hold your
> breath.
> 
> I wrote this just to share my enthusiasm. I expected it to be maybe 2
> hours of soldering and coding fun, but with this timing-optimizing this
> promises fun for at least a week!
> 
> Maybe after reading this you have any suggestions? Noticed anything
> silly? Please let me know.
> 
> Oh for the graphs I used "AllanTools" for Python:
> https://pypi.org/project/AllanTools/ I used the example at the bottom of
> that page put replaced mdev (modified allan deviation) by adev (the
> supposedly regular one) as I only have a vague notion how to interprete
> the regular one.
> 
> The sampling of the DIN-5 midi is performed by connecting my device to a
> "ESI Audiotechnik GmbH ESI MIDIMATE eX" MIDI-to-USB interface and then
> dumping the messages with a modified 'amidi' from 'alsa-utils' (I added
> code to output timestamps with milliseconds resolution).
> 
> The WiFi output is sampled using a raspberry pi 4 with tcpdump (with
> name resolving disasbled).
> 
> 
> Regards,
> 
> Folkert van Heusden
> <1783.png><1783-wifi.png>_______________________________________________
> time-nuts mailing list -- time-nuts at lists.febo.com -- To unsubscribe send an email to time-nuts-leave at lists.febo.com
> To unsubscribe, go to and follow the instructions there.




More information about the Time-nuts_lists.febo.com mailing list