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 <folk...@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@lists.febo.com -- To unsubscribe send > an email to time-nuts-le...@lists.febo.com > To unsubscribe, go to and follow the instructions there. _______________________________________________ time-nuts mailing list -- time-nuts@lists.febo.com -- To unsubscribe send an email to time-nuts-le...@lists.febo.com To unsubscribe, go to and follow the instructions there.