Parts List:
(x1) Arduino Uno (Duemilanove is fine, but make sure it is ATMEL328P) Radioshack #276-128
(x1) Arduino ProtoShield Radioshack #276-140
(x1) PC Board with Copper Radioshack #276-147
(x9) High Tact Switch Radioshack #275-002 (I really liked the feel of these buttons, but they only come in a surface mount version, which makes them fairly difficult to solder because of the small leads. Additionally, since these buttons are square it is harder to drill a hole for them in an enclosure. If you are a beginner, you might want to use a different type of button, any of these momentary switches will work)
(x1) 10KOhm Audio Control Potentiometer with SPST Switch Radioshack #271-215 (this will be used to control volume and turn the device on/off)
(x1) 50K-Ohm Linear-Taper Potentiometer Radioshack #271-1716
(x2) 220µF 35V 20% Radial-lead Electrolytic Capacitor (or anything between 200 and 300 uF) Radioshack #272-1029
(x2) SPST PC-Mountable Submini Toggle Switch Radioshack #275-645
(x2) Silver Tone Knurled Knob (or any knob with 0.25" inner diameter) Radioshack #274-424
(x9) 1N914/4148-Type Diode (two packages) Radioshack #276-1122
(x3) 2K ohm 1/2W 5% Carbon Film Resistor (1 package)
(x10) 10K Ohm 1/4-Watt Carbon Film Resistor (2 packages) Radioshack #271-1335
(x8) 20K Ohm 1/4-Watt Carbon Film Resistor (2 packages)
(x1) 4.7K Ohm 1/4-Watt Carbon Film Resistor Radioshack #271-1330
(x1) 1K Ohm 1/4-Watt Carbon Film Resistor Radioshack #271-1321
(x1) 5K Ohm 1/4-Watt Carbon Film Resistor
(x1) 9V Alkaline Battery Radioshack #23-853
(x1) Heavy-Duty 9V Snap Connectors Radioshack #270-324
(x1) Amber Super-bright LED Indicator Radioshack #55050630
(x1) White Super-bright LED Indicator Radioshack #55050633
(x1) 1/8" Stereo In-Line Audio Jack Radioshack #274-274
(x1) LM386 Low Voltage Audio Power Amplifier (8-Pin DIP) Radioshack 276-1731
(1x) 8 Pin Socket 276-1995 Radioshack 276-1995
Additional materials:
22 Gauge Wire Radioshack #278-1224
Solder Radioshack #64-013
drill
plywood
polyurethane finish
sand paper
hot glue
super glue
four wood screws
Heat Shrink Wrap Radioshack #278-1610
Electrical Tape Radioshack #64-2375
I've included fritzing breadboard diagrams (divided into a few parts) and schematics for this project as well as all firmware. You can find these documents throughout the body of this instructable or download them all in one zip file below.
all files.zip2 MB
Remove these ads by
Signing UpStep 1: Build enclosure
I wanted to sand off the scorched ends of the laser cut pieces so that the outside of the box had a consistent finish, so I also made a set of eps files with some extra length on the ends for sanding ("enclosure long").
I glued the pieces together with wood glue and cut a piece of acrylic for the front panel.
glitchbox enclosure.zip345 KB


























































Visit Our Store »
Go Pro Today »




Thanks for attempting to help me again. I'm not having any luck. One difference I have noticed is that my Arduino files end in .INO yours end in .PDE I am not sure if this has any relevance. It's something I noticed when I had to make changes to your code and save it. Another thing I'm not clear on is if I am initializing the Max patch correctly. I open it, plug in my USB, click on the X and go to the bottom and double click Noteout and choose either MaxRunTime 1 or 2. I've tried all the MIDI channels separately as well and I still get nothing. Your tip on printing CMD + Control + M is not working either. I get an error sound. I also don't see a Print button. I won't give up cuz I have my heart set on making this work, but it is pretty frustrating. Thanks for your patience.
Just to be clear...
I'm using Mac OS 10.8.3
Arduino R3 with ATMEGA 328P
USB Cable (Obvious, but I'm so frustrated I included it to be funny.)
2 breadboards...haven't built the pots and switches yet.
And all the parts you listed.
WHERE AM I GOING WRONG???
it's not command+control+M it's command or control + m (depends if you are using windows or mac)
the print button is grey and oval shaped, it says "print" it is near the top of the max patch
don;t worry about noteout for now, you should see the squares in the grid light up when you press the buttons.
let me know how it goes, send me the output from that print thing.
I just wanted to update you on where I'm at with this project. I've ordered the hi tact switches from geeetech.com. I was able to get 50 of them for $2.50. They have longer leads than the Radio Shack switches so i will be able to stick them in the breadboard. I'm hoping they arrive in the next couple of days. I was wondering if you were able to upload the code I amended and if it works with your Glitchbox? Thanks for your advice.
//by Amanda Ghassaei 2012
////todo
//led data
//audio storage
//send out audio
//trigger audio
//pot control
//switches
//timers
//turn off midi-send clear when mute
/***********************************************************************
if you want to add your own audio samples, compress them to 8 bit 8kHz using these instructions:
and paste the data into the memory below. the buttons are arranged as follows:
0 1 2
3 4 5
6 7 8
***********************************************************************/
//AUDIO STORAGE
boolean on1 = 0;
boolean on2 = 0;
boolean on3 = 0;
boolean on4 = 0;
boolean on5 = 0;
boolean on6 = 0;
boolean on7 = 0;
boolean on8 = 0;
boolean on9 = 0;
//variables for loops
byte i;
byte j;
byte k;
//position variables
byte x;
byte y;
//states
byte state = 0;
//position variables
byte xseq;
byte yseq;
//states
byte stateseq = 0;
//data storage for buttons
boolean button_current[9];//current state
boolean button_last[9];//last state
boolean button_state[9];//current debounced state
byte button_debounce_count[9];//debounce counter
boolean button_event[9];//event signal
byte buttonData;//used for reading portc
int kButtonUpDefaultDebounceCount = 12; // Used in button debouncing
/***********************************************************************
change the number following "#define steps" to set the number of steps in your sequencer.
default is 16
***********************************************************************/
//sequencer
#define steps 16
byte sequencer[steps][9];//32 step sequencer storage
//REC- turn sequencer on/off
boolean currentrec = 0;
boolean prevrec = 0;
boolean recdebounce = 0;
byte recdebouncecount;//debounce rec switch
//variables for loops
byte recdebouncesteps;
byte recdebouncei;
int seqTimer = 0;
boolean seqONcurrent = 1;//optional mute recorded sequences
boolean seqONprev = 1;
boolean seqON = 1;
byte seqONcounter;//debounce mute switch
boolean initonoff;
//BPM
int BPMvalcurrent;
int BPMvalstored;
void buttonInit() {
byte i;
for (i = 0; i <9; i++) {
button_current[i] = 0;
button_last[i] = 0;
button_state[i] = 0;
button_event[i] = 0;
}
PORTB = 0xFF;//set all pins high
}
//MUCH OF THIS BUTTON DEBOUNCING FUNCTION WAS COPIED FROM THE MONOME 40H FIRMWARE BY JOE LAKE AND BRIAN CRABTREE
// buttonCheck - checks the state of a given button.
void buttonCheck(byte index)
{
if ((button_current[index] ^ button_last[index]) && // if the current physical button state is different from the
(button_current[index] ^ button_state[index])) { // last physical button state AND the current debounced state
if (button_current[index]) { // if the current physical button state is depressed
button_event[index] = 1; // queue up a new button event immediately
button_state[index] = 1; // and set the debounced state to down.
}
else{
button_debounce_count[index] = kButtonUpDefaultDebounceCount;
} // otherwise the button was previously depressed and now
// has been released so we set our debounce counter.
}
else if ((button_current[index] ^ button_last[index]) == 0 && // if the current physical button state is the same as
(button_current[index] ^ button_state[index])) { // the last physical button state but the current physical
// button state is different from the current debounce
// state...
if (button_debounce_count[index] > 0 && --button_debounce_count[index] == 0) { // if the the debounce counter has
// been decremented to 0 (meaning the
// the button has been up for
// kButtonUpDefaultDebounceCount
// iterations///
button_event[index] = 1; // queue up a button state change event
if (button_current[index]){ // and toggle the buttons debounce state.
button_state[index] = 1;
}
else{
button_state[index] = 0;
}
}
}
}
void buttonpress() {
// digitalWrite(8,HIGH);
// digitalWrite(9,HIGH);
// digitalWrite(10,HIGH);
PORTB |= 0x07;//set pins 8, 9, 10 high
for (i=0; i<9; i++) {
button_last[i] = button_current[i];
}
//THE FOLLOWING CODE CHECKS THE STATES OF THE BUTTONS
digitalWrite(8,LOW);
button_current[2] = 1^digitalRead(A0);
button_current[1] = 1^digitalRead(A1);
button_current[0] = 1^digitalRead(A2);
digitalWrite(8,HIGH);
digitalWrite(9,LOW);
button_current[5] = 1^digitalRead(A0);
button_current[4] = 1^digitalRead(A1);
button_current[3] = 1^digitalRead(A2);
digitalWrite(9,HIGH);
digitalWrite(10,LOW);
button_current[8] = 1^digitalRead(A0);
button_current[7] = 1^digitalRead(A1);
button_current[6] = 1^digitalRead(A2);
digitalWrite(10, HIGH);
////SAME AS THE CODE ABOVE- WITHOUT ARDUINO LIBRARY COMMANDS
//for (j=0; j<3; j++){
// PORTB &= ~(1<//
//// buttonData = PORTC & 0x07;//read pins a0,a1,a2
//// for (k=0; k<3; k++){
//// button_current[3*j+k] = ((~buttonData & (1 << k)) >> k);//load data into button_current
//// }
//
// button_current[3] = 1^digitalRead(A0);
// button_current[4] = 1^digitalRead(A1);
// button_current[5] = 1^digitalRead(A2);
// PORTB |= (1<//}
for (i=0; i<9; i++) {
buttonCheck(i);
if (button_event[i]) {//if there has been a button event send serial data/data to sequencer
button_event[i] = 0;
x = i % 3;//x coordinate
y = i / 3;//y coordinate
state = button_state[i];//on/off
Serial.write(((x << 6) | (y << 4)) | (state<<3));
if (recdebounce){//if in rec mode
sequencer[seqTimer/2+seqTimer%2][i] = state+1;//store a 1 in sequencer for release and 2 for start, and quantize to nearest beat
}
}
}
}
void bpmRead(){
}
void checkSwitches(){
prevrec=currentrec;
if (digitalRead(A3)){
currentrec = 0;//
}
else{
currentrec = 1;
}
if ((currentrec ^ prevrec) && (currentrec ^ recdebounce)){//current diff than prev and debounce
if(currentrec){//currently 1
recdebounce=1;//debounce now set to 1
for (recdebouncesteps=0; recdebouncesteps for (recdebouncei=0; recdebouncei<9; recdebouncei++){
sequencer[recdebouncesteps][recdebouncei] = 0;//clear out sequencer for new pattern
Serial.write(1);//clear surrent midi
initonoff=digitalRead(A4);//set mute off
}
}
}
else {
recdebouncecount=12;//else set debounce counter to 12
}
}
else if ((currentrec == prevrec) && (currentrec ^ recdebounce)) {//if current prev and diff than debounce
if (recdebouncecount > 0 && --recdebouncecount == 0) {//decrease debounce counter and check to see if = 0
if (currentrec){//if debounce counter = 0 toggle debounced state
recdebounce = 1;
for (recdebouncesteps=0; recdebouncesteps for (recdebouncei=0; recdebouncei<9; recdebouncei++){
sequencer[recdebouncesteps][recdebouncei] = 0;//clear out sequencer for new pattern
Serial.write(1);//clear current midi
initonoff=digitalRead(A4);//set mute off
}
}
}
else{
recdebounce = 0;
}
}
}
seqONprev=seqONcurrent;
if (digitalRead(A4)){
seqONcurrent = 1;//
}
else{
seqONcurrent = 0;
}
if ((seqONcurrent ^ seqONprev) && (seqONcurrent ^ seqON)){//current diff than prev and debounce
if(seqONcurrent){//currently 1
seqON=1;//debounce now set to 1
Serial.write(1);//end current MIDI
}
else {
seqONcounter=12;//else set debounce counter to 12
}
}
else if ((seqONcurrent == seqONprev) && (seqONcurrent ^ seqON)) {//if current prev and diff than debounce
if (seqONcounter > 0 && --seqONcounter == 0) {//decrease debounce counter and check to see if = 0
Serial.write(1);//end current MIDI
if (seqONcurrent){//if debounce counter = 0 toggle debounced state
seqON = 1;
}
else{
seqON = 0;
}
}
}
}
void checkBPM(){
BPMvalcurrent=analogRead(A5);
if (abs(BPMvalcurrent-BPMvalstored)>8){//if change exceeds noise tolerance
BPMvalstored = BPMvalcurrent;
OCR1A = 31250/(BPMvalstored/100); // compare match register 16MHz/256/2Hz
}
}
ISR(TIMER1_COMPA_vect){
if (seqTimer==2*steps-1){
seqTimer=0;
}
else{
seqTimer+=1;//increase seqTimer by 1
}
if (seqON==initonoff){//if mute is off
if (seqTimer%2==0){//every other tick
PORTB&=B11100111;//turn off LEDs
//Serial.write(1,);//clear out midi from last time step
for (byte iseq=0; iseq<9; iseq++) {
stateseq = sequencer[seqTimer/2][iseq];
xseq = iseq % 3;//x coordinate
yseq = iseq / 3;//y coordinate
if ((stateseq==1)|(stateseq==2)){
Serial.write(((xseq << 6) | (yseq << 4)));//byte [xxyy(off)---]//clear out midi
Serial.write(((xseq << 6) | (yseq << 4)) | ((stateseq-1) << 3));//byte [xxyy(on/off)---]
}
}
if (seqTimer%(steps/2) ==0) {//turn led on every forth tick
if (recdebounce){
PORTB|=B00001000;//turn on amber LED
}
else{
PORTB|=B00010000;//turn on white LED
}
}
}
}
else{
if (seqTimer%2==0){//every other tick
PORTB&=B11100111;//turn off LEDs
}
if (seqTimer%(steps/2) ==0) {//turn led on every forth tick
if (recdebounce){
PORTB|=B00001000;//turn on amber LED
}
else{
PORTB|=B00010000;//turn on white LED
}
}
}
}
void setup() {
//button data out on pins 8, 9, 10
DDRB = 0xFF;
//button data in on pins A0, A1, A2
DDRC = 0x00;
BPMvalstored = analogRead(A5);
// //SETUP TIMER2 FOR SEQUENCER
cli();//stop interrupts
// TCNT2=0x00;
// OCR2A = 250; // 1 ms @ Fosc = 16 MHz
// TCCR2A=0x02; // WGM: No wave generation
// TCCR2B=0x04; // START Timer, prescaler = 64
// TIMSK2 = (1 << TOIE2); // Enable interrupt when Timer reaches OCRA
// set up Timer 2
// Timer 2 - gives us our 1 mS counting interval
// 16 MHz clock (62.5 nS per tick) - prescaled by 128
// counter increments every 8 uS.
// So we count 125 of them, giving exactly 1000 uS (1 mS)
// TCCR2A = 0; // stop timer 2
// TCCR2B = 0;
// TCNT2 = 0; // reset counter
//
// OCR2A = 124; // count up to 125 (zero relative!!!!)
// TCCR2A = _BV (WGM21) ; // CTC mode
// TCCR2B = _BV (CS20) | _BV (CS22) ; // start Timer with a prescaler of 128
// TIMSK2 = _BV (OCIE2A); // enable Timer2 Interrupt (ie. every 1 mS)
//
// TCCR2A = 0;
// TCCR2B = 0;
// TCNT2 = 0;
//
// OCR2A = 255; // compare match register 16MHz/256/2Hz
// TCCR2B |= (1 << WGM21); // CTC mode
// TCCR2B |= (1 << CS20); // 256 prescaler
// TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 31250/(BPMvalstored/100); // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei();//allow interrupts
//initialize mute switch so that it allows playback on startup
initonoff=digitalRead(A4);
PORTB = 0x07;//set pins 8, 9, 10 high, 11, 12 low
Serial.begin(57600);//not initializing properly when unplugged and replugged
buttonInit();
Serial.write(1);//clear message
}
void loop() {
buttonpress();
checkBPM();
checkSwitches();
checkBPM();
}
Happy Monday! Sorry to bother you again. I am still having trouble testing the button schematic. I amended the code and got it to upload ok, but nothing is happening when I press the buttons. Can I send you my code to make sure I amended it ok?
How do I amend this in your code?
On the Arduino end of things, I uploaded your sketch and clicked on the Monitor. I get gibberish. I even made sure the baud was set to 57600. Feeling not sooo smart. Hahaha. Please help. Thanks.
I am trying to prototype your project. I would like to test the buttons from the Fritzing sketch. You suggested I run MaxRunTime. I downloaded it, got the MIDI firmware up, plugged in my Arduino attached to my breadboard. I clicked the X to start the metronome and right clicked on noteout to set the MIDI out...I attempted both from MaxRunTime 1 and 2. No luck. Is there a step I am missing? Thanks for your help.
Have you been able to use a mini sd card for storage of longer samples?
Have you been able to use a mini sd card for storage of longer samples?
How can I overcome this.Maybe I have the smaller processor on my board?
avrdude: stk500_paged_write(): (a) protocol error, expect=0x14, resp=0x64
avrdude: stk500_cmd(): programmer is out of sync
any ideas? i'm new to arduino