nOb controller apparently available this instant (this is not a drill)

Pi pico’s have an advertised 12 bit resolution and cost £3.60 here. My initial experiments showed the noise floor at 5 bits, after some reading around I managed to increase this to 9 bits, by adding a shunt diode to the reference voltage, and switching power supply modes. I feel to get any more bit depth I may look at replacing the pots.

Good call on looking at the core module code

This is ugly, but it kills noise fairly well. The assumption is that the noise is centered around a value determined by the pot shaft position. I don’t know the distribution, but it seems to do what I want. The type punning is used to provide a weighted average without using floats. This is for only one pot, but the macros make it fairly easy to use several.

You’ll need to hack this up for Pi Picos as that’s a different word and ADC size.

Ugh! There’s a bug in that code. The last line in setup should read INIT_POT(potval, A0);

I actually fixed that typo during testing, but it must have not gotten copied back to the repo.

Thanks for the code. I have done some experimenting with filtering and can see improvements on bit depth, but at the cost of time resolution. I am now keen to try this out in vcv to see how much of an impact filtering has.

That average takes a fairly large number of samples to converge, but it’s free running, and on the nano seems to track knobs and sticks well. For knobs I’m really looking at Hall rotational position encoders. There, you can read 'em out with I2C, and the digitization comes for free. Sadly, the one I have greatest interest (as5601) in seems out of stock EVERYWHERE despite having “production” status by the manufacturer. Key benefit is that is has high enough resolution, and it can always correspond to whatever soft synth it is controlling at the moment. That one in particular can detect change in the gap-to-magnet, so you can have a push button feature.

Even though they are somewhat spendier, you might also look at the SAMD21 based cards. You get more ADCs, and there’s facility for capacitive sense if you want that.

Lots of interesting stuff happening here, will catch up w/the rest of it later, but there’s @stoermelder’s implementation in MIDI-CAT; haven’t read the code yet but at a glance it looks like it needs to see both the MSB and LSB before it updates. Dev version only, so, not technically in the library, @curlymorphic, but library-adjacent. Here’s a pickup point:

14-bit input in V2 was confirmed in the devlog on Feb '20.

14-bit output is a Rack V2 milestone having been accepted as a FR.

Here’s an earlier thread with @Schabbes and others making the same points as above about waiting. (Sounds like @Vortico is using the MSB/wait for LSB approach).

Mod(s), if you roll by and feel so inclined, this could probably get split ∓ post #14 into its own thread so that it’s easier to find for anyone interested in 14-bit MIDI. (The irony being that the nOb is not a MIDI controller :slight_smile: )

Seems like to “close the loop” someone should submit a standard for VCV to along with the other ones? Admittedly this will only be faced by devs who process MIDI… but maybe there will be more ways to do this in the future.

My guess is that it’ll serve as a reference implementation of the relevant part of MPE+ (a little confusing that it lives there, since MPE and 14-bit control are orthogonal)…

Unless dissuaded, I intend to do my long-ago-proposed whistle-stop tour of the VCV codebase once V2 is out, and I’ll definitely write up how the 14-bit implementation works which, if not a standard, would at least serve as a prose citation rather than a code excerpt…


My implementation does need both messages before proceeding, no matter which order they arrive. This might not work in every case, but well, we’ll see what happens when released to the VCV Library.

1 Like

I’m going to guess that what will happen is that @gc3 will try to make it glitch, and let you know the results. :wink:

First chance I get :slight_smile:

go get it out of git and try it now!!!

1 Like

Parachuting back in for a moment to say that I finally had a chance to test it and v1-dev of @stoermelder MIDI-CAT works like a treat with 14-bit mode on my Faderfox UC4.

To make this concrete using real-world knobs and scaling, plus factory settings:

With MIDI-CAT mapping the FREQ knob of Rack VCO-2, I can tune to 440.04Hz and can get an 0.17Hz change up or down (i.e. to 440.21 or 439.87). In 7-bit mode the closest I can get to A4 is 438.2Hz and the next values up and down are 460.27 (+22.07) and (417.2) (-22), which I’d describe as a flat A# and a sharp Ab, and obviously a big audible jump. To be clear, this is the interaction of VCO-2’s knob scaling and MIDI-CAT’s mapping, not anything specific to the hardware or the 14-bit protocol, but I think it’s not a bad starting benchmark.

Some quick points:

  1. The UC4 has endless encoders, so it should be possible to do about as well with, say, MIDI-STEP, PILE and some fancy slew and scaling to handle knob acceleration; I’ll test this. (Basically, some version of MIDI-STEP and PILE is what’s running on the UC4 firmware anyway, and the question is whether it’s polling at an increased rate and, if so, whether that makes a practical difference);
  2. Slew limiting is still important to avoid audible glissandi (that is, to make glissandi into portamenti) because it’s not as though the HW is outputting anything close to the 14-bit physically traversed values in between the start and end knob positions. In practice, small slew values make changes feel highly responsive and smooth to my ear.
  3. Because (per @stoermelder’s comment above) MIDI-CAT needs a new MSB and LSB message before updating, switching the HW to 7-bit mode without informing MIDI-CAT will, as expected, stop all updates for that CC. The workarounds above might allow auto-switching back to 7-bit using either the timeout or the eat-one method, but there’s a certain amount of “Doctor, it hurts when I do this”; “Then don’t do that!” here.
  4. There are a few quality of life thoughts I might have about mapping and mode changes, but I’ll move those into a separate thread once I’ve experimented a bit more.

The upshot is that high-quality 14-bit MIDI control is available in Rack V1 thanks to @stoermelder and if you’re MIDI-mapping pitch-related knobs (in particular) with MIDI-CAT and aren’t quantizing anyway you should definitely try to use 14-bit hardware unless you like randomly sharp flats and randomly flat sharps.

I will, of course, compare this to the nOb as soon as it arrives!


My cheat for this sort of thing was far more evil. I created a thread from Rack that can mash floats fed via a FIFO into an array that’s globally visible, and I made a simple plug that looks at eight consecutive values and clamps normal floats (-12V, 12V), sends denormals to 0V, and everything else (infs and nans) generates a trigger. The message is a frame char, eight bytes of base64, and a newline. The data decodes to an index uint16_t and a float value. So for the cost of some kludgery, I have comms a lot lighter weight than OSC. I have similar hacks for fsthost (WINE vst2 support), jalv (lv2 standalone), and zynaddsubfx. All I need to drive this is something that reads hardware input, and maps to a float value appropriately.

Neat! Interested to see where you go with this. I haven’t done much with OSC, but am curious to know what problem the additional overhead was creating (or was expected to create). Are you planning HW that has a lot of controllers updating simultaneously at very high speed, and/or are you operating in a restricted environment?

Having spent some time reading about the pitfalls of the MIDI 1.0 standard when using 14 bit CC’s, I decided to implement 3 methods to see what the differences are, and how they translate in use. I have also looked the the Core module, MIDI-CC, where smoothing filters are used. I have used the same filter but added a slider to the context menu to adjust the response, where the original module uses tau = 1/30 = 0.03333333 seconds.

The methods used are: a. MIDI 1.0, when MSB is set LSB = 0. b. When MSB or LSB is recieved, the output is updated, with no zeroing or waiting c. When MSB is updated, LSB is waited upon before updaing all 14bit, LSB are updated with no waiting.

With the smoothing filter set at 0.033333, to match MIDI-CC the scope is showing no noticable glitches, however this changes when the response time of the filter is reduced to the minimum the diffence in the three methods becomes apparent.

a. downward glitches become apparent

b. upward glitches

c. I am yet to see a glitch.

Here is a video showing the differences. My tests have all been using done on a homemade controller consisting of a pi pico, a couple of multiplexers, and some trimmers. It would be very helpful if others could test also to confim the results, but I have been very impressed with the improvements. I have been able to dial in CV values with an accuracy of 0.002V, and tune VCO’s better than I can tune a guitar with a clip-on tuner.

In the video, I have two feeds to the scope, both from the same controller, 7 bit and 14 bit, even though the hardware is at best 12 bit, but more like 9 bit with filtering. The scope is set to 0.25V/div so only covers the range 0 - 1v to be able to clearly see the difference.

The code can be found at rack-modules/Zilah.cpp at Midi-cc-14 · StudioSixPlusOne/rack-modules · GitHub

Windows and Linux build can be found: Release Zilah, · StudioSixPlusOne/rack-modules · GitHub

1 Like

No. More that I’m pretty agressive about conserving resources. It’s sort of a hang over from my PDP-11 / RT-11 and Z80 / CP/M days.

1 Like

ah, an example of Knuth’s law in action?

1 Like

Z80, thats where I started in the 80’s, I had a choice, Amstrad Basic, or Assembly, Now you can get a microcontroller that is more powerful for the price of a coffee.

1 Like

I was there, too. 6502-b. A lot of stuff mattered then.