Page 1 of 1

An Arduino parallel keyboard scanner

PostPosted: Sun Feb 17, 2019 6:51 pm
by Coenraads
In the belief that a properly programmed Arduino can perform any function necessary to implement a VPO, at a cost much less than that of commercially available units, I decided to explore whether an Arduino Mega has enough digital inputs to parallel scan a 61 note keyboard. At first the answer appeared to be no, until I discovered that three of the four serial ports can be relieved of their serial port duties and reconfigured to yield an additional six digital input pins. It turns out, the Arduino can then scan 64 digital inputs and one analog input, the latter useful for adding an expression pedal. Two, three or more of these scan units, each with the identical program, can then be daisy chained together depending on the number of keyboards. What the limit is, I do not know.

To me, parallel wiring has always seemed attractive because of its conceptual simplicity; configuring and wiring diode-isolated matrixes, I find a nuisance. Here, however, one keyswitch is wired to one input pin, no diodes required. The other sides of the switches share a common ground. Analog input can be as simple as connecting the wiper of a 20k (+/-) potentiometer, connected across ground and 5V, to the analog input pin.

Two procedures are included for converting expression pedal voltages in, to controller commands out. Method 1, features an array of numbers that specifies which controller values are to be output for each input voltage in 0.31V increments. This array can be edited by the user to yield any response curve desired.

Method 2 , which I have commented out, provides a simple linear response but requires that you fit a straight line to two points based on the voltage with the swell pedal closed and the swell pedal open. This works well if the voltage change occupies only a small segment of the 0 to 5V range. Try this if you still remember your y = mx + b.

Daisy chaining the units requires that all the Arduinos be connected to a common ground. Then it is just a matter of connecting Transmit Out (Tx) of one unit to Receive In (Rx) of the next unit (via serial port 0). Each time MIDI data from one unit flows through another unit, its channel number is bumped up by one. This guarantees that data from each unit will have its own unique channel number at the final output. The last unit's output is connected using the standard 5 pin, DIN MIDI out configuration: connect pin 5 in series with a 220 ohm resistor to Tx, pin 4 in series with a 220 ohm resistor to +5V, and finally, connect pin 2 to ground.

The program code may be found on my website:

https://sites.google.com/site/casavantopus400/

Disclaimer: Although the scanners appear to work correctly on my test bench, that's no guarantee that everything will work in a full scale setup. If you find bugs, or have suggestions for improvements, please post a reply.
John

Re: An Arduino parallel keyboard scanner

PostPosted: Mon Feb 18, 2019 10:07 am
by Japio
This is an enormous breakthrough! Well done!
I saw someone on internet was busy with arduino and midi, I think it was you :D
Is it possible to connect enlighted registration knobs and enlighted pistons to an arduino? (I think so)
Do we need original Arduino boards or can clones of € 5,- be used?

Re: An Arduino parallel keyboard scanner

PostPosted: Mon Feb 18, 2019 12:39 pm
by jkinkennon
I would strongly recommend looking at the Teensy 3.2 or 3.6 as a full-blown console controller. Granted they do not have the pin count to scan an entire keyboard, but a single Teensy, which is an extension of the Arduinos, can handle multiple SPI input boards and uses the blindingly fast USB-MIDI connection to the computer.

This approach also avoids the latency issues inherent in daisy chaining. We have run the Teensy 3.6 with three manuals, pedals, stops, and pistons and the only issue is learning to slow it down enough to do effective debouncing without adding latency.

Re: An Arduino parallel keyboard scanner

PostPosted: Mon Feb 18, 2019 2:05 pm
by Coenraads
Compared to programming an 8080 in machine language, back in the mid 1970s, to turn my pipe organ into a player pipe organ (and yes, 16 kilobytes of memory could both store the program and a Bach toccata), the Arduino is heaven sent. Its general capabilities are rather amazing and using C, a comparative breeze to program. It can certainly be programmed to implement lighted draw knobs and pistons. I haven't attempted this, because I help my friends set up inexpensive VPOs and often they are satisfied with, let's say, Jeux d'orgues on an iPad. This allows them to select stops using the touch screen. I could hook up a stop rail, of course, but as soon as a combination piston is pushed, I am not aware of any way of synchronizing the stops shown on the stop rails with the the stops activated in the app. In HW this must be possible and those more familiar with HW than I am, might be willing to explain how this is done.

As far as clones go, I order them from China and stick with names like Elegoo, Sodial and Kuman. I once had a problem with a batch of clones I just could not get to work. After a day of frustration, an Internet search eventually revealed that these clones used the CH340 communications chip as opposed to the usual Atmega16U2 or similar variant. The CH 340 chip requires downloading a special driver but it was not available for my MacBook Pro. So I dusted off my very old PC, downloaded the driver and the clones ended up working just fine. On a supplier's website, zoom in on the chip next to the USB port. If it has pins on only two sides, it's a CH340. 16U2s have pins on four sides.

Latency is always a concern, hence my cautionary note. When I get my next batch of Arduinos I may just daisy chain half a dozen to see what happens. I know the Arduino is lightning fast. I once programmed one as a note sequencer to record and playback my playing. I wanted to see if I could break it, so I played multiple notes by rocking my forearm back and forth across the keys. It didn't miss a beat playing this back. But how could I be sure? The program was set up so that during playback, it would continue to record new music. So while this mess of a playback was occurring, I calmly played a hymn. When I played that back, not a note was missing and the timing was dead on. Since then I don't worry as much.

Now the serial ports are another matter. But 31250 baud is an awful lot of bits per second and a single MIDI command is only three bytes. You do the arithmetic. And remember that I'm not suggesting that people building high-end HW systems go the Arduino route. My ideas are strictly aimed at those who enjoy tinkering with electronics and Arduinos as much as I do and love organs.
John

Re: An Arduino parallel keyboard scanner

PostPosted: Tue Feb 19, 2019 11:47 am
by jkinkennon
The Teensy is extremely compatible with Arduino for about $30. It programs via the same IDE and merely extends Arduino with some great timing features for starters. The conversion would be simple and give you the power to operate an entire console without multiple Arduino Mega boards.

31250 bits per second works out to one MIDI message per millisecond. That is not trivial when daisy chaining devices. At least use a MIDI merger to avoid the daisy-chain. Just trying to offer a simple improvement.

Re: An Arduino parallel keyboard scanner

PostPosted: Wed Feb 20, 2019 10:19 pm
by Coenraads
Thank you for your observations and advice, John. I had a look at the Teensy and am amazed at what this little powerhouse can do. And the way you incorporate it into your products is impressive. But I should doubt that I will make the transition.

What I like about the Arduino is the multiplicity of pins. I normally do go the matrixed route, and a single Mega can easily handle a three manual organ. But on my next conversion (preferably a two manual, not already matrix wired) I'd like to try parallel scanning. Three Arduinos, at $20 each, would handle this including 40 or 50 pistons and three expression pedals. The sheer simplicity of one wire per switch, each going to it's own pin, I find irresistible. Plus the ability to avoid all additional circuitry or components, even diodes and pull-up resistors makes for a pretty clean installation. (One has to love the Arduino's built in pull-up resistors.)

On a two manual instrument, I strongly doubt that daisy chaining will introduce any noticeable latency. One can always put the pedal/piston unit first. It generates negligible traffic compared to the manuals. A MIDI merger is almost certainly unnecessary.
John

Re: An Arduino parallel keyboard scanner

PostPosted: Thu Feb 21, 2019 5:57 am
by NickNelson
I notice that in the handling of the expression input, you truncate before comparing the values to see if it has changed. As I argued here: viewtopic.php?f=15&t=15799&p=118619#p118619, comparison before truncation is a better strategy and not difficult to code.

Nice project, and revived my interest in the Arduino's potential.

Nick

Re: An Arduino parallel keyboard scanner

PostPosted: Thu Feb 21, 2019 7:46 am
by NickNelson
jkinkennon wrote: . . .and the only issue is learning to slow it down enough to do effective debouncing without adding latency.


My current approach to debouncing is do this after sending the note-on or note-off message rather than before. The logic is that if a key is known to have been in a stable state for some given time (ie longer than the debounce interval) then any change in its state can be immediately interpreted as such and the MIDI message sent. The debouncing counters then begin, effectively 'locking' the note in its new state until it is demonstrably stable again. There is effectively no latency.

I originally described the approach here: viewtopic.php?f=15&t=13249&p=97822#p97770

This is the relevant block of code :Image

Sorry it's in (Atmel) assembler but you might make sense of it. If not I'll try and turn it into C, though I'm pretty rusty at that. Probably, if your 'scan' interval is much shorter than mine the 32 counts would be insufficient, and a separate and larger register would be needed.

Nick

Re: An Arduino parallel keyboard scanner

PostPosted: Thu Feb 21, 2019 2:26 pm
by Coenraads
Thanks Nick for your always welcome observations and your willingness to share your expertise. I also didn't expect anyone to scrutinize my code quite as carefully as you have.

When I tested my original expression pedal code, it operated nicely but occasionally it would go on a tear and spew out reams of alternating values. I assumed this to be the result of mechanical or electrical jitter. I killed this by comparing the new value not only with the preceding value but also the value preceding that. At first I thought this might halve the the resolution but the output suggests not.
But your approach of comparing before truncating to avoid this altogether makes such elegant sense. Not that I'm going to go back and rewrite this code, but I will keep it in mind in the future

Your approach of debouncing after sending out the MIDI message is one I'd never thought of. And I'm sort of annoyed (kidding) that I can't think of any flaw in your reasoning! I guess in my mind I was just emulating what hardware debounce would do. In practice, I'm not convinced it makes much difference. When I built a multiplexed switching system for my ten rank home pipe organ back in the mid 1970s (with design help from Henry Wemekamp of Classic Organ/MidiWorks), I played with the clock speed to see at what point delay was noticeable. I concluded that any delay less than 10 ms could not be detected. I'm comfortable that my debouncing falls within that. And those of us who play pipe organs are used to latencies longer than that given the slowness of electropneumatic action and the time it takes for the sound to reach your ear.

Brushing off what I remember about 8080 and 6800 assembler, I had no trouble following your profusely commented code. So no C translation necessary, but thanks.

Happy to be programming in C.
John

Re: An Arduino parallel keyboard scanner

PostPosted: Fri Feb 22, 2019 3:03 am
by NickNelson
Coenraads wrote:I concluded that any delay less than 10 ms could not be detected. I'm comfortable that my debouncing falls within that. And those of us who play pipe organs are used to latencies longer than that given the slowness of electropneumatic action and the time it takes for the sound to reach your ear.


I entirely agree that playing a real organ in a real space necessarily introduces latency. In fact I have occasionally considered whether it would add to the realism of a large cathedral or concert hall organ to intentionally introduce the appropriate degree of latency.

However, for practice purposes using virtual organs in small spaces I'm inclined to think that reducing latency as far as possible is a good thing. There contributors to this forum who regard any latency as abhorrent (though I wouldn't go that far myself).

I suppose that one circumstance where latency could become intrusive would be where a virtual organ of several divisions (I am aware of setups with five manuals + pedal) are chained using serial MIDI. This could lead, in theory at least, to unpredictable and variable delays which are not characteristic of real organs in real spaces.

Nick

Re: An Arduino parallel keyboard scanner

PostPosted: Fri Feb 22, 2019 9:37 am
by jbittner
Coenraads wrote: I played with the clock speed to see at what point delay was noticeable. I concluded that any delay less than 10 ms could not be detected. I'm comfortable that my debouncing falls within that.

Keep in mind that the latency introduced by debouncing is only part of the total system latency. As you have some programmatic control over your keyboard latency, it's best to keep its contribution to a minimum lest it push the total latency over an acceptable limit due to those factors you cannot control.

Re: An Arduino parallel keyboard scanner

PostPosted: Fri Feb 22, 2019 2:32 pm
by Coenraads
Hey, you are beginning to make me nervous.
Am I putting code out there with inherent problems? Time for some measurements!
Back to my parallel scanner. I changed the debounce count/array from byte to integer and tried a value of 10,000. It took 7 seconds for the note to turn on, so the cycle period for a complete scan is 700 microseconds. Since I normally use a debounce count of 4 (a guess) my debounce period is 2.8 mS. That is an acceptable latency and enough to tame most noisy switches. The scan cycle, of course, keeps going during debounce and can actually debounce several notes simultaneously.

Now for the daisy chaining and the worst case scenario of 12 notes (each a three byte MIDI instruction) being turned on simultaneously. Since I transfer one MIDI instruction per scan cycle, from one Arduino to the next, this will take 8.4 mS. Significant, but not bad for worst case. Can the serial port keep up?

At 31250 baud, ignoring overhead, this is 3906 bytes per second, I.e. 1302 MIDI instructions per second. So 12 instructions will take 10 mS. Again significant but not bad for worst case. The Arduino can operate at baud rates of up to 115,200 but I doubt that would gain me anything. I.e., the rate at which I'm feeding the serial buffer seems to be a good match for the rate at which data are being transferred.

I think I can relax. For a two, possibly even a three manual organ, I think my code will function nicely. For four or five, yes, use a MIDI merge, but then I'm aiming my work at the hobbyist, not a high-end HW setup.
John

Re: An Arduino parallel keyboard scanner

PostPosted: Sat Feb 23, 2019 11:46 am
by jkinkennon
Your calculations look right to me. I rarely scan faster than once a millisecond and vary from three counts down to just one scan on the attack for a normally open contact where it is safe to assume that one closed reading indicates the key is being depressed. Keep up the interesting work and keep us informed. I haven't followed the code line by line but updates and any additional features are easy with the Arduino.