I thought I might as well share some of the code I have been putting together to give an idea of complexity and structure. So here is the code for the part that displays the tuner. It needs refactoring, but isn't too embarassing.
You may also notice some code to dim the screen when nothing is happening. It doesn't work. A debug session is in order.
//////////////////////////////////////////////////////////////////////
// this code will aim to detect the nearest note and then show which
// direction to tune to get to the exact note
//////////////////////////////////////////////////////////////////////
void displayTuner() {
String note = lastNote;
// check to see if the sample buffer is ready
if (isSampleReady() && isAmplitudeOK()) {
frequency = getPitch();
resetSampler();
note = getNearestNote();
}
// if no amplitude detected, start to fade display
if (!isAmplitudeOK()) {
brightness--;
if (brightness <= MIN_BRIGHTNESS) {
brightness = MIN_BRIGHTNESS;
}
} else {
brightness = MAX_BRIGHTNESS;
}
if (noteError == 0) {
textColour = getGradientColour(brightness, SHADE_GREEN);
}
// redraw the background graphics if we've swapped sides of the error display
if ((noteError == 0 && lastNoteError != 0) || (noteError < 0 && lastNoteError > 0) || (noteError > 0 && lastNoteError < 0)) {
displayTunerGraphics();
}
if ((note != lastNote) || (textColour != lastTextColour)) {
// display the note
Display.txt_Height(5);
Display.txt_Width(3);
Display.txt_Attributes(0);
Display.txt_Opacity(OPAQUE);
Display.gfx_OutlineColour(BLACK);
Display.gfx_RectangleFilled(60, 0, 100, 50, BLACK);
int xpos = note.length() * 22;
xpos = 81 - (xpos / 2);
displayTextAtPoint(note,textColour, xpos, 8);
}
Display.gfx_OutlineColour(colour);
int offset = TUNER_OFFSET;
int increment = TUNER_INCREMENT;
if (noteError > 0) {
offset = 92 + offset;
for (int i = 0; i < 10; i+=2) {
if (noteError > i) {
int shade = getGradientColour(brightness-(i*3), SHADE_GREEN);
Display.gfx_RectangleFilled(offset, 5+i, offset+5, 45-i, shade);
} else {
Display.gfx_RectangleFilled(offset, 5+i, offset+5, 45-i, BLACK);
}
offset += increment;
}
} else if (noteError < 0) {
offset = 67-offset;
int invertError = -noteError;
for (int i = 0; i < 10; i+=2) {
if (abs(invertError) > i) {
int shade = getGradientColour(brightness-(i*3), SHADE_GREEN);
Display.gfx_RectangleFilled(offset, 5+i, offset-5, 45-i, shade);
} else {
Display.gfx_RectangleFilled(offset, 5+i, offset-5, 45-i, BLACK);
}
offset -= increment;
}
}
lastTextColour = textColour;
lastNote = note;
lastNoteError = noteError;
}
Wednesday, 30 October 2013
Ready to build a soldered version
So although I thought I had the final circuit, I didn't. I added an additional digital pot to the feedback loop of the pre-amp to allow me to boost output when the tuner was engaged and lower it again so as to avoid clipping when being played more dynamically (that's strumming the guitar to you and me).
I also did some more work on the tuner code, switching from the slope detecting code to a Yin algorithm that works by shifting the waveform until it overlaps as accurately as possible. Initially I tried this in fixed point, but had all kinds of problems avoiding overflow and still keeping accuracy, plus I then needed 32 bit integers and managed to fill up the 8K RAM you have for data on the Mega card. I did try shifting some static variables into program memory rather than RAM, but that made code almost unreadable. Instead I managed to optimise out a lot of static data, such as my frequency look up tables, and was then fit in a good sized buffer to enable a sufficiently large waveform for the Yin algorithm. For the high E, this is easy, for the low E, it was challenging to get a couple of cycles.
Further tweaking allowed me to lower the sample rate as guitar strings are quite low frequency, meaning more cycles captured, and then I used floating point instead of fixed point. Although this is undoubtedly slower, it is actually just about fast enough and updates about once a second. I'll try to improve on this by moving as much as possible into the integer domain and only use float when strictly necessary, but for now fixed point seems to be impossible to tune for the Yin algorithm on an Arduino. Or more properly I haven't had the time to work out where it goes wrong and find a solution.
So here is the probable final channel circuit with the target guitar.
I also did some more work on the tuner code, switching from the slope detecting code to a Yin algorithm that works by shifting the waveform until it overlaps as accurately as possible. Initially I tried this in fixed point, but had all kinds of problems avoiding overflow and still keeping accuracy, plus I then needed 32 bit integers and managed to fill up the 8K RAM you have for data on the Mega card. I did try shifting some static variables into program memory rather than RAM, but that made code almost unreadable. Instead I managed to optimise out a lot of static data, such as my frequency look up tables, and was then fit in a good sized buffer to enable a sufficiently large waveform for the Yin algorithm. For the high E, this is easy, for the low E, it was challenging to get a couple of cycles.
Further tweaking allowed me to lower the sample rate as guitar strings are quite low frequency, meaning more cycles captured, and then I used floating point instead of fixed point. Although this is undoubtedly slower, it is actually just about fast enough and updates about once a second. I'll try to improve on this by moving as much as possible into the integer domain and only use float when strictly necessary, but for now fixed point seems to be impossible to tune for the Yin algorithm on an Arduino. Or more properly I haven't had the time to work out where it goes wrong and find a solution.
So here is the probable final channel circuit with the target guitar.
Monday, 21 October 2013
One Pickup Prototype
So this is the final prototype for the guitar circuit. I have tweaked ICs (some were noisier than others) resistors and capacitors until I have a loud enough circuit that doesn't clip when the guitar thrashed but has the same output as a normal guitar.
My main concern has been to retain an authentic tone by comparing the pickups with and without circuits. The aim isn't fidelity as guitars are meant to distort, but a good tone, rich, full and chiming. Ultimately it's limited by the pickups that aren't as good as my Suhr's, but it now sounds right.
The next stage is to make up some circuit boards now, I'll use strip board to start with and a prototyping shield for the Mega. The shield will just be a place to attach connectors to the right pins and won't have any circuits on it. The transfer to circuit board should also help with noise and reliability - the capacitive circuits seem to be affected by all the extra wires and occasionally I knock a wire and it all gets very noisy again.
I'll then replicate the circuit for all three pickups and try switching. I have decided to not use relays but instead just turn volumes to zero. This will save power as I want this to be battery driven from a lithium battery pack I bought earlier.
I also plan to have the USB accessible for re-programming the guitar once it is assembled as the tuner isn't as reliable as I want. I need to work on the algorithms for matching the same point in the waveform. Currently it works by looking for the highest slope, but I think I can improve on this for better pattern matching. I'll need to record some waveforms for this and then prototype it in Java in my laptop.
Saturday, 12 October 2013
Fitting the display and updated graphics
After a bit of filing and shaving of both display surround and guiter body, the colour display is in place and I have also tried some positions for the Arduino card within the guitar body.
The graphics have been updated to be simpler and use colour more to indicate what i
s happening, so volume and tone use a gradient that goes from dark to light as value increases.
I'm still thinking about the tuner control, I have a version that works (the code correctly identifies note from a given frequency), but it isn't so pleasing from a graphical aspect. I can return to that later though.
Next step is to hook up the capacitive input chip and try some touch and proximity sensing to start controlling functions. Once I have that, then I'll move onto actual signal control. That'll start with relays to select pickups and then onto volume and tone control.
I have an audio amplifier chip (several actually, in case I get clumsy) that uses 5v and will output with 20x gain the signal based around a datum of 2.5v, which is perfect for the digital potentiometers I will use for volume and tone as they need to operate in a 0-5v range.
At the end of the audio chain all that is needed is a capacitor to remove the DC and that can sent to the guitar amplifier.
Ok, time for some soldering...
Monday, 7 October 2013
First test screens
I assembled my shopping list and bought the following:
First task was to hook up the OLED to the Arduino using the shield I bought for it. Except that it meant that you had to remove the shield to program the display because it connected to the Rx/Tx lines used for serial uploading of new code. So the shield was banished and I wired the serial display Rx/Tx to pins 16 and 17, not 0 and 1.
Now that I could load code, it was time to break out the Goldelox libraries. First of all I tried a Picasa one that seemed to work for some people, but I soon realised that was the wrong one. So I found the correct Goldelox one and everything sprang into life late on a Saturday night. The problem is that although the Arduino is happy being developed with a Mac, all 4D Systems tools are Windows based, so unless you download and disassemble the Windows installs, you can't find the libraries.
First thing to say is that the Arduino development environment whilst not as sophisticated as most modern IDEs is a lot better than I expected. Writing and loading code is easy and once you have worked out that adding a new tab means "add a new file to the project" you can soon start putting together a decent project structure. Coding is like a limited C++, which is fine by me.
So here is the product of a few hours coding to see what sort of easy to read display I could create that would fit in in the guitar (there's more than enough room for Arduino cards)
The iPhone I used to film this has completely washed out the colours as well as generating the video striping from different display rates. In reality and on the guitar it looks pretty decent and is very readable, so I may stick with it for now and add a unique font and background images later on when I am adding polish.
- An Arduino Mega2560
- A 4D Systems uOLED-160-G2 OLED display with Goldelox processor
- A breadboard. A big one. There will be quite a bit of signal control going on.
- Many breadboarding wires
- Assorted resistors
- Assorted capacitors
- Some Digital Potentiometers
- Relays to control the analogue signal path
- A capacitive sensor board to do touch and proximity sensing for the controls
First task was to hook up the OLED to the Arduino using the shield I bought for it. Except that it meant that you had to remove the shield to program the display because it connected to the Rx/Tx lines used for serial uploading of new code. So the shield was banished and I wired the serial display Rx/Tx to pins 16 and 17, not 0 and 1.
Now that I could load code, it was time to break out the Goldelox libraries. First of all I tried a Picasa one that seemed to work for some people, but I soon realised that was the wrong one. So I found the correct Goldelox one and everything sprang into life late on a Saturday night. The problem is that although the Arduino is happy being developed with a Mac, all 4D Systems tools are Windows based, so unless you download and disassemble the Windows installs, you can't find the libraries.
First thing to say is that the Arduino development environment whilst not as sophisticated as most modern IDEs is a lot better than I expected. Writing and loading code is easy and once you have worked out that adding a new tab means "add a new file to the project" you can soon start putting together a decent project structure. Coding is like a limited C++, which is fine by me.
The iPhone I used to film this has completely washed out the colours as well as generating the video striping from different display rates. In reality and on the guitar it looks pretty decent and is very readable, so I may stick with it for now and add a unique font and background images later on when I am adding polish.
Updating the Bond Electraglide with modern electronics
Earlier this year I bought a Bond Electraglide guitar. The
Electraglide was the Delorean of the guitar world, an 80′s dream of a
future instrument that sadly crashed and burned because the idea
outreached the technology of the time.
The guitar had many innovations, fully electronic internals with a
digital read out, a completely original fretboard with stepped aluminium
ridges instead of frets and a composite body that although not carbon
fibre is similar in look and feel.
Unfortunately the Bond cost too much to make and although an
intriguing design that used high quality components, it was a financial
failure. It was unreliable, with the outboard power supply often failing
and guitars being robbed of parts to get others working. The case alone
cost over £150K in tooling and although it was championed by the Edge from U2,
Mick Jones of Big Audio Dynamite and Dave Stewart of the Eurythmics, it
only lasted a year in production.
Only 1400 were recorded as being made, with the real number most
likely under 1,000. They are closet classics, their scarcity and
originality sure to make them future collector items. You can still pick
one up hundreds of pounds if you are lucky, although shops sell them
for thousands.
So I have one, or rather as of two weeks ago, two. I have an original, clean
and complete Bond with case and PSU and now a second Bond, with tatty
case and no electronics.
So what to do with the incomplete one? My idea is simple. Using
modern electronics, make the Bond what it should have been – a modern
guitar. However it won’t be all digital, I love the analogue sounds of
old guitars and so I want to use different pathways for audio and
control.
I plan to use an Arduino for switching and OLED display
control, but then use all-analogue pathways for the output of the
pickups to the amp. I will use relays for signal switching and the one
concession to digital control will be to use digital potentiometers to
adjust tone and volume.
Once I have the basic guitar controls in place, I plan to go
further with a tuner based on the Arduino and then look at other built
in analogue effects, such as a tube screamer or boost. I may even extend
to using EMG pickups if I can get some at a good price.
Finally, a new paint job may be in order, depending on the price
again. I think a pearlescent white might be in order, or perhaps one of
the colour shifting car paints.
Subscribe to:
Posts (Atom)