[time-nuts] Re: metronome

SimBeej t3acherbj at gmail.com
Sun Jul 4 23:02:17 UTC 2021


Hi Folkert,
As a total newbie timenut myself I don't have any advice to offer, but just
wanted to say, what a great project and well done you!!

:-)

Belinda


<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Virus-free.
www.avast.com
<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Sun, Jul 4, 2021 at 5:30 AM 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
> _______________________________________________
> 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