Gecho Loopstyler is a 2D Stylophone.

In compare to traditional Stylophone, it uses a matrix of rows and columns, expanding the possibilities. You can think of it as a Stylophone combined with Le Strum.

The design of electronics is derived from Gecho Loopsynth v2. Likewise, loopstyler listens to your environment, capturing the faintest sounds, applying effects to them and recording everything digitally.

What can it do?


In this image you can see a prototype board. What is missing are 6 buttons and front panel. The design is similar to our Loopsynth.


The back side is almost assembled. What is missing is the rest of voltage dividers. This is because it took some experimenting to determine the best values, as explained in the "How does it work" paragraph below.


Technical Specifications

An open platform, featuring some of the newest elements, driven by a well-maintained open-source software framework (ESP-IDF).


How does it work?

The classic Stylophone is analog. When we look at the schematic (original one using discrete components [1] or these variations with 555 IC [2] [3]), we can see that it uses resistor ladder to set the frequency of each note. When stylus touches a key pad, it completes the oscillator circuit with desired resistance. This requires every resistor to be precisely "tuned". In real world resistors are manufactured with certain tolerance (usually 5% or 1%), which is not ideal, however it looks like there is no need to pick a "perfect" resistor from a bunch, as the resulting error is usually quite within our perception of a well enough tuned note (+/- 2Hz, or 2-8 cents depending on the octave).

This simple approach works well for a typical Stylophone with one row of keys and about two octaves. It would probably work well for even 4 or 5 octaves. But what if we are happy with one octave but want more rows instead? Not sure how exactly might this be useful in the analog circuit - we'd need a oscillator per row and tune every resistor ladder differently, so the "columns" represent individual chords. That would be interesting, but limited to a set of pre-defined chords. Thankfully in a digital device there is a lot more flexibility, as we merely need to detect which pad was touched with the stylus; translation to exact frequency for each note happens in the software.

Implementing the digital stylus

Common embedded microcontrollers like those used in Arduino, STM32 and other prototyping boards have input pins with ADC capability (analog to digital converter), which are very useful. There is usually two or more ADC blocks, each with a couple of "channels" - each channel connected to a separate pin. The measurements are read in sequence and the conversion happens so fast that there is no need to have a separate ADC block per pin.

Imagine that in a digital Stylophone, we have the same resistor ladder, with one end connected to the positive voltage source (Vdd), e.g. 3.3V or 5V, and another one to ground (GND). The stylus is connected to ADC input and measures the voltage. When touching a key, voltage is detected somewhere between 0 and Vdd. We could just use the same resistors everywhere, as many as needed, and the measured voltages will be evenly spaced (as that's how voltage dividers work). If Vdd was 3.3V and there were 15 resistors as on the picture above, we would measure a voltage of 0.22V over each resistor. If stylus touches pad P1, ADC will measure 0.22V, if P2 then 0.44V and so on. Since from the perspective of writing the code, measured values are rather integers from 0 to maximum resolution (determined by bits, for example 1024 for 10-bit ADC), we will receive values like 68, 136, 204..., which are easy enough to analyse in the code with some simple math.

We could also save two of these resistors, having first pad connected directly to GND and the last pad to Vdd. In such case, the first pad will result in a measured value of 0 and the last of 1023 (which is 2^10-1). Of course all this is theoretical, in reality everything is less precise due to element tolerances, voltage fluctuations etc..

Now, doubling this circuit will not help us much as we would not know which row's key is touched by the stylus - the same values will come from corresponding pads in each row. Changing first and last resistor by the same amount (for example to 3k3 and 6k1) will shift the entire array of values accordingly, but that is not fundamentally different from having just one long chain of resistors spreading over more rows. Because of how the measured values fluctuate, at some point the voltage differences will become too small to detect reliably, resulting in errorneous triggering of adjacent keys.

What if we could use more than one ADC channel, ideally one per row of keys? It would work, only if there was a separate stylus connected to each ADC pin. In order to be good with only one stylus, we need to reverse the whole thing.

Let's have a similar ladder, with the pad after the first resistor connected to ADC input. Now, the stylus will be simply connected to GND. By touching individual pads, it will shorten them to ground and effectively remove the remainder of the ladder from the equation. This will directly influence measured voltage. We can have as many ladders as there is ADC channels, and will always know which pad in which row is grounded by the stylus. Even better, this allows for some level of polyphony. If the stylus did not just have a rounded tip but a wider one that can cover more pads simulatenously, we could tell which pads in which row is it touching. Of course we will not be able to tell if two pads in the same row are touched, only the leftmost one will be detected.

It should be easy to see that touching P1 will ground the ADC directly, resulting in a measured value 0. P2 will create a voltage divider consisting of two equal resistors, so it will generate a value in the middle, fluctuating around 512 (we are still talking about 10-bit ADC as in previous example). Then it gets more complicated, P3 will set the resulting voltage at 2/3 of the range (measured value of 683), P4 at 3/4 (768) etc.. The farther to the right we move, the differences will be smaller. P13 vs. P14 will be 12/13 vs. 13/14, or 945 vs. 951, which might already be too close to detect reliably at this ADC resolution.

Tangent about the internal workings of ESP32

The ESP32 chip we are using in our designs has ADCs that can operate with up to 12-bits of resolution (it can be configured). This gives integer values from 0 to 4095 (2^12-1). Below you can see predicted result of what values will we get from an evenly spaced resistor ladder as described above. In reality the values slightly differ thanks to element tolerances and internal conditions of ADC. It contains a source of so called "reference voltage" with which the incoming voltage is compared, and this reference is not always set precisely due to environmental influences like temperature or manufacturing tolerances - simply saying, every chip is slightly different.

Also, the ESP32 ADC block uses reference voltage of 1100mV (which in reality can be 1000-1200mV), and there is an "attenuation" parameter that allows to measure voltages above the reference voltage (normally, the range of reference voltage will map over the whole ADC range, e.g. from 0 to 4095). To measure voltages up to 3V as we need in our application, we are selecting attenuation of 11dB (parameter is ADC_ATTEN_11db) which expands the range to 3.9V (clamped to Vdd by protective diodes at input).

Optimizing the resistor ladder

Anyway, we can see that the first half of the range (from 0 to 2048) is unused, while towards the end of the range, we have the voltages packed too close together. Still, in the first iteration of Loopstyler, this already worked reasonably well. However we want to avoid the necessity of "calibrating" this in any way, it will be much better to allow the values fluctuate more wildly without any adverse effect.

The solution is to distribute the resistances differently. While it is possible to calculate values which will result in evenly spaced voltages, ideally we should re-use values that are already elsewhere in the design. The reason is that the manufacturing cost of the PCB increases not only with number of elements, but sometimes even more with number of different elements. This is because the elements come to the assembly machine in reels, and every new value requires installing of a new reel. The machine can only handle a certain amount of reels at the time, so having more reels means that it might be necessary to swap them in the middle of the assembly process. Therefore we want to keep using resistors like 1k0, 2k0, 4k7, 10k, 20k and no other. Some of these values are the "must have", dictated by things like I2C pullups (4k7), MCP73831 charging circuit current setting (2k0), driving of LED diodes (1k0), or ESP32 external circuitry requirements (20k). Arguably, this value could be avoided altogether by replacing it with a pair of 10k resistors, but there is hardly enough space to accommodate them close to the CPU where they need to be. There are also 47k resistors used at the output of TLV320AIC3104 sound chip, but we do not want to use this value as it would result in an unnecessarily high overall resistance of the ladder.

Excel is a great program and it is easy enough to tweak the spreadsheet and instantly see the impact. It only took a few minutes to arrive at this configuration, which distributes the voltages quite well. The difference in integer values is never below 100, and if you think of the "delta" column as percentages (as the floating point values are "normalized", by GND being at 0 and Vdd at 100%), you can see no two points are closer together than 3% of the whole range. Compare this to previous configuration, where the rightmost points were as close as 0.5% of the range. The column "improvement" compares the delta value against corresponding one from the previous configuration. As you can see, it got worse in the first few points, where it does not matter, and got much better at the latter points.

With this method we could easily have 33 pads in the row (over 2½ octaves), with the same 3% clearance between them.


Prototype PCB

This is the first iteration of the circuit board. In compare to Loopsynth, most things were turned upside down. Four buttons, switches and USB connector are now at the top, to make space for array of metal pads. What used to be SET and RST buttons were moved to right, and will probably be renamed. Most LEDs were removed, only one row of 8 LEDs remains - they will probably be yellow. Power LED will most likely be white, as it is easier to look at than other colours. There will be no blue LEDs this time, only some red to indicate charnging and recording.


The resistor ladders are situated on the lower side of the PCB, bottom side. On this see-through picture you can see how the pads are connected to the resistors.


This is the top side of the board, with silkscreen visible (white text). The larger copper area between left 12 columns and 2 remainig columns is a touch-sensitive pad, connected to one of the ESP32 inputs with this capability. This was not originally planned but as there is micro-SD card holder underneath, it is not possible to put more columns of pads over it - there would not be enough space for the resistors. The electrodes at left and right are connected to GND, for the purpose of attaching a crocodile clip for the stylus' wire (later there will probably be a dedicated connector).


And this is the bottom side, also with silkscreen visible (yellow text, although in reality it is white too).



Coming soon!

Once the prototype works, it will be matter of 3-4 months to manufacture and start shipping the first batch.
And you could be among the first to ever own one of them. Sign up for updates here to not miss the launch!