Step 4: Normalize the Input and Output


This is the only real "trick" when it comes to the hardware for this system. Audio happens as an AC signal from -1 V to +1 V, but the analog inputs on the Arduino run from 0 V (Ground) to some positive voltage called the analog reference (5 V by default). You can specify this positive voltage in code or with an external reference.

Since -1 V to +1 V is a 2 V range, we'll choose something smaller than 2 V for our analog reference value. It turns out 1.1 V is specified as a built in internal reference, which works out nicely.

From here we have to normalize the -1 V to +1 V as 0 V to 1.1 V. I did this using a resistor in series followed by a voltage divider circuit. A guitar cannot directly drive this circuit, it needs a preamp (like another pedal) to drive it. I'm sure you could add a transistor or op-amp preamp to the perf board so you could plug into the pedal directly.


For the output, we're going to be using PWM. With some low level hacks in software, you can get an 8-bit PWM running at 62kHz = 16 MHz / 28

There are some other methods for audio output on the Arduino. A good overview can be found at uC hobby. I got some great results from an R2R DAC, but considering it needs around 40 resistors for 10-bit stereo output, I decided against it. Instead I went with the weighted pins technique, which is kind of like a cross between standard PWM and a resistor ladder.

Building the Circuit

I built two of each circuit on one perf board. I had a ground strip down the center that helped for arranging things as neatly as possible. The first time I built the circuit, it was too tall and didn't fit in the enclosure, so I had to build it again.

When you have capacitors in series like this, they will cut off some of your low frequencies. WIth a 2.2 uF capacitor, it's low enough so it doesn't really affect sounds in our hearing range. The larger the value, the better; but capacitors tend to get physically larger as their value increases.
<p>How would I create this with 1/4 audio jacks?</p>
<p>I played guitar and I think a great invention</p>
<p>I'm having trouble getting sound from this build. I wanted to test the voltage on the input circuit to make sure I was getting values that looked righht, so I wrote a little dummy test to output my value of A0 in the serial console after going through the input circuit (I couldn't find my voltmeter!)</p><p>Oddly enough, when no audio signal is coming in, I keep getting values between 405 and 409. Even stranger, when I connect the input to ground, I still get the same values. When I have a strong audio signal coming in, I get values between 405 and 620. </p><p>The only thing I can think of is that I had to use a lower value cap (.1uF instead of 2.2uF) because it's all I had, but I thought that would just affect filtering. Otherwise I'm not sure what's going on. I've double checked the build of the circuit and resistor values. Any help would be appreciated!</p>
<p>Nevermind, I realized I was a fool and forgot how voltage dividers worked! When I replaced the cap with the proper value 2.2uF I got a ground value of 495, which I realized is close to 512, which is where it's supposed to be since it's a DC offset audio signal, so it's going to oscillate around the middle of the voltage range. When I turned my volume all the way up, I got values between 13 and 1020, just as I should!</p><p>Still no sound out of the other end though, but I haven't tested everything yet.</p>
The folder I downloaded is named &quot;Arduino_Guitar_Pedal&quot; including five files. There is not any GlitchPedal file. May you send me the link to the Glitchpedal code? I am doing something wrong.. <br>
<p>Did you ever get the proper code? I'd also like to see it!</p>
@CyrilHaumont, could not get reply working, so here are the answer: <br> <br>To make it work on newer IDE (&gt;= 1.0) you need to replace all &quot;Wprogram.h&quot; and &quot;Wconstants.h&quot; with &quot;Arduino.h&quot;
Hi, <br>I'm doing a new version of your guitar pedal. But i have just one problem, I can't find any Wprogram.h or Wconstants.h... <br>And i read all comments (randolfo's too), it seems nobody has this kind of problem ? <br>can it be from my version of arduino ide ?
Hi there, <br>I am about to start building this specific project but I would like to know how I am going to upload the code to my Arduino and make it run. Where can I find the GlitchPedal code and do I have to load more code (libraries) to run it? I am noobie as you understood.. Thanks a lot!!
there are no other libraries to run, just the GlitchPedal code. but i recommend you follow this new tutorial by randy http://www.instructables.com/id/Arduino-Guitar-Pedal/
could someone tell me why the compiler tells me that analogWrite is not defined within scope?
I'm a total arduino/electronics noob, but I think that some of the function libraries got migrated to a new location in some core revision to the arduino libraries. <br><br>Basically, in dsp.cpp, replace <br><br> #include &quot;WProgram.h&quot;<br><br>with <br><br> #include <br><br>And then make the same swap in timers.cpp with <br><br> #include &quot;WConstants.h&quot; <br><br><br>The code at least compiled for me. Of course I am still having problems with the actual build. All I'm getting is a very faint square wave buzz that modulates with knobc. <br><br>Why did I think this was going to be simple? <br>
hey man! this looks truly awesome. any chance of a video or mp3? also, how would keyboards/synthesizers/drum machines work through this? sweet project!<br> -stefan1138
check out the video on vimeo <div class="media_embed"> <iframe frameborder="0" height="282" src="http://player.vimeo.com/video/1460684?title=0&byline=0&portrait=0" width="500"></iframe></div>
I got the asynchronous analog read you discussed working, though not using interrupts but a standard loop. Vastly increases my sample rate. Ported the chorus/flanger to it. <br>code: http://pastebin.com/thP70QFj
Wrote a chorus! <br>Pot 1 is chorus speed. Define LINEARITY for experimental sine wave LFO using pot 2 to blend between linear or sine (it has problems) and pin 13 which has a LED on most devices will display the rate visually. <br>http://pastebin.com/nCNyXSsR <br>Works really nicely on low values, with a subtle flange on high values. Can also do many silly noises with the chorus set really fast. <br>Sample: http://soundcloud.com/nexekho/arduino-lo-fi-chorus
Site note: buffers take up quite a bit of memory, might need to go mono for a Mega 168.
Sounds MUCH BETTER in mono due to higher sample rate. <br>http://pastebin.com/2ed16VD0 <br>http://soundcloud.com/nexekho/much-much-smoother
Added a depth control that changes how far it sweeps. Very useful for getting good flange effects. <br>Code: http://pastebin.com/cRmNHCdk <br>Sample: http://soundcloud.com/nexekho/flange-this
Is there a way to add an on/off switch to the circuit (like the one on the picture), making a stomp box out of this?
You can make a bypass with a SPDT which will select either the Arduino output or the guitar input, but it will likely &quot;suck tone&quot; and as such you will need a DPDT to isolate the Arduino input as well.
Yes it would be possible, in tonepad.com you can see a wiring diagram for these switches. It would have to be a DPDT or 3PDT.
I don't usually make guitar pedals so I'm not familiar with the way that switch is wired. If it actually toggles between two sources, you just need to wire the &quot;clean&quot; input directly to one side of the switch, and the distorted output to the other.<br><br>On the other hand, if it is a momentary switch you'll need to wire it to an interrupt pin on the Arduino and modify the code to watch for that interrupt, not applying any effects when the toggle is on.<br><br>I'm sure there are also plenty of schematics out there for making toggle boxes with these switches, in which case you would just wire your clean signal to one input and the distorted signal to the other.
Hey, I just built one of these on perfboard, made a mistake on the inputs (biasing with A7 rather than 5V, will correct in the morning) and while almost everything works (the dials work, etc.) I can't get a sound wave out. If I just take a standard flashing light example script and tell it to whack a PWM to pin 3, it outputs a very loud square wave. Using your code, nothing is output. This is my first Arduino project. I'm using a Nano but it's a Mega328P Nano which should work right?
I've fixed it now. It was an issue with the timer registers. Thanks for the design.<br> <br> I've attached some photos of my custom build. &nbsp;Small size was a priority here so I built the output filters under the Arduino itself which was a fun challenge.
wow! awesome, and congratulations on your first arduino project. glad everything worked out. your design is super compact, it looks great :)
Made some code changes and got it as good as it'll ever be in terms of sound cleanliness. Using 10-bit in, 16-bit out, and a prescale of 8. <br>Sample: http://soundcloud.com/nexekho/almost-perfect <br>(note: I'm using a POD as a preamp and distortion, the Arduino is just clean passthrough at the moment and then a Valvecaster post-amp before going into my PC's line in) <br>Code: http://pastebin.com/9zphwpvA <br>I'm finding that using a tone dial to roll off the highs makes a far cleaner sound. <br>
(also note: I'm not being silly, I'm trying to output a 100Hz triangle wave using your code instead of passthroughing the input ;])
Also, the schematic describes a high-pass-filter for the output. Is that right? It feels like it should be low pass.
I'm new the the arduino scene, is Diecimila the same as Duemilanove ?
This looks great! I was wondering if this can be used with a synth or laptop audio. And if not, if it can be modified to do so..
anything you can plug into a guitar pedal should work fine. and definitely laptop output, i primarily used my laptop for testing this while i developed it.
I see you used ceramic and electrolytic caps. Which one works better?&nbsp;<br /> Also, what would be the polarity if you used the electrolytics in your schematic?<br />
I&nbsp;didn't evaluate ceramic vs electrolytic for their &quot;sound&quot; really, so I&nbsp;can't say which one is &quot;better&quot;. You'll have to try both out and let me know if you hear a difference!<br /> <br /> I&nbsp;vaguely remember, on the outputs, the electrolytic caps facing the output. But again, you should try it both ways -- this was two years ago now and I&nbsp;have been writing a lot more code that making circuits since then :)<br />
&nbsp;Any chance you could post a picture with the other side of the perfboard circuit for the DAC? I'd like to have a go at this project but am having a little trouble with this stage.<br /> <br /> Someone should make an audio input/output sheild for the Duemilanove with all the DAC on board for projects like this!<br />
Sorry, I don't have this pedal any more, I&nbsp;made it for a friend!<br /> <br /> If I remember correctly, the perf board wasn't connected on the back and everything was manually soldered. So hopefully the diagrams/schematics on this page will explain anything missing from the pictures. The pictures were meant more as a layout guide for fitting the components in a smaller space.<br />
I was wondering what kind of preamp is necessary. I don't own a tuner that acts as a preamp (more like a filter). Is it possible to build a preamp that's not too difficult?<br />
A preamp can be as simple as an opamp. But there are a ton of DIY&nbsp;guitar preamp designs, <a href="http://www.diyguitarist.com/GuitarStuff.htm" rel="nofollow">here's one of the first links that popped up on Google.</a><br />
Hi there, <br /> <br /> love your work, I have one question about this though, the r1 on the in-part, what is it good for, why do you need it?<br />
Hi Larsby,<br /> <br /> The r1 acts to &quot;scale&quot;&nbsp;the incoming signal. I&nbsp;generally think in terms of software rather than hardware, so you can imagine the chain on the input acting like this:<br /> <br /> - r1 divides the signal (scales it down slightly)<br /> - c1 centers the signal around zero (removes the DC&nbsp;component)<br /> - r2 and r3 add a constant DC&nbsp;component back in -- shifting the signal up<br />
Hi guys, great work!<br /> <br /> I'm trying to get the basic code working, but I can't seem to get all the PWM pins going! inputs are working fine, as far as I can tell, but only pin 3 is PWM'ing. 5/6/11 do nothing! I'm just using the basic aduino dsp code right out of the box.<br /> <br /> When I edit setupIO() in DSP.cpp to say:<br /> <br /> &nbsp; waveformGenerationMode(11, fastPWM);<br /> &nbsp; timerPrescale(11, 1);<br /> &nbsp; analogWrite(11, 0);<br /> <br /> 11 seems to work fine. (though it's just noise, because i'm not using accurate resistors...)<br /> <br /> I can't get 5/6 to work at all. <br /> <br /> Any ideas? <br /> <br />
I had the same problem, I&nbsp;got around it by removing the &quot;analogWrite&quot;s from:<br /> <br /> void setupIO() {<br /> &nbsp; // prepare left<br /> &nbsp; waveformGenerationMode(3, phaseCorrect);<br /> &nbsp; timerPrescale(3, 1);<br /> //&nbsp; analogWrite(3, 0);<br /> &nbsp; <br /> &nbsp; // prepare right<br /> &nbsp; waveformGenerationMode(5, phaseCorrect);<br /> &nbsp; timerPrescale(5, 1);<br /> //&nbsp; analogWrite(5, 0);<br /> //&nbsp; analogWrite(6, 0);<br /> &nbsp; <br /> &nbsp; // faster input<br /> &nbsp; analogReference(INTERNAL);<br /> &nbsp; analogPrescale(analogPrescale32);<br /> }<br /> <br /> And also fiddling around with the timer registers:<br /> <br /> void waveformGenerationMode(int pin, int type) {<br /> &nbsp; int timer = getTimer(pin);<br /> &nbsp; int wgm = type == phaseCorrect ? B001 : B011;<br /> &nbsp; if(timer == 0) {<br /> &nbsp;&nbsp;&nbsp; TCCR0B &amp;= ~(B1 &lt;&lt; 3); // clear WGM02<br /> &nbsp;&nbsp;&nbsp; TCCR0A &amp;= ~B11; // clear WGM01 and WGM00<br /> &nbsp;&nbsp;&nbsp; TCCR0A |= wgm | B11110000; // set WGM01 and WGM00, Compare on Match<br /> &nbsp; } else if(timer == 2) {<br /> &nbsp;&nbsp;&nbsp; TCCR2B &amp;= ~(B1 &lt;&lt; 3); // clear WGM23<br /> &nbsp;&nbsp;&nbsp; TCCR2A &amp;= ~B11; // clear WGM21 and WGM20<br /> &nbsp;&nbsp;&nbsp; TCCR2A |= wgm | B11110000; // set WGM21 and WGM20, Compare on Match<br /> &nbsp; } <br /> &nbsp; <br />
Thanks man!<br /> <br /> I'll try that and let you know how it goes.<br />
I&nbsp;recommend trying an earlier version of the Arduino IDE (maybe revision 15). I&nbsp;haven't tested this with the most recent versions, and this has some pretty low level stuff that might have been affected by changes.<br />
Thanks man, I tried versions 13 - 15, but no go. <br /> <br /> Anyone else had this problem? I'm just using a standard Arduino Duemianove with an ATmega328P-PU. <br /> I've tried both mac/windows. I'm just using the example code. (the Arduino DSP one, not the Glitch Pedal. Though, that has the same problems...)&nbsp;<br /> <br /> Thanks a million for all the help!<br /> &nbsp;- Loren
I'm stuck on this one. There might be some difference I&nbsp;haven't run across yet between the 168 and 328 registers, but I'm pretty sure the only difference is memory.<br /> <br /> I'm working with someone on making a more sturdy and varied version of this pedal that you could throw into a bag with your other pedals. I'll be rewriting the code completely, but there isn't a clear deadline... so for now I&nbsp;recommend asking on the Arduino forums. Sorry I&nbsp;can't be more helpful!<br />
Hows it goin, <br /> <br /> I have made a mono version of this pedal using the left part the schematics given above and it works grand. However, im trying to read the incoming audio signal from analog 0 and send it to a sketch in Processing. As soon as I add in the lines of code necessary to read the values, the pedal completely fails to work. All I get is a continuous hum and when I look at the serial window it gives constant values around 504 (I also dont know what these numbers represent). The values very slightly change when I pluck a string. The few lines of code I have added are included below:<br /> <br /> ************************************************************************************<br /> <br /> #include &quot;dsp.h&quot;<br /> #include &quot;interface.h&quot;<br /> #define BAUDRATE 9600<br /> #define audioIn 0<br /> #define wait 10<br /> <br /> int val = 0;<br /> void setup() {<br /> &nbsp; <br /> Serial.begin(BAUDRATE);<br /> <br /> &nbsp; pinMode(redPin, OUTPUT); //Sets Pin9 as the red led output<br /> &nbsp; pinMode(greenPin, OUTPUT); //Sets Pin10 as the green led output<br /> &nbsp; pinMode(yellowPin, OUTPUT); //Sets Pin12 as the yellow led output<br /> <br /> &nbsp; setupIO(); //calls the setupIO function<br /> &nbsp; <br /> &nbsp; <br /> &nbsp; <br /> }<br /> <br /> short prev, originalInput;<br /> void loop() {<br /> &nbsp;&nbsp; <br /> &nbsp; updateInterface();<br /> &nbsp; if(delayed &gt; delayLength) {<br /> &nbsp;&nbsp;&nbsp; originalInput = analogRead(left);<br /> &nbsp;&nbsp;&nbsp; short input = originalInput;<br /> &nbsp;&nbsp;&nbsp; switch(mode) {<br /> &nbsp;&nbsp;&nbsp; case bitcrush:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; input = input &gt;&gt; value10 &lt;&lt; value10;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br /> &nbsp;&nbsp;&nbsp; case bitshift:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; input = (input &lt;&lt; value10);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br /> &nbsp;&nbsp;&nbsp; case overdrive:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; input = (int) (512 + (value20 * (input - 512)));<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br /> &nbsp;&nbsp;&nbsp; case binary:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch(value6) {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0: input = input &amp; ~prev; break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1: input = input ^ prev; break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2: input = ~(input | prev); break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 3: input = ~(input ^ prev); break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 4: input = ~(~input &amp; prev); break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 5: input = ~(input &amp; prev); break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br /> &nbsp;&nbsp;&nbsp; }<br /> &nbsp;&nbsp;&nbsp; output(left, input);<br /> &nbsp;&nbsp;&nbsp; output(right, input);<br /> &nbsp;&nbsp;&nbsp; prev = input;<br /> &nbsp;&nbsp;&nbsp; delayed = 0;<br /> &nbsp; }<br /> &nbsp; delayed++;<br /> <br /> &nbsp; val = analogRead(audioIn);<br /> &nbsp; Serial.println(val);<br /> &nbsp; delay(wait);<br /> }<br /> <br /> void updateInterface() {<br /> &nbsp; if(interfaceUpdate &gt; interfaceSamplerate) {<br /> &nbsp;&nbsp;&nbsp; knoba = analogRead(knobaPin);<br /> &nbsp;&nbsp;&nbsp; knobb = analogRead(knobbPin);<br /> &nbsp;&nbsp;&nbsp; knobc = analogRead(knobcPin);<br /> <br /> &nbsp;&nbsp;&nbsp; mode = knoba / modeSpacing; // knoba quantized into mode values<br /> &nbsp;&nbsp;&nbsp; value6 = knobb / 171; // knobb quantized into [0-6]<br /> &nbsp;&nbsp;&nbsp; value10 = knobb / 103; // knobb quantized into [0-9]<br /> &nbsp;&nbsp;&nbsp; value20 = 1 + ((float) knobb / (float) 52); // knobb scaled to [1-20]<br /> &nbsp;&nbsp;&nbsp; delayLength = knobc &gt;&gt; 2;<br /> <br /> &nbsp;&nbsp;&nbsp; alternatePin(yellowPin, mode);<br /> &nbsp;&nbsp;&nbsp; digitalWrite(greenPin, <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; originalInput == 0 || <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; originalInput == 1024 || <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (originalInput &gt; 496 &amp;&amp; originalInput &lt; 528) ? LOW : HIGH);<br /> &nbsp;&nbsp;&nbsp; switch(mode) {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case bitcrush:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case bitshift:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alternatePin(redPin, value10);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case binary:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alternatePin(redPin, value6);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case overdrive:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; digitalWrite(redPin, LOW);<br /> &nbsp;&nbsp;&nbsp; }<br /> &nbsp;&nbsp;&nbsp; interfaceUpdate = 0;<br /> &nbsp; }<br /> &nbsp; interfaceUpdate++;<br /> }<br /> <br /> void alternatePin(int pin, int value) {<br /> &nbsp; digitalWrite(pin, value % 2 == 0 ? LOW : HIGH);<br /> }<br /> <br /> ************************************************************************************<br /> <br /> Sorry if none of this makes sense as I am very new to arduino and code in general. Would you have any idea why this is happening? Or if it even possible to read the incoming audio in this way?<br /> <br /> <br /> Cheers!<br />

About This Instructable




More by kylemcdonald:Structured Light 3D ScanningNandhopper 1-Bit Noise SynthLo-fi Arduino Guitar Pedal
Add instructable to: