Final Project
Programmable, portable, and remotely controllable guitar preamp/effector that plugs into a guitar. The input signal from guitar is processed by the effector which can drive either an amp speaker or a headphone. It has Bluetooth connectivity that allows a wireless device e.g. smartphone or laptop to control the effector remotely.
![](img/P1040436.png)
Working video:
Final product:
![](img/P1040395.png)
![](img/P1040342.png)
![](img/P1040350.png)
CIRCUIT
The circuit includes ATTiny44 for processing the input signal, LM386 for driving headphones, and Bluesmirf Bluetooth module for wireless connectivity. I used ATTiny44's differential ADC with 20x gain to get good dynamic range for input signal from the guitar.
![](img/final_circuit.png)
![](img/P1040293.png)
The parts to be connected: 9v battery, 1/4" input/output, 1/8" output, potentiometer for volume control, and a Bluetooth module.
![](img/P1040294.png)
Generations of the circuit design. From old (left) to new (right).
![](img/P1040285.png)
SOFTWARE
Arduino code:
#include <SoftwareSerial.h>
#define rxPin 0
#define txPin 1
SoftwareSerial mySerial(rxPin, txPin);
unsigned char inputLo, inputHi;
int inputRaw;
unsigned short output;
int preset;
//effect
int fx;
int j, value50, value300, value10000, delayed;
//chorus
unsigned char buffer[128];
byte Progress;
boolean Direction;
byte Offset;
byte Position;
unsigned short SinceNudge;
unsigned short SinceUpdate;
unsigned short NudgeLength;
//audio processing
int iw;
byte bb;
int icnt;
int iw1;
volatile byte Timewaster;
void setup()
{
CLKPR = (1 << CLKPCE);
CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
TCCR0A = ((0 << COM0A0) | (1 << COM0A1) | (0 << COM0B0) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00));
TCCR0B = (1 << CS00); // set timer 0 prescalar to 1
pinMode( 8, OUTPUT);
pinMode( 7, OUTPUT);
analogWrite( 8, 0 );
analogWrite( 7, 0 );
ADMUX = (0 << REFS1) | (0 << REFS0) // 5V ref
| (1 << MUX5) | (1 << MUX4) | (0 << MUX3) | (0 << MUX2) | (0 << MUX1) | (1 << MUX0);
ADCSRA = (1 << ADEN) // enable
| (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0); // prescaler /64
ADCSRB = (1 << BIN); // bipolar mode
/* Give it four cycles to sink in. */
Timewaster++;
Timewaster--;
Timewaster++;
Timewaster--;
//init value
j = 50;
value50 = 50;
value300 = 300;
value10000 = 10000;
delayed = 0;
Progress = 0;
Direction = 0;
Offset = 0;
SinceNudge = 0;
SinceUpdate = 0;
NudgeLength = 0;
preset = 1;
mySerial.begin(115200);
}
void loop()
{
if (mySerial.available()){
preset = mySerial.read() - 48;
}
fx = 100;
if(preset==0){ //bypass
readInput();
outputInt(inputRaw, 5, 1024); //16 bit out
}
else if(preset==1){ //distortion
readInput();
outputInt((unsigned char)((inputRaw+512)<<3), 5, 0); //16 bit out
}
else if(preset==2){ //phasor
readInput();
NudgeLength = 128;
inputRaw += 512;
inputRaw>>=1;
if(Progress<128) buffer[ Progress ] = inputRaw;
Progress++;
if(Progress>127) Progress = 0;
if( SinceNudge ) SinceNudge--; else
{
if( Direction )
{
Offset++;
if( Offset == 128 ){ Offset = 127; Direction = 0; }
}
else
{
Offset--;
if( Offset == 255 ){ Offset = 0; Direction = 1; }
}
SinceNudge = NudgeLength;
}
Position = Progress + Offset;
while(Position>127) Position -= 128;
if(Position<128) inputRaw += buffer[ Position ];
outputInt(inputRaw, 6, 0); //16 bit out
}
else if(preset==3){ //bit crush
value300 = 1 + ((float) fx / (float) 3);
readInput();
if(delayed > value300) {
unsigned int input = (inputRaw<<6) + 32768;
input = (input >> 8 << 8);
outputInt(input, 0 , -32768);
delayed = 0;
}
delayed++;
}
else if(preset==4){ //customize your own sound
value50 = 1 + ((float) fx / (float) 20);
readInput();
outputInt((inputRaw<<6 + 32768)*value50, 0, -32768);
}
}
/*
I/O for full scale int
*/
void outputInt(int val, int scale, int offset){
output = (val + offset)<<scale;
analogWrite( 8, output >> 8 );
analogWrite( 7, output & 255 );
}
void readInput(){
/* get input */
delay(2); // Wait for Vref to settle
ADCSRA |= (1 << ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
inputLo = ADCL;
inputHi = ADCH;
// rearragne bits
inputRaw = 256*inputHi + inputLo;
if (inputRaw > 511){
inputRaw -= 1024;
}
}
iPhone application for controlling the effects
![](img/P1040451.png)
CASE
![](img/rhino_case_model.png)
![](img/P1040438.png)
Two parts of the case slide and snap into each other. Very sturdy, no hinges needed.
![](img/P1040445.png)
Testing how the connectors can be installed.
![](img/P1040302.png)
![](img/P1040301.png)
![](img/P1040303.png)
![](img/P1040307.png)
PUTTING TOGETHER
![](img/P1040374.png)
![](img/P1040380.png)
![](img/P1040369.png)
![](img/P1040332.png)
![](img/P1040384.png)
Copyright © 2014 Sang-won Leigh