Posted on

DIY 26 Speaker Ambisonic Dome – Part 1

This project seemed fairly simple when I started designing it around March 2020. 26 Speakers, 26 amplifiers, an ambisonic decoder and some simple arduino based controllers. It got out of hand very quickly and although I am happy with how the project has come together, I have spent more time than I would like to admit wanting to set the whole thing on fire and forgetting that I ever wanted this thing to exist.

Let’s break it down into sections and have a look at everything that can go wrong when you dive into a project with too much enthusiasm and little forethought.

The Dome Structure

It’s what everyone sees first – it defines the whole project. It turned out to be the easiest part – though I haven’t sorted out all of the problems yet.

The first test assembly, proving the viability of the electrical conduit and PLA printed hubs

The hubs are 3D printed from PLA using a very cheap little 3D printer from Cocoon Products. It’s branded ‘Balco’ and I think that this model was once sold through Aldi. Although it was cheap it has some features that I think a 3D printer must have in order to be genuinely useful.

  • A heated bed – if you print in ABS or other less forgiving mediums than PLA you will need a heated bed. Without one your prints will curl up from contraction of the hot plastic while the job is still being printed. Sometimes it still will anyway. Ambient temperature can have a big effect on the quality of your prints. On cold nights I’ve built boxes from styrofoam, cardboard and clear polycarbonate around to printer to keep the heat from the bed escaping. A ready-made fully enclosed printer would be great, but is three times more expensive than my Balco.
  • Standalone operation from an SD Card – I have CNC mills that are driven straight from the computer (via the parallel port). It’s great to have a cool animated display (from Linux CNC), but it requires me to have a monitor, computer, keyboard and mouse for each mill. Either that or have my laptop tied up for four hours during a cut. It’s great to just load a GCode file onto the SD Card, open it from the touch screen and walk away.
  • Moving bed gantry design – this is nice because the bed doesn’t move beyond the boundaries of the printer base. For messy people like me, this means that your printer won’t push things off the bench. (My CNC mills will do this all the time if I’m careless).
  • A cool little touch screen with utility functions built in – filament exchange, homing and bed-leveling are all built into the unit. This saves a lot of time and fiddling around.

Files are prepared for the 3D printer using the free software package ‘Ultimaker Cura‘. It won’t help you with modifying your designs, though it can expand or shrink the size – a function I’ve used in very small increments to make the caps fit better on my hubs.

The Dome Components

The dome is a 2V geodesic semi-dome, needing three hub types to complete. The clips are electrical conduit clips. Also shown in the picture are the 6cm speakers and the first version of the class D 26 channel power amp. There’s 100m of speaker lead on that top reel – it wasn’t nearly enough.

My original plans were to test print the dome using PLA (it’s faster and more forgiving to print) and, after verifying the design, to reprint the whole thing is ABS for better strength. I never had to bother. The dome has been set up several times in differing locations, been left out in a thunderstorm, and has undergone rapid unplanned disassembly several times (usually when we were trying to raise a finished dome onto its legs. I’ve had to re-print parts due to breakage only four five six times (so far).

Each hub contains a single 6cm speaker held in place with a printed ring. They are quite small and don’t have a lot of volume behind them, so they can’t handle any low frequencies. A single subs unit handles non-directional low frequency audio.

Structural test installation of the dome (without the amplifiers) with temporary legs. The ring of lights around the base give the performer information about the intensity and position of active voices. The steel pickets can be reversed and driven into the ground for a sturdy outdoor setup.
Audio rig test with 10 of the 26 channels active. Full dome installation coming soon.

Posted on

Nichrome wire as a controller input for Max Msp

The bow hair has been replaced with strands of nichrome wire. When the wires are connected by contact with a violin string or another piece of metal they form a conductive loop. The aim is to reliably measure the length of that loop and deduce the position of the bow. The electronics packages also contain gyros and bluetooth modules.

Recently I attempted to create a violin controller that used lengths of nichrome wire to replace the horsehair in the bow. The theory was that I could use the predicable resistance of the nichrome to detect where the bow was contacting a conductive element on the violin bridge. It turned out to be a little more complicated than I anticipated.

28 gauge (0.3mm) nichrome wire (Jaycar). 13.77 Ω/m resistance.

What is nichrome?

Nichrome in an alloy of nickel, chromium and (often) iron. It has high resistivity and is used to construct heating elements. DIY types would know it as the hot wire in a home-made foam cutter. The resistance increases linearly with length – a property I thought would make it ideal for constructing my own sensor.

Turning nicrome into a length sensor

Arduinos, and their clones, make measuring resistances very simple. The usual method is to construct a voltage divider using 5v or 3.3v sourced from the Arduino (or a power supply) and a known resistance (usually something in the order of a few kΩ). There are two reasons why this method will not work with the length of nichrome I am using in my project:

The usual way to measure a resistance with an Arduino. Ideally, the known and unknown resistances need to be similar, but that is not possible with my project due to current concerns.

The sensitivity and voltage range of the Arduino

The change in resistance over the length of nichrome I am using is small – only ~16Ω, and I need to measure that small resistance with the highest accuracy I can get.

Using the voltage divider equation, a divider using, for example, a 1k resistor as the known value will give me a tiny range of 5V to 4.92V on my 5V powered Arduino Pro.

The standard Arduino only has a 10 bit resolution for measuring that input voltage – that’s a 0 – 1023 range, of which I can use ~80 with that tiny change in voltage. To make matters worse, in the real world you sacrifice some of that range to ensure that the values you are measuring are all relevant and all captured. A system set up to use all of the input range has no room for values to slip, components to change, or for just the random behavior that seems to creep into home-built hardware. It is possible, however, to tell the Arduino to use a different measure for comparing voltages.

Input voltages are usually measured against a reference voltage that matches the voltage used to power the Arduino. This is convenient, as the Arduino is commonly the voltage source for sensing attached switches and potentiometers. It is possible to set a different reference voltage inside the Arduino, using AnalogReference(). This approach has some limitations, not the least of which is the lack of uniformity across the range of Arduinos and clones. This project began on an Arduino Mega clone, was installed on genuine Arduino Pro units for the final product and was moved to a Duinotech Nano for one of the interfaces. The second round of hardware has spent some time installed on 3.3v Duinotech ESP32s and a 3.3v Arduino Nano 33 BLE Sense (the sense has an optional 12 bit resolution but uses 10 bits for compatibility).

Lets’s look at the available reference voltages for the family of boards that I have used for the first round. Setting anaglogReference(INTERNAL) gives different results on different boards, some values are only available on Mega boards and the standard value differs between 5v and 3.3v versions of the same boards.

Arduino AVR style internal reference voltages: 
5V (5V power supply) or 3.3V (3.3V power supply)
INTERNAL: 1.1 volts on the ATmega168 or ATmega328P and 2.56 volts on the ATmega32U4 and ATmega8 (not available on the Arduino Mega)
INTERNAL1V1: a built-in 1.1V reference (Arduino Mega only)
INTERNAL2V56: a built-in 2.56V reference (Arduino Mega only)

So why not maximise the voltage available for measurement by using a known resistance similar in value to my length of nichrome? Because that would be very dangerous for my Arduino. The nichrome in the bow forms a loop when the two strands are bridged by a metal contact, so the total resistance would be < ~14Ω when in use (you won’t usually use the very ends of the bow, so you won’t see the full 16Ω). Even if we double that and use a 25Ω resistor, with a 5v source that is is ~200mA (1W @ 5v!). I’ve looked through the specifications for a few models of Arduino, and they have all had a 40mA maximum for IO pins. So how do we do it safely?

Safe sensing

Connecting a constant current source to the Arduino.

We can measure low resistances safely using an external constant current source. R = V / I, so with a known voltage and current we can measure resistance without presenting a risk to the Arduino. The LM317 regulator shown in the diagram provides a known 104mA. We can round this down to 100mA (0.01A) and see that R = 10V. My 14Ω usable resistance range is now a manageable voltage range of 0 – 1.4V of 1.6V total range measured against 5V. That immediately improves the 5V Arduinos measurement resolution to ~287 of ~328. The hardware will be re re-implemented on newer 3.3V modules which improves the Arduinos performance to ~434 of ~496. The 3.3V Nano 33 BLE SENSE has an optional 12 bit mode (0 – 4095) that improves the bow reading accuracy again to ~1736 of ~1984.

Making it Better

There are some easy ways to make the hardware better – the most obvious being altering the current source, but these modules are already built and I’d like them to be useful for other low resistance tasks, so they’ll stay at 100mA for now. There is, however, a simple way of drastically improving the apparent resolution of a hardware sampling system without touching the hardware at all:

Next installment: oversampling

LM317 modules in action:

Bow electronics package. The LM317 is visible on the bottom right.
Another electronics package for the body of the violin, to sense a nichrome replacement for one of the violin strings. The LM317 and 12Ω resistor are visible on the middle right.

Posted on

Using Inkscape (and other free products) to run a CNC mill.

Inkscape is a popular, free and easy to use vector graphics editor. It won’t give you the powerful part manipulation features of a CAD program – but it is a comfortable working environment for artists or designers that may be more used to Illustrator, Canvas, Xara or similar art packages. The current version of Inkscape (.92) comes with a plugin for generating Gcode, a popular language for running small CNC mills. The process for getting from artwork to code and then to the mill is not well documented and can be very confusing for a new user, so I’m going to explain the process step-by-step in the hope that others can find it useful.

The Preparation

Orientation points and the tool library.

In order for the Gcode plugin to generate code, it needs to know where to place the origin (zero X,Y) of your drawing and how deep you need to cut. These values are set using the orientation points. You can move these points to other areas of the document, but be careful not to accidentally group them or edit them when you think you have another part selected or they may stop working. You can delete them and re-generate them at any time if they become broken.

Select ‘Orientation points’ from the Extensions menu

Markers for 0,0 and 100,0 will appear at the bottom of your document. This is an excellent time to check that 100,0 on the Orientation points matches 100 on your X ruler at the top of the page. It can be very confusing if your document measurements are set in pixels (or something else) and your orientation points are in mm. The very last number, in this case -0.25, is the total depth of the cut you wish to perform. You can add more orientation point sets on other layers for different cut levels, but I won’t go into that now. You can edit the depth by clicking on it as if your were editing a normal Inkscape text object.

Next we need to tell Inkscape about your tools and how you want to cut with them.

Select ‘Tools library’ from the Extensions menu.

For engraving work, you will need a cone cutter. For simple jobs with only one tool this selection does not really matter, but it helps to give tools their proper names if you come back to this file after some time has passed.

Click on the text values to edit them as if they were normal Inkscape text objects. Set the speed to something sensible. The depth step will generate layers of cuts until the final depth set in the orientation points is reached. For example, if I had set a depth of 5mm in the Orientation points and 1mm in Depth step, the tool would cut the path 5 times, lowering by 1mm each time. My total depth is only -0.25mm so a step of 1mm will only produce one layer of cuts.

The tool description will ‘helpfully’ appear right over the top of your work, so just drag it off to the side to get it out of the way.

Generating the code.

The Gcode generator has some restrictions. Items MUST be paths and they must not be part of a group. The status line at the bottom of the screen will tell you if you have any groups in your selection. Fonts must be turned into paths! I usually make a copy of my work in a separate, locked, hidden layer before turning it all into paths for the plugin.

You are ready to select ‘Path to Gcode’ from the Extensions menu.

Open the Preferences tab; set the name of your output file and, importantly, your safe travel height! I usually leave on ‘Add numeric suffix’ which just adds a version number to the end of every new file, keeping the old ones in place. I recommend this because it is very easy to forget to update your file name and accidentally overwrite the last project you were working on.

Now flip back to the first tab and hit Apply! Note: you must be on this tab when you hit Apply. It won’t work if any of the other tabs are selected. I guess it must be a restriction in the way plugins are written for Inkscape.

Check the Gcode

This is OpenSCAM, known in later versions as Camotics. The later versions look slicker but have removed some functionality that I liked. It can show you the surface of your finished job and the paths your tools will take over the surface.

Rapids are shown in red, the cut path is in green. This tool is especially useful for calculating how long your job will take to cut at various speeds and depth slices.

Level the Gcode

Autoleveller is a simple but invaluable piece of software that makes PCB or artwork engraving a reliable, repeatable process. It modifies your Gcode to include instructions for probing the surface of your work, recording the variations in height and applying those variations to your cutting job. If PCBs are your focus get this software or something similar without delay.

A simple Java interface. This version is a bit old, but so is my Java. I often work with boxes that are cast with curved edges, so I start the probe job 5mm in from the edge (the X and Y entries), and shorten the X Length and Y Length by a similar amount to avoid the curve. I also raise the Probe Depth from 1mm to 5mm so I spend less time setting the mill up before I start probing. It can generate code for LinuxCNC, Mach3 or TurboCNC. Depth probes don’t have to be expensive or complicated. I glued a microswitch to the end of a pencil shaft that fits over my cutting bit. It works perfectly well and cost me $2.

Posted on

Making keys for the uniform keyboard

It was immediately obvious that painting over the top of re-shaped keys was just not going to be good enough. The existing keyboard I had been shown was functional but looked like a mess. These keyboards would probably see heavy use by students so I needed something very durable that also felt natural. It’s hard enough learning a new way of playing a keyed instrument without the distraction of paint coming off under your fingers.

I decided to re-cast the tops of the raised keys (previously the sharps and flats) in solid white resin. This increases the mass of the key a little, but that is not a drawback. The more expensive Korgs that use this keybed have weights installed to give them a better feel and even out the stronger spring response of the shorter keys. The extra weight of my solid tops is improving the keyboard!

Posted on

Bilinear Uniform Chromatic Keyboard

This is an interesting project. I’ve just been commissioned to alter a Korg Triton LE keyboard to the bilinear uniform chromatic keyboard standard.  It fairly obvious to anyone who has studied keyed instruments that the traditional keyboard is exactly the sort of mess that you end up with when you extend an interface far past what is was originally meant to do. We can’t undo the unholy dog’s breakfast that is tempered tuning, but at least we can address the crazy lopsided way we approach the piano keyboard. If you are interested in how it works, there is a great explanation here.

All of the previously ‘white’ keys need to be trimmed to a symmetrical shape and widened. There are more ‘black’ keys than before, so I’ll have to order some in as parts. Luckily the Triton was a very popularkeyboard, so parts are easy to find. Shaping and re-casting the keys will the tricky part.The Triton is very easy to take apart and the screws are large and mostly restricted to two sizes, making eventual reassembly much easier. After lifting off the bottom plate the whole keybed comes out as one unit. The keys clip in and out of the bed easily. I’ve arranged the ‘black’ keys where I need them, but five more need to be ordered to fill the gap.

That’s the easy part. I’ve measured the keys and laid out my replacement white key in Solvespace. Now it’s time to make a mold and start cutting them up.