loading
Picture of Sugarcube MIDI Controller
IMG_0286 copy copy.jpg
IMG_0279 copy copy.jpg
IMG_0273 copy copy copy.jpg

This project is a portable, Arduino-powered, grid-based MIDI controller that boots up into a variety of apps to do lots of things with sound. It has 16 backlit buttons, used as both inputs and outputs to give the controller some visual feedback. 2 potentiometers give analog control, depending on the app the pots are assigned to tempo, MIDI velocity, pitch, and scrolling (making the avaible grid space larger than 4x4). An x/y accelerometer and an x/y gyroscope add some playful, gestural control to the device; most of the apps implement a "shake to erase" control and several respond to tilt in various ways. It boots up into 7 different apps (described below), though it has the potential to boot up into 16 total. This device is primarily a MIDI controller, but I've also written an app that allows you to pull the button and analog data into MaxMSP and to control audio.

This controller was inspired by both the monome and tenori-on. When I was in college, I built a large touchscreen display, based on the Arduinome monome-Arduino clone schematics and code, that worked with all the open source monome applications written in MaxMSP. There are a ton of people building their own monome-type devices using these buttons from Sparkfun and the Arduinome code, as well as a few variations on the theme. With this project, I was interested in making a device that was a little more self-contained and relatively cheap to make (lots of buttons = lots of $). In keeping more with the concept of the tenori-on, this controller does all its app processing itself, it does not rely on a computer to process button presses/analog controls into MIDI. This means you can plug it directly into a synth or any device that understands MIDI and you're good to go, no computer required. It runs off a beefy LiPo battery that keeps it running for days on a charge, so it's fairly portable as well. In keeping with the monome side of things, it's totally open source and can be adapted to your particular audio setup/needs. All the Arduino code is up on github (click the cloud-shaped button to download), along with a MaxMSP patch that decodes data from the controller into something usable in Max.

An overview of the apps I've written so far:

Pixel Tilt - One pixel moves across a 2D keyboard with tilt, triggering MIDI as it moves. Control velocity and basenote with pots.

Flin - Music Box app based on monome. Speed and velocity of notes controlled by y tilt. Paging across 16 "lanes" with pot. Shake to erase.

Serial Communication with MaxMSP - Pull data from buttons and analog controls into MaxMSP and use Max to send LED states. Supports 5 bit analog controls for x/y accelerometer and 2 pots. This is great if you want to run audio processing applications with the controller. Download SerialDemo app (SerialDemo.maxpat, included with the Arduino files, click the cloud-shaped button here) to parse data in Max. Beat slicer (shown above) app is included with the Arduino files as well.

Arpeggiator - Plays a two, three, or four note arpeggio, similar to this app I wrote for monome. One pot controls the speed of the arpeggio, another controls velocity. Notes within the arpeggio can be shifted up or down by one semitone via button controls. The whole arpeggio is transposed via x tilt. Press the leftmost note in the arpeggio to play the notes in ascending order, press the rightmost note in the arpeggio to play the notes in descending order, and press a middle note in the arpeggio to play the notes in a random order. Shake to erase.

Boiing - Bouncing pixels that generate polyrhythms, based on this tenori-on app. Bounce direction based on y tilt. Speed and MIDI velocity (loudness) controlled by pots. Shake to erase.

Step Sequencer - Four note 16 step sequencer. Pots control tempo and paging across sequence. Shake to erase.

MIDI Keyboard - Simple MIDI keypad. Control velocity and basenote with pots, pitchbend with x tilt.

Parts List:

SPARKFUN:
(1x) Button Pad 4x4 - LED Compatible Sparkfun COM-07835
(1x) Button Pad 4x4 - Breakout PCB Sparkfun COM-08033
(1x) Arduino Uno Sparkfun DEV-11021
(1x) Accelerometer/Gyro 5 Degrees of Freedom Sparkfun SEN-11072
I put a 3-axis accelerometer and 2 axis gyroscope in this controller to give it some gestural control, but so far I haven't actually used the gyro in any apps, and I've only got the x and y axis of the accelerometer wired up. That means you could sub in a simpler/cheaper part like this.

DIGIKEY:
(16x) White 5mm LED (3mm is fine too) Digikey C513A-WSN-CV0Y0151-ND
(2x) 74HC595 shift register Digikey 296-1600-5-ND
(1x) 74HC165 shift register Digikey 296-8251-5-ND
(3x) 16 pin IC socket Digikey A100206-ND
(16x) 1N4148 Diode Digikey 1N4148FS-ND
(4x) current limiting resistors (value will depend on LEDs, sample calculation included in step 5)
(4x) 10kOhm 1/4watt resistors Digikey CF14JT10K0CT-ND
(1x) 220Ohm 1/4watt resistor Digikey CF14JT220RCT-ND
(1x) 5-Pin MIDI Jack Digikey CP-2350-ND (optional - explained in step 27)
(1x) USB type B female jack Digikey 732-2734-ND (optional - explained in step 27)
(2x) 10kOhm linear taper potentiometer Digikey 987-1308-ND

JAMECO:
(1x) 16 conductor ribbon cable Jameco 28RC16-10VP
(1x) 16 pin right angle connector Jameco 746285-3
(6x) male header pins Jameco 103393

RADIOSHACK:
(1x) Midi Cable Radioshack 42-2149 (optional - explained in step 27)
(1x) Size N Panel-Mount Coaxial DC Power Jack with switch Radioshack 274-1576
(1x) Size N Coaxial DC Power Plug Radioshack 274-1573
(1x) SPST Toggle Switch Radioshack 275-634

AMAZON:
(1x) Li-Ion 7.4V Tenergy 2200mAh Rechargeable Battery module with PCB Amazon
(1x) Tenergy Universal Smart Charger for Li-Ion/Polymer battery Pack (3.7V-14.8V 1-4 cells) Amazon
(1x) MIDI to USB cable Amazon (optional - explained in step 27)

NEWARK:
(2x) Aluminum knobs Newark 74M6717

ADDITIONAL MATERIALS:
22 Gauge Wire, various colors Jameco #9313-0-R
electrical tape Radioshack 64-2373
wire cutters
wire strippers
solder
wood/acrylic/project enclosure (I used this 6"x6"x2" bamboo box The Container Store)
glue/epoxy
double sided foam tape Amazon

 
Remove these adsRemove these ads by Signing Up

Step 1: Schematic and Overview

All schematics for this project are shown above. Detailed overviews of the 74HC595, 74HC165, and power connections are given later in this Instructable. All the Arduino pin connections are listed below:

Analog

0 - Gyroscope Y (Y4.5)
1 - Potentiometer 1
2 - Gyroscope X (X4.5)
3 - Accelerometer Y (YAcc)
4 - Accelerometer X (XAcc)
5 - Potentiometer 2

Digital

0 - serial in - this must remain unconnected
1 - serial out - this is hooked up to the MIDI output
2 - 74HC165 data pin (Q7)
3 - 74HC165 clock pin (CP)
4 - 74HC165 latch pin (PL)
5 - 74HC595 clock pin (SH_CP)
6 - 74HC595 latch pin (ST_CP)
7 - 74HC595 data pin (DS)

no connections to digital pins 8-13

Step 2: Solder LEDs to Sparkfun PCB

Thread the leads of 16 LEDs (5mm or 3mm are fine, I used 5mm) through LED holes in the Sparkfun PCB. These boards are compatible with 4-lead RGB LEDs, so there are four available holes on each button pad. You can use the two center holes for single color LEDs (see figure 3). Be sure that the flat edge of the LED (the cathode) lines up with the flat marking on the PCB.

Solder the LED leads and cut away the excess wire.

Step 3: Solder Diodes to Sparkfun PCB

Solder 16 diodes to Sparkfun PCB. Be sure to line up black marking on diode (cathode) with the stripe on the PCB.

Step 4: Ribbon Cable

Picture of Ribbon Cable
IMG_3425 copy.jpg
IMG_3428 copy.jpg

Cut about 1ft of 16 conductor ribbon cable. Separate and strip the ends of all 16 wires on one side and solder to Sparkfun PCB. The following list gives all the colored conductors in order with the name of the PCB hole they should be soldered to, if you do this correctly none of the wires should cross. Note that since I'm only using a single color LED, I'll wire up only the "blue" anode.

Connections:

one side of ribbon cable
Brown SWT-GND1
Red LED-GND1
Orange SWT-GND2
Yellow LED-GND2
Green SWT-GND3
Blue LED-GND3
Purple SWT-GND4
Grey LED-GND4
White BLUE4
Black SWITCH4
Brown BLUE3
Red SWITCH3
Orange BLUE2
Yellow SWITCH2
Green BLUE1
Blue SWITCH1
other side of ribbon cable

Step 5: Clamp Socket

Picture of Clamp Socket
IMG_3432 copy.jpg
IMG_3433 copy.jpg
IMG_3434 copy.jpg
IMG_3436 copy.jpg

Use a bench vice to clamp the16 pin socket on the ribbon cable. If you do not have a bench vice do not use pliers do this, you will clamp the socket on sideways and mess up the connections. You're better off using a hammer to tap the clamp shut, just make sure you are always applying pressure evenly across the socket.

Be sure the clamp the socket on the ribbon cable in the same orientation indicated in the images above.

Step 6: Multiplexing with Arduino and 74HC595

Picture of Multiplexing with Arduino and 74HC595
IMG_5725.jpg
IMG_5726.jpg
Screen Shot 2013-09-11 at 5.56.06 PM.png

Two 74HC595s (wired in parallel) will be driving all the LEDs in the project as well as providing power to all of the buttons. The 74HC595 is an 8 bit serial in parallel out shift register. I've written a detailed tutorial about multiplexing with the 74HC595, and you can find more info about this chip on its datasheet. Please note that the 74HC595 drawn in the schematic is not a pin diagram, I have rearranged the order of the pins to make the circuit diagram more clear. The pin diagram for the chip is shown in fig 4.

The 74HC595 has the following pins (the technical name may be one of several things depending on which data sheet you are reading):

Position Common Name Technical Name

1 parallel output 2 QB or Q1
2 parallel output 3 QC or Q2
3 parallel output 4 QD or Q3
4 parallel output 5 QE or Q4
5 parallel output 6 QF or Q5
6 parallel output 7 QG or Q6
7 parallel output 8 QH or Q7
8 ground GND
9 serial data output QH' or Q7' or Q7S
10 master reset (active low) MR(with a line on top) or SRCLR(with a line on top)
11 clock pin SH_CP or SRCLK
12 latch pin ST_CP or RCLK
13 output enable (active low) OE(with a line on top)
14 data pin DS or SER
15 parallel output 1 QA or Q0
16 5 volts supply VCC

The connections between the 74HC595 and the sparkfun board are shown in the schematic and repeated below:

74HC595 Sparkfun Breakout Board

Q0 BLUE 4 and SWITCH 4
Q1 BLUE 3 and SWITCH 3
Q2 BLUE 2 and SWITCH 2
Q3 BLUE 1 and SWITCH 1
Q4 LED GND 4 (via current limiting resistor)
Q5 LED GND 3 (via current limiting resistor)
Q6 LED GND 2 (via current limiting resistor)
Q7 LED GND 1 (via current limiting resistor)

The remaining pins have the following connections to the Arduino (also shown in schematic):

74HC595 Arduino

Vcc 5V
GND GND
DS Digital Pin 7
OE(line on top) GND
ST_CP Digital Pin 6
SH_CP Digital Pin 5
MR(line on top) 5V
Q7' no connection

Step 7: Header Pins

Picture of Header Pins
IMG_3517 copy.jpg

Solder two rows of eight header pins to the protoboard. This is where the ribbon cable socket will attach to the board.

Step 8: Current Limiting Resistors

Picture of Current Limiting Resistors
IMG_3521 copy.jpg
IMG_5722.jpg

The 74HC595 will be driving the LEDs in the sparkfun board. However, this chip only outputs 0 or 5V and it can output as much as 70mA. This means we must use current limiting resistors to prevent damaging the LEDs.

From the specs of the LEDs I used:
max forward current: 30mA
forward voltage: 3.2V

Calculate the resistance needed to achieve these max ratings from V = IR:
resistance = (5V-3.2V) / (0.03A)
= 60 ohms

I used 68 ohm resistors so that I was not running at the absolute maximum, but also ensuring that I wouldn't lose too much brightness. (I made a mistake a grabbed the 100KOhm resistors when I made this project, I fixed it later, but the stripes of 100Ohm resistors should be blue, grey, black, gold, ignore the colors in the images).

These are the sample calculations for the specific LEDs I used, you'll need to do you own calculations based on the specs of your LEDs. If you are unsure of what to do, use 220ohm or higher resistors; using too much resistance will make the LEDs less bright, but they will not be damaged.

Solder four resistors to the protoboard as shown in the images. Connect the leads of the resistors to their adjacent header pins with solder (figure 2).

Step 9: 74HC595 socket

Picture of 74HC595 socket
IMG_3532 copy.jpg
IMG_5722.jpg

Solder an 8-pin socket to the protoboard as shown in the images above.

Step 10: Connections to LEDs

Picture of Connections to LEDs
IMG_3534 copy.jpg
IMG_3536 copy.jpg
IMG_3535 copy.jpg
IMG_5722.jpg
Screen Shot 2013-09-11 at 5.56.06 PM.png

As shown in figure 6, the output pins (Q0-Q7) are located on pins 1-7 and 15. This image was taken from the datasheet of the 74HC595. Connect the resistors to pins 4-7 with jumper wires as shown in figures 1 and 2. Connect pins 1-3 and 15 to the header pins according to the schematic (note the wiring in the image is incorrect, but the schematic is correct). The pins connections to the 74HC595 should be as follows:

Pin 15 - Blue 4
Pin 1 - Blue 3
Pin 2 - Blue 2
Pin 3 - Blue 1
Pin 4 - LED GND 4
Pin 5 - LED GND 3
Pin 6 - LED GND 2
Pin 7 - LED GND 1

Be sure to get these pin connections correct- do this part slowly and refer to the schematic often.

Make sure to electrically join all these connections with solder on the underside of the board (figs 2 and 4)

Step 11: Add Second 74HC595: Part 1

Picture of Add Second 74HC595: Part 1
IMG_5722.jpg
IMG_3821 copy.jpg

Each 74HC595 can only source 70mA at a time for all its pins. With the 100ohm current limiting resistors, if all 4 LEDs in a row are on at the same time (with multiplexing this is the max number of LEDs that can possibly be on at the same time), they will each draw about 18mA which puts the current requirements slightly above the 70mA maximum rating. I'll be drawing additional current from pins Q0-Q7 to multiplex the buttons (in later steps). An easy solution to this problem is to add another 74HC595 to the circuit, it will be wired parallel to the current 74HC595 (see schematic). This will give us additional 70mA to draw from on all 8 pins.

Add another 16 pin socket to the protoboard as shown in the images.

Step 12: Add Second 74HC595: Part 2

Picture of Add Second 74HC595: Part 2
IMG_3823 copy.jpg
IMG_3824 copy.jpg
IMG_3825 copy.jpg
IMG_5722.jpg
Screen Shot 2013-09-11 at 5.56.06 PM.png

Wire pins 1-7 and 15 of the sockets to each other (see note on schematic). These pins correspond to all eight outputs of the 74HC595s.

Step 13: Add Second 74HC595: Part 3

Picture of Add Second 74HC595: Part 3
IMG_3827 copy.jpg
IMG_5722.jpg

Connect pin 8 (ground) and pin 16 (5V) of the sockets together (see image note on schematic).

Step 14: Add Second 74HC595: Part 4

Picture of Add Second 74HC595: Part 4
IMG_3829 copy.jpg
IMG_5722.jpg
Screen Shot 2013-09-11 at 5.56.06 PM.png

Connect pins 11, 12, and 14 of the sockets to each other. These correspond to the clock, latch, and data pins of the 74HC595s.

Step 15: Add Second 74HC595: Part 4

Picture of Add Second 74HC595: Part 4
IMG_3831 copy.jpg
IMG_5722.jpg
Screen Shot 2013-09-11 at 5.56.06 PM.png

Wire pin 10 to 5V (pin 16) and pin 13 to ground (pin 8). Pin 10 (MR) should be high and pin 13 (OE) should be low in order to send data to the output pins (Q0-Q7).

Step 16: Header Pins

Picture of Header Pins
FTFRUL0H337JN8Z.LARGE.jpg
F299I7UH337JN8Y.LARGE.jpg
IMG_3851 copy.jpg

Solder header pins to the perfboard so that an Arduino Uno can snap fit onto it. Be careful of the odd pin spacing between digital pins 7 and 8, I've designed this project so that connecting to pin 8-13 is not necessary, it's probably best to omit header pins for Arduino pins 0-13 so that things snap together easier (see image note).

Step 17: Connect 74HC595 to Arduino

Picture of Connect 74HC595 to Arduino
5231e44bec8d8367d400006f.jpg
IMG_5722.jpg
Screen Shot 2013-09-11 at 5.56.06 PM.png

Connect three 74HC595 data pins to Arduino digital pins 5, 6, and 7. Connect ground and 5V to Arduino corresponding power pins.

Pin connections:

74HC595 Arduino

data pin (pin 14) digital pin 7
latch pin (pin 12) digital pin 6
clock pin (pin 11) digital pin 5

Step 18: Test LEDs

Picture of Test LEDs

Upload the code below onto the Arduino and test to see if LEDs are wired correctly. Insert two 74HC595s into the empty sockets, plug the button pcb into its socket, and connect the arduino to the protoboard (fig 1). You should see each LED light up one at a time, this loop will continue repeating forever (see video below). If this is not working, double check the connections in the previous steps and check all your connections for continuity. Do not continue onto the next steps until you get the LEDs working.

For more information on the 74HC595 and shiftOut, see fig 2, the datasheet, and the arduino reference page.
//LED TEST w/ 74HC595
//by Amanda Ghassaei 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
*/

//this firmware lights up each led one by one

//pin connections
int latchPin = 6;
int clockPin = 5;
int dataPin = 7;

//looping variables
byte i;
byte j;

//storage variable
byte dataToSend;

void setup() {
  pinMode(latchPin,OUTPUT);
  pinMode(clockPin,OUTPUT);
  pinMode(dataPin,OUTPUT);
}

void loop() {
  for (i=0;i<4;i++){
    for (j=0;j<4;j++){
      
      dataToSend = (1 << (i+4)) | (15 & ~(1 << j));//preprare byte to send to 74HC595
      
      // setlatch pin low so the LEDs don't change while sending in bits
      digitalWrite(latchPin, LOW);
      // shift out the bits at dataToSend
      shiftOut(dataPin, clockPin, LSBFIRST, dataToSend);
      //set latch pin high so the LEDs will light up
      digitalWrite(latchPin, HIGH);
      
      delay(500);//wait
    }
  }
}

Step 19: Multiplexing with Arduino and 74HC165

Picture of Multiplexing with Arduino and 74HC165
IMG_5722.jpg
IMG_5726.jpg
Screen Shot 2013-09-11 at 6.36.13 PM.png

The 74HC595 can only do parallel output, so I used a 74HC165 to measure the state of the buttons via 4 current limiting resistors and send this information to the Arduino. More info about the chip can be found on its datasheet. Note in fig 2 that the 595 chips from the previous steps will be providing power to the buttons (as they are doing for the LEDs).

The 74HC165 has the following pins (the technical name may slightly different depending on which data sheet you are reading):

Position / Common Name / Technical Name

1 latch pin (active low) PL(with a line on top)
2 clock pin CP
3 parallel input 4 D4
4 parallel input 5 D5
5 parallel input 6 D6
6 parallel input 7 D7
7 inverse serial output Q7(with a line on top)
8 ground GND
9 serial output (data pin) Q7
10 serial input DS
11 parallel input 0 D0
12 parallel input 1 D1
13 parallel input 2 D2
14 parallel input 3 D3
15 clock enable input (active low) CE(with a line on top)
16 5 volts supply VCC

The connections between the 74HC165 and the Sparkfun board are shown in the schematic and repeated below:

74HC165 -> Sparkfun Breakout Board

D0 SWITCH GND 4
D1 SWITCH GND 3
D2 SWITCH GND 2
D3 SWITCH GND 1

(note that the 165 pins should also have a connection through a resistor to ground - see schematic)

The remaining pins have the following connections to the Arduino (also shown in schematic):

74HC165 -> Arduino

Vcc 5V
GND GND
CE(line on top) GND
DS GND
Q7 Digital Pin 2
Q7(line on top) no connection
PL(line on top) Digital Pin 4
CP Digital Pin 3

Step 20: 74HC165: Part 1

Picture of 74HC165: Part 1
schematic.jpg
Screen Shot 2013-09-11 at 6.36.13 PM.png

Solder a third 16 pin socket to the protoboard, this will be for the 74HC165. Connect 5V to pin 16 and ground to pin 8.

Step 21: 74HC165: Part 2 Pull Down Resistors

Picture of 74HC165: Part 2 Pull Down Resistors
IMG_5123 copy.jpg
IMG_5142 copy.jpg
schematic.jpg
IMG_5722.jpg
Screen Shot 2013-09-11 at 6.36.13 PM.png

I used resistors in series with the buttons to pull D0-D3 of the 165 chip down to ground while the buttons are not pressed - this is called a "pull down resistor". Solder four 10kOhm resistors to the pins adjacent to the header pins (see fig 1). Connect four wires from the 74HC165 inputs D0-3 (pins 11-14) to the space between the male header pins and the 10k resistors as indicated in fig 3 and in the schematic (also see yellow wires in fig 2). Drag solder between the header pins, the wires to the 165 chip, and the resistors to connect them (see fig 3). Connect the other side of all four resistors to each other and to Arduino ground (again see fig 3 and the schematic).

We'll be powering the buttons with the same supply that is powering the LEDs - the 595 chips. Drag solder between the header pins that connect to the LED-BLUE (1-4) on the sparkfun board to the header pins that connect to SWITCH (1-4) on the sparkfun board (see note on fig 3 and 5).

Step 22: 74HC165: Part 3

Picture of 74HC165: Part 3
53cfe71fd535cfefe70000f8.jpg
Screen Shot 2013-09-11 at 6.36.13 PM.png

Connect the data pins of the 74HC165 to the Arduino (brown wires)
Pin connections (also shown in schematic):

74HC165 Arduino

PL(line on top) (pin 1) digital pin D4
CP (pin 2) digital pin D3
Q7 (pin 9) digital pin D2

Step 23: 74HC165: Part 4

Picture of 74HC165: Part 4
IMG_5139 copy.jpg
schematic.jpg
Screen Shot 2013-09-11 at 6.36.13 PM.png

Connect ground to pins 15 (CE with line on top) and 10 (DS) of the 74HC165.

Step 24: Test Buttons

Picture of Test Buttons
IMG_5236 copy.jpg
Upload the following code onto the Arduino. If everything is wired correctly each button will light up while pressed. If you're noticing that some buttons are not as responsive try cleaning the conductive rings and the traces on the pcb with water and drying thoroughly, this solved some response problems for me.
//BUTTON TEST w/ 74HC595 and 74HC165
//by Amanda Ghassaei 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
*/

//this firmware will cause the buttons to light up momentarily while they are pressed.

//pin connections
int ledLatchPin = 6;
int ledClockPin = 5;
int ledDataPin = 7;
int buttonLatchPin = 4;
int buttonClockPin = 3;
int buttonDataPin = 2;

//looping variables
byte i;
byte j;
byte k;

//storage for led states, 4 bytes
byte ledData[] = {0, 0, 0, 0};
//storage for buttons, 4 bytes
byte buttonCurrent[] = {0,0,0,0};
byte buttonLast[] = {0,0,0,0};
byte buttonEvent[] = {0,0,0,0};
byte buttonState[] = {0,0,0,0};
//button debounce counter- 16 bytes
byte buttonDebounceCounter[4][4];


void setup() {
  DDRD = 0xFA;//set pins D7-D4 as output, D2 as input
}

// buttonCheck - checks the state of a given button.
//this buttoncheck function is largely copied from the monome 40h firmware by brian crabtree and joe lake
void buttonCheck(byte row, byte index)
{
  if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) &&   // if the current physical button state is different from the
  ((buttonCurrent[row] ^ buttonState[row]) & (1 << index))) {  // last physical button state AND the current debounced state

    if (buttonCurrent[row] & (1 << index)) {                      // if the current physical button state is depressed
      buttonEvent[row] = 1 << index;              // queue up a new button event immediately
      buttonState[row] |= (1 << index);                         // and set the debounced state to down.
  }
    else{
      buttonDebounceCounter[row][index] = 12;
    }  // otherwise the button was previously depressed and now
    // has been released so we set our debounce counter.
  }
  else if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) == 0 &&  // if the current physical button state is the same as
  (buttonCurrent[row] ^ buttonState[row]) & (1 << index)) {        // the last physical button state but the current physical
    // button state is different from the current debounce 
    // state...
    if (buttonDebounceCounter[row][index] > 0 && --buttonDebounceCounter[row][index] == 0) {  // if the the debounce counter has
      // been decremented to 0 (meaning the
      // the button has been up for 
      // kButtonUpDefaultDebounceCount 
      // iterations///

      buttonEvent[row] = 1 << index;    // queue up a button state change event

      if (buttonCurrent[row] & (1 << index)){          // and toggle the buttons debounce state.
        buttonState[row] |= (1 << index);
      }
      else{
        buttonState[row] &= ~(1 << index);
      }
    }
  }
}


void shift(){
  
  for (i=0;i<4;i++){
    
    buttonLast[i] = buttonCurrent[i];
    
    byte dataToSend = (1 << (i+4)) | (15 & ~ledData[i]);
      
    // set latch pin low so the LEDs don't change while sending in bits
    digitalWrite(ledLatchPin, LOW);
    // shift out the bits of dataToSend
    shiftOut(ledDataPin, ledClockPin, LSBFIRST, dataToSend);  
    //set latch pin high so the LEDs will receive new data
    digitalWrite(ledLatchPin, HIGH);
      
    //once one row has been set high, receive data from buttons
    //set latch pin high
    digitalWrite(buttonLatchPin, HIGH);
    //shift in data
    buttonCurrent[i] = shiftIn(buttonDataPin, buttonClockPin, LSBFIRST) >> 3;
    //latchpin low
    digitalWrite(buttonLatchPin, LOW);
    
    for (k=0;k<4;k++){
      buttonCheck(i,k);
    }
  }
}

void updateLEDs(){ //update the leds to reflect hte state of the buttons
  for (j=0;j<4;j++){
    ledData[j] = buttonState[j];
  }
}

void loop() {
  shift();
  updateLEDs();
}

Step 25: Serial Communication

Picture of Serial Communication

At this point in the project I got a little impatient and wanted to start making some sounds, so I added some things to the firmware to make the Arduino send and receive information serially. I've posted the code below. I used a timer interrupt to keep the Arduino responsive to incoming serial messages, you can read a little more about how that works here. (if you're going to test this code, use the app attached, the newer version of the beat slicer app on github is a little different).

//BUTTON TEST w/ 74HC595 and 74HC165 and serial communication
//by Amanda Ghassaei
//June 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
*/

//this firmware will send data back and forth with the maxmsp patch "beat slicer"

//pin connections
int ledLatchPin = 6;
int ledClockPin = 5;
int ledDataPin = 7;
int buttonLatchPin = 4;
int buttonClockPin = 3;
int buttonDataPin = 2;

//looping variables
byte i;
byte j;
byte k;
byte ledByte;

//storage for led states, 4 bytes
byte ledData[] = {0, 0, 0, 0};
//storage for buttons, 4 bytes
byte buttonCurrent[] = {0,0,0,0};
byte buttonLast[] = {0,0,0,0};
byte buttonEvent[] = {0,0,0,0};
byte buttonState[] = {0,0,0,0};
//button debounce counter- 16 bytes
byte buttonDebounceCounter[4][4];


void setup() {
  DDRD = 0xFA;//set pins D7-D4 as output, D2 as input
  
  Serial.begin(57600);
  
  cli();//stop interrupts

  //set timer2 interrupt every 128us
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 7.8khz increments
  OCR2A = 255;// = (16*10^6) / (7812.5*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS11 bit for 8 prescaler
  TCCR2B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);
  
  sei();//allow interrupts
  
}

// buttonCheck - checks the state of a given button.
//this buttoncheck function is largely copied from the monome 40h firmware by brian crabtree and joe lake
void buttonCheck(byte row, byte index)
{
  if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) &&   // if the current physical button state is different from the
  ((buttonCurrent[row] ^ buttonState[row]) & (1 << index))) {  // last physical button state AND the current debounced state

    if (buttonCurrent[row] & (1 << index)) {                      // if the current physical button state is depressed
      buttonEvent[row] = 1 << index;              // queue up a new button event immediately
      buttonState[row] |= (1 << index);                         // and set the debounced state to down.
  }
    else{
      buttonDebounceCounter[row][index] = 12;
    }  // otherwise the button was previously depressed and now
    // has been released so we set our debounce counter.
  }
  else if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) == 0 &&  // if the current physical button state is the same as
  (buttonCurrent[row] ^ buttonState[row]) & (1 << index)) {        // the last physical button state but the current physical
    // button state is different from the current debounce 
    // state...
    if (buttonDebounceCounter[row][index] > 0 && --buttonDebounceCounter[row][index] == 0) {  // if the the debounce counter has
      // been decremented to 0 (meaning the
      // the button has been up for 
      // kButtonUpDefaultDebounceCount 
      // iterations///

      buttonEvent[row] = 1 << index;    // queue up a button state change event

      if (buttonCurrent[row] & (1 << index)){          // and toggle the buttons debounce state.
        buttonState[row] |= (1 << index);
      }
      else{
        buttonState[row] &= ~(1 << index);
      }
    }
  }
}


void shift(){
  
  for (i=0;i<4;i++){
    
    buttonLast[i] = buttonCurrent[i];
    
    byte dataToSend = (1 << (i+4)) | (15 & ~ledData[i]);
      
    // set latch pin low so the LEDs don't change while sending in bits
    digitalWrite(ledLatchPin, LOW);
    // shift out the bits of dataToSend
    shiftOut(ledDataPin, ledClockPin, LSBFIRST, dataToSend);  
    //set latch pin high so the LEDs will receive new data
    digitalWrite(ledLatchPin, HIGH);
      
    //once one row has been set high, receive data from buttons
    //set latch pin high
    digitalWrite(buttonLatchPin, HIGH);
    //shift in data
    buttonCurrent[i] = shiftIn(buttonDataPin, buttonClockPin, LSBFIRST) >> 3;
    //latchpin low
    digitalWrite(buttonLatchPin, LOW);
    
    for (k=0;k<4;k++){
      buttonCheck(i,k);
      if (buttonEvent[i]<> 1) & 3;
      byte ledx = (ledByte >> 3) & 3;
      if (ledstate){
        ledData[ledy] |= 8 >> ledx;
      }
      else{
        ledData[ledy] &= ~ (8 >> ledx);
      }
    }//end if serial available
  }//end do
 while (Serial.available() > 8);
}    


void loop() {
  shift();//updates leds and receives data from buttons
}

I sent this serial data to an audio processing application I wrote in MaxMSP. You can download this application below (called beat slicer) and open it with MaxMSP or MaxRuntime (free version) here. I'm running Max 5, I assume it will work on Max 6 as well. It will prompt you to select an audio file (wav, mp3, aiff). Then you can manipulate this audio file using the button grid as shown in the video below:

Step 26: Battery

One of my main objectives for this project was to make something portable, so the next step is to add portable power. I used a rechargeable Li-Po battery to minimize waste and provide enough power for hours of use. Additionally, I wanted a Li-Po battery that only had two leads coming out of it so that I could charge it using a regular barrel plug.

Here are the parts for the power setup, taken from the parts list on the first page:

Li-Ion 7.4V Tenergy 2200mAh Rechargeable Battery module with PCB Amazon
Tenergy Universal Smart Charger for Li-Ion/Polymer battery Pack (3.7V-14.8V 1-4 cells) Amazon
Size N Panel-Mount Coaxial DC Power Jack Radioshack 274-1576
Size N Coaxial DC Power Plug Radioshack 274-1573
SPST Toggle Switch Radioshack 275-634

Cut and strip the two leads from the battery (do not let them short out). Make connections between the battery, plug, switch and Arduino according to the schematic above. I like to always attach ground to the outside part of the coaxial jack, but you can wire it however you like (just make sure your wiring of the charger is consistent!).

Cut and strip the two leads from the charger. Solder the n type barrel plug to these leads as shown in the image above. Make sure that the polarity of your charger's barrel plug matches the polarity of the jack. Again, I've chosen to connect ground to the outside part of the coaxial jack/plug in the images above.

Now the switch acts as an on/off switch to the Arduino and the battery can be charged via the barrel plug. Charging Li-Po batteries is a somewhat complicated procedure that involves balancing the cells of the battery, I'm not sure if hooking up the Arduino in parallel with the battery during charging will interfere with this process. Just to be safe, I'm always sure to switch the power switch off during charging, thereby removing the Arduino from the circuit.

Note- be careful when using Li-Po batteries, improper use can result in fire. Be careful not to short circuit the battery and always use the proper charger.

Step 27: Midi Out

This instrument is primarily a MIDI device, so we need to build a MIDI out. There are two ways to do this (and over the course of this project I did one and then switched to the other):

output MIDI via a 5 pin DIN connector (see fig 1)
output MIDI via USB (this is what I eventually settled on)

Either of these options is fine, I chose USB because I didn't want to have to carry a special MIDI to USB cable all the time. If you have a lot of synthesizers that receive a 5 pin MIDI input, it might be more convenient for you to use the 5 pin jack (it's also a little easier). I'll go through both processes below:

5 pin connection:

Solder a 220ohm resistor to pin 4 of the MIDI jack and connect to Arduino 5V. Solder a wire between MIDI pin 2 and ground. Solder a wire between MIDI pin 5 and digital pin 1 (TX).

MIDI over USB:

MIDI over USB is a little tricky. Ideally we'd be able to send MIDI out the USB port already connected to the Arduino, but this turns out to be more trouble than it's worth in my opinion. You can read a little bit about various solutions here. Instead, I found a really great tutorial that explains how you can take apart a cheap MIDI to USB cable, solder new connections to it, and tuck it inside your project enclosure with your Arduino, to create a secondary MIDI-USB output. The process is explained really well on the Shiftmore blog, but the MIDI to USB cable I received from amazon was a little different, so I'll describe the process again here.

Remove the plastic casing from the MIDI to USB cable and unsolder the connections to the cables on either end (fig 8). The USB connections are shown here, make the following connections:

5V +
DP D+
DM D-
VSS -

As you can see in figs 9 and 10, I used a pieced of perf board to make the connections to the USB jack. On the other side of the MIDI to USB board, make the following connections to the Ardunio:

IN- Digital Pin 1 (TX)
GND Arduino Ground

Testing it out:

Load the firmware below onto the Arduino (also in attached file), it will turn the keypad into a simple MIDI device: pressing each of the buttons will cause the button to light up and trigger a MIDI note. Disconnect the Arduino's serial connection and connect the MIDI output to a MIDI instrument or your computer to hear the MIDI notes. You should also see the yellow MIDI IN light on the MIDI to USB board turn on with each note. More info about programming the Arduino to send MIDI can be found here.

//basic midi test
//by Amanda Ghassaei 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
*/

//this firmware will cause the buttons to light up momentarily while they are pressed.

//pin connections
int ledLatchPin = 6;
int ledClockPin = 5;
int ledDataPin = 7;
int buttonLatchPin = 4;
int buttonClockPin = 3;
int buttonDataPin = 2;

//looping variables
byte i;
byte j;
byte k;

//storage for led states, 4 bytes
byte ledData[] = {0, 0, 0, 0};
//storage for buttons, 4 bytes
byte buttonCurrent[] = {0,0,0,0};
byte buttonLast[] = {0,0,0,0};
byte buttonEvent[] = {0,0,0,0};
byte buttonState[] = {0,0,0,0};
//button debounce counter- 16 bytes
byte buttonDebounceCounter[4][4];

//MIDI variables
int velocity = 100;
int noteON = 144;
int MIDIoffset = 60;

void setup() {
  DDRD = 0xFA;//set pins D7-D4 as output, D2 as input
  
  Serial.begin(31250);//set midi baud rate
}

// buttonCheck - checks the state of a given button.
//this buttoncheck function is largely copied from the monome 40h firmware by brian crabtree and joe lake
void buttonCheck(byte row, byte index)
{
  if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) &&   // if the current physical button state is different from the
  ((buttonCurrent[row] ^ buttonState[row]) & (1 << index))) {  // last physical button state AND the current debounced state

    if (buttonCurrent[row] & (1 << index)) {                      // if the current physical button state is depressed
      buttonEvent[row] = 1 << index;              // queue up a new button event immediately
      buttonState[row] |= (1 << index);                         // and set the debounced state to down.
  }
    else{
      buttonDebounceCounter[row][index] = 12;
    }  // otherwise the button was previously depressed and now
    // has been released so we set our debounce counter.
  }
  else if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) == 0 &&  // if the current physical button state is the same as
  (buttonCurrent[row] ^ buttonState[row]) & (1 << index)) {        // the last physical button state but the current physical
    // button state is different from the current debounce 
    // state...
    if (buttonDebounceCounter[row][index] > 0 && --buttonDebounceCounter[row][index] == 0) {  // if the the debounce counter has
      // been decremented to 0 (meaning the
      // the button has been up for 
      // kButtonUpDefaultDebounceCount 
      // iterations///

      buttonEvent[row] = 1 << index;    // queue up a button state change event

      if (buttonCurrent[row] & (1 << index)){          // and toggle the buttons debounce state.
        buttonState[row] |= (1 << index);
      }
      else{
        buttonState[row] &= ~(1 << index);
      }
    }
  }
}


void shift(){
  
  for (i=0;i<4;i++){
    
    buttonLast[i] = buttonCurrent[i];
    
    byte dataToSend = (1 << (i+4)) | (15 & ~ledData[i]);
      
    // set latch pin low so the LEDs don't change while sending in bits
    digitalWrite(ledLatchPin, LOW);
    // shift out the bits of dataToSend
    shiftOut(ledDataPin, ledClockPin, LSBFIRST, dataToSend);  
    //set latch pin high so the LEDs will receive new data
    digitalWrite(ledLatchPin, HIGH);
      
    //once one row has been set high, receive data from buttons
    //set latch pin high
    digitalWrite(buttonLatchPin, HIGH);
    //shift in data
    buttonCurrent[i] = shiftIn(buttonDataPin, buttonClockPin, LSBFIRST) >> 3;
    //latchpin low
    digitalWrite(buttonLatchPin, LOW);
    
    for (k=0;k<4;k++){
      buttonCheck(i,k);
    }
  }
}

void updateLEDs(){ //update the leds to reflect hte state of the buttons
  for (j=0;j<4;j++){
    ledData[j] = buttonState[j];
  }
}

void MIDImessage(int command, int MIDInote, int MIDIvelocity) {//send s a MIDI message
  Serial.write(command);//send note on or note off command 
  Serial.write(MIDInote);//send pitch data
  Serial.write(MIDIvelocity);//send velocity data
}

void sendMIDI(){
  for (byte a=0;a<4;a++){
    for (byte b=0;b<4;b++){
      if (buttonEvent[a]&(1<<b)){
        buttonEvent[a]&=~(1<<b);//zero button event
        if (buttonState[a]&(1<<b)){
          MIDImessage(noteON,(MIDIoffset+a*5+b),100);
        }
        else{
          MIDImessage(noteON,(MIDIoffset+a*5+b),0);
        }
      }
    }
  }
}


void loop() {
  shift();
  updateLEDs();
  sendMIDI();
}

Step 28: Accerometer/Gyro

I attached a 2 axis gyroscope and 3 axis accelerometer onto this project so that I could add some interesting control to the device. The 5 degrees of freedom board from Sparkfun outputs data from its gyroscope and accelerometer as analog voltages. I sent these to analog pin 0-4. You may notice that the Gyro has four outputs- I chose to use the X/Y4.5 out instead of the X/YRate out because the 4.5 has higher resolution. I wrote more about this board and explained some of the code I used to get it up and running here.

Solder header pins on the gyro/accelerometer board. Solder on the perfboard, making sure to leave room for the Arduino to fit on top. Make the following pin connections:

RAW - Arduino 5V
GND- Arduino ground
X4.5- A2
Y4.5- A0
XAcc- A4
YAcc- A3
ZAcc- A1 (I ended up disconnecting this later to free up an analog input for a second potentiometer)

Upload the following code and check the serial monitor to make sure accelerometer/gyro is functioning properly. When the board is lying still and parallel to the ground the values of xGyro, yGyro, xAcc, and yAcc should all hover around 0. zAcc should output a value around -66 (see fig 8). Move the board around and see how the values change. In figure 9 you can see how rotation about the x axis changes xGyro and y and zAcc, but not yGyro or xAcc.
//Analog Accerometer w Serial
//by Amanda Ghassaei
//instructables.com/amandaghassaei
//August 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
*/ 
 
 //setup acceleration variables
 int xAcc;
 int yAcc;
 int zAcc;

 //setup gyre variables
 int xGyro;
 int yGyro;
 
 int zero = 282;//this was the zero point value for my accelerometer, your board may be slightly different.

void setup(){
  Serial.begin(9600);//set up serial
}

void loop(){
  
  //read values
  xGyro = analogRead(A2);
  yGyro = analogRead(A0);
  xAcc = analogRead(A4);
  yAcc = analogRead(A3);
  zAcc = analogRead(A1);

  
  //print values
  Serial.print("xGyro ");
  Serial.println(317-xGyro);
  Serial.print("yGyro ");
  Serial.println(183-yGyro);
  Serial.print("xAcc ");
  Serial.println(zero-xAcc);
  Serial.print("yAcc ");
  Serial.println(zero-yAcc);
  Serial.print("zAcc ");
  Serial.println(zero-zAcc);
  Serial.println(" ");
  delay(500);//wait

}

The following pieces of firmware combine the hardware that I've set up in the preview steps with the accelerometer and gyroscope. Each of the programs functions are summarized in the video below:

The code below lets you light up one pixel of the button pad and move the pixel around the 4x4 grid by tilting it in different directions. As the pixel moves across the grid it also triggers MIDI notes.
//accelerometer test
//by Amanda Ghassaei 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
*/

//this firmware will cause the buttons to light up momentarily while they are pressed.

//pin connections
int ledLatchPin = 6;
int ledClockPin = 5;
int ledDataPin = 7;
int buttonLatchPin = 4;
int buttonClockPin = 3;
int buttonDataPin = 2;

//setup varibles for Gyroscope/Accelerometer
int xGyroRAW;
int yGyroRAW;
int xAccRAW;
int yAccRAW;
int zAccRAW;

byte xGyro;
byte yGyro;
byte xAcc;
byte yAcc;
byte zAcc;

//looping variables
byte i;
byte j;
byte k;

//storage for led states, 4 bytes
byte ledData[] = {0, 0, 0, 0};
//storage for buttons, 4 bytes
byte buttonCurrent[] = {0,0,0,0};
byte buttonLast[] = {0,0,0,0};
byte buttonEvent[] = {0,0,0,0};
byte buttonState[] = {0,0,0,0};
//button debounce counter- 16 bytes
byte buttonDebounceCounter[4][4];

//variables for accelerometer pixel movement
boolean firstPress = 1;
byte movingPixel[] = {0, 0, 0, 0};
byte yPosition;
byte xPosition;
int timeX = 0;
int timeY = 0;
boolean dirX = 0;
boolean dirY = 0;
byte lastX = 4;
byte lastY = 4;

//MIDI variables
int velocity = 100;
int noteON = 144;
int MIDIoffset = 60;
byte currentX;


void setup() {
  
  DDRD = 0xFA;//set pins D7-D4 as output, D2 as input
  
  Serial.begin(31250);//MIDI baud rate 
//  Serial.begin(9600);
  
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (16*10^6) / (1000*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  
  sei();//allow interrupts
  
}

ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz
  timeX++;//increment timeX
  timeY++;//increment timeY
}

// buttonCheck - checks the state of a given button.
//this buttoncheck function is largely copied from the monome 40h firmware by brian crabtree and joe lake
void buttonCheck(byte row, byte index)
{
  if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) &&   // if the current physical button state is different from the
  ((buttonCurrent[row] ^ buttonState[row]) & (1 << index))) {  // last physical button state AND the current debounced state

    if (buttonCurrent[row] & (1 << index)) {                      // if the current physical button state is depressed
      buttonEvent[row] = 1 << index;              // queue up a new button event immediately
      buttonState[row] |= (1 << index);                         // and set the debounced state to down.
  }
    else{
      buttonDebounceCounter[row][index] = 12;
    }  // otherwise the button was previously depressed and now
    // has been released so we set our debounce counter.
  }
  else if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) == 0 &&  // if the current physical button state is the same as
  (buttonCurrent[row] ^ buttonState[row]) & (1 << index)) {        // the last physical button state but the current physical
    // button state is different from the current debounce 
    // state...
    if (buttonDebounceCounter[row][index] > 0 && --buttonDebounceCounter[row][index] == 0) {  // if the the debounce counter has
      // been decremented to 0 (meaning the
      // the button has been up for 
      // kButtonUpDefaultDebounceCount 
      // iterations///

      buttonEvent[row] = 1 << index;    // queue up a button state change event

      if (buttonCurrent[row] & (1 << index)){          // and toggle the buttons debounce state.
        buttonState[row] |= (1 << index);
      }
      else{
        buttonState[row] &= ~(1 << index);
      }
    }
  }
}


void shift(){
  for (i=0;i<4;i++){
    buttonLast[i] = buttonCurrent[i];
    
    byte dataToSend = (1 << (i+4)) | (15 & ~ledData[i]);
      
    // set latch pin low so the LEDs don't change while sending in bits
    digitalWrite(ledLatchPin, LOW);
    // shift out the bits of dataToSend
    shiftOut(ledDataPin, ledClockPin, LSBFIRST, dataToSend);  
    //set latch pin high so the LEDs will receive new data
    digitalWrite(ledLatchPin, HIGH);
      
    //once one row has been set high, receive data from buttons
    //set latch pin high
    digitalWrite(buttonLatchPin, HIGH);
    //shift in data
    buttonCurrent[i] = shiftIn(buttonDataPin, buttonClockPin, LSBFIRST) >> 3;
    //latchpin low
    digitalWrite(buttonLatchPin, LOW);
    
    for (k=0;k<4;k++){
      buttonCheck(i,k);
    }
  }
}

void checkFirstButton(){
  for (byte a=0;a<4;a++){
    if (buttonEvent[a]){
      for (byte b=0;b<4;b++){
        if (buttonState[a]&(1<=-10){
    return 5;
  }
  else if (RAW<-10){
    if (RAW<-50){
      return 0;
    }
    else if (RAW<-40){
      return 1;
    }
    else if (RAW<-30){
      return 2;
    }
    else if (RAW<-20){
      return 3;
    }
    else{
      return 4;
    }
  }
  else if (RAW>10){
    if (RAW>50){
      return 10;
    }
    else if (RAW>40){
      return 9;
    }
    else if (RAW>30){
      return 8;
    }
    else if (RAW>20){
      return 7;
    }
    else{
      return 6;
    }
  }
}

void checkAccelerometer(){
  //read values
  xGyroRAW = analogRead(A1);
  yGyroRAW = analogRead(A0);
  xAccRAW = analogRead(A4);
  yAccRAW = analogRead(A3);
  zAccRAW = analogRead(A2);
  
  //offset data
  xGyroRAW = 317-xGyroRAW;
  yGyroRAW = 183-yGyroRAW;
  xAccRAW = 282-xAccRAW;
  yAccRAW = 282-yAccRAW;
  zAccRAW = 282-zAccRAW;
  
  if (xAccRAW>0){
    dirX = 1;
  }
  else{
    dirX = 0;
  }
  if (yAccRAW>0){
    dirY = 1;
  }
  else{
    dirY = 0;
  }
  
  //convert to 0-10
  xAcc = scaleAcc(xAccRAW);
  yAcc = scaleAcc(yAccRAW);
}

int getTime(byte acceleration){
  switch (acceleration){
    case 0://max - acceleration
    return 25;
    break;
    case 1:
    return 25;
    break;
    case 2:
    return 50;
    break;
    case 3:
    return 100;
    break;
    case 4:
    return 150;
    break;
    case 5://lying flat
    return 0;
    break;
    case 6:
    return 150;
    break;
    case 7:
    return 100;
    break;
    case 8:
    return 50;
    break;
    case 9:
    return 25;
    break;
    case 10://max + acceleration
    return 25;
    break;
  }
}

void moveXPixel(int timeComp){
  if (timeComp==0){
  }
  else{
    if (timeX>timeComp){
      timeX = 0;
      if (dirX){
        if (xPosition==8){
        }
        else{
          xPosition = xPosition<<1;
        }
      }
      else{
        if (xPosition==1){
        }
        else{
          xPosition = xPosition>>1;
        }
      }
    }
  }
}

void moveYPixel(int timeComp){
  if (timeComp==0){
  }
  else{
    if (timeY>timeComp){
      timeY = 0;
      if (dirY){
        if (yPosition==3){
        }
        else{
          yPosition = yPosition+=1;
        }
      }
      else{
        if (yPosition==0){
        }
        else{
          yPosition = yPosition-=1;
        }
      }
    }
  }
}

void checkMIDI(){
  //convert xPosition to decimal
  switch (xPosition){
    case 1:
    currentX = 0;
    break;
    case 2:
    currentX = 1;
    break;
    case 4:
    currentX = 2;
    break;
    case 8:
    currentX = 3;
    break;
  }
  //if pixel has moved send midi
  if (lastX != currentX || lastY != yPosition){
    MIDImessage(noteON,(lastX+5*lastY+MIDIoffset),0);//turn off last note
    MIDImessage(noteON,(currentX+5*yPosition+MIDIoffset),velocity);//turn on next note
  }
  lastX = currentX;
  lastY = yPosition;
}
  

void MIDImessage(int command, int MIDInote, int MIDIvelocity) {//send s a MIDI message
  Serial.write(command);//send note on or note off command 
  Serial.write(MIDInote);//send pitch data
  Serial.write(MIDIvelocity);//send velocity data
}

void loop() {
  shift();
  if (firstPress){
    checkFirstButton();
  }
  else{
    for (byte pixel=0;pixel<4;pixel++){
      if (pixel==yPosition){
        ledData[pixel]=xPosition;
      }
      else{
        ledData[pixel] = 0;
      }
    }
    checkAccelerometer();
    moveXPixel(getTime(xAcc));
    moveYPixel(getTime(yAcc));
    checkMIDI();
  }
}
The code below lets you light up one pixel in each column. As you tilt the gyroscope, the pixels bounce against the edge of the grid and trigger a MIDI note.
//accelerometer test
//by Amanda Ghassaei 2012

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
*/

//this firmware will cause the buttons to light up momentarily while they are pressed.

//pin connections
//#define ledLatchPin 6
//#define ledClockPin 5
//#define ledDataPin 7
//#define buttonLatchPin 4
//#define buttonClockPin 3
//#define buttonDataPin 2

//setup varibles for Gyroscope/Accelerometer
int xGyroRAW;
int yGyroRAW;
int xAccRAW;
int yAccRAW;
int zAccRAW;

byte xGyro;
byte yGyro;
byte xAcc;
byte yAcc;
byte zAcc;

//looping variables
byte i;
byte j;
byte k;

//storage for led states, 4 bytes
byte ledData[] = {0, 0, 0, 0};
//storage for buttons, 4 bytes
byte buttonCurrent[] = {0,0,0,0};
byte buttonLast[] = {0,0,0,0};
byte buttonEvent[] = {0,0,0,0};
byte buttonState[] = {0,0,0,0};
//button debounce counter- 16 bytes
byte buttonDebounceCounter[4][4];

//variables for accelerometer pixel movement
boolean firstPress[] = {0, 0, 0, 0};
byte movingPixel[] = {0, 0, 0, 0};
byte xPosition[4];
int timeX[] = {0, 0, 0, 0};
boolean dirX;
boolean dirY;
boolean prevDirX = 0;
boolean bounceDirection[]= {0, 0, 0, 0};
boolean toggle[] = {1, 1, 1, 1};
byte peakHeight[4];
byte lastX = 4;
byte lastY = 4;

//MIDI variables
int velocity = 100;
int noteON = 144;
int MIDIoffset = 60;
byte currentX;
byte note[] = {60, 64, 67, 72};


void setup() {
  
  DDRD = 0xFA;//set pins D7-D4 as output, D2 as input
  
  Serial.begin(31250);//MIDI baud rate 
  
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (16*10^6) / (1000*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  
  sei();//allow interrupts
  
}

ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz
  for (byte a=0;a<4;a++){
    timeX[a]++;//increment each element of timeX
  }
  shift();
}

// buttonCheck - checks the state of a given button.
//this buttoncheck function is largely copied from the monome 40h firmware by brian crabtree and joe lake
void buttonCheck(byte row, byte index)
{
  if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) &&   // if the current physical button state is different from the
  ((buttonCurrent[row] ^ buttonState[row]) & (1 << index))) {  // last physical button state AND the current debounced state

    if (buttonCurrent[row] & (1 << index)) {                      // if the current physical button state is depressed
      buttonEvent[row] = 1 << index;              // queue up a new button event immediately
      buttonState[row] |= (1 << index);                         // and set the debounced state to down.
  }
    else{
      buttonDebounceCounter[row][index] = 12;
    }  // otherwise the button was previously depressed and now
    // has been released so we set our debounce counter.
  }
  else if (((buttonCurrent[row] ^ buttonLast[row]) & (1 << index)) == 0 &&  // if the current physical button state is the same as
  (buttonCurrent[row] ^ buttonState[row]) & (1 << index)) {        // the last physical button state but the current physical
    // button state is different from the current debounce 
    // state...
    if (buttonDebounceCounter[row][index] > 0 && --buttonDebounceCounter[row][index] == 0) {  // if the the debounce counter has
      // been decremented to 0 (meaning the
      // the button has been up for 
      // kButtonUpDefaultDebounceCount 
      // iterations///

      buttonEvent[row] = 1 << index;    // queue up a button state change event

      if (buttonCurrent[row] & (1 << index)){          // and toggle the buttons debounce state.
        buttonState[row] |= (1 << index);
      }
      else{
        buttonState[row] &= ~(1 << index);
      }
    }
  }
}


void shift(){
  
  for (i=0;i<4;i++){
    
    buttonLast[i] = buttonCurrent[i];
    
    byte dataToSend = (1 << (i+4)) | (15 & ~ledData[i]);
      
    // set latch pin low so the LEDs don't change while sending in bits
    PORTD&=B10111111;//digitalWrite(ledLatchPin, LOW);
    // shift out the bits of dataToSend 
    //shiftOut(ledDataPin, ledClockPin, LSBFIRST, dataToSend);  
    for (j=0;j<8;j++){
      PORTD&=B11011111;//digitalWrite(ledClockPin,LOW);
      //digitalWrite(ledDataPin,((dataToSend>>j)&1));
      if ((dataToSend>>j)&1){
        PORTD|=B10000000;
      }
      else{
        PORTD&=B01111111;
      }
      PORTD|=B00100000;//digitalWrite(ledClockPin,HIGH);
    }
    //set latch pin high so the LEDs will receive new data
    PORTD|=B01000000;//digitalWrite(ledLatchPin, HIGH);
    
    // SlowDown is put in here to waste a little time while we wait for the state of the output
    // pins to settle.  Without this time wasting loop, a single button press would show up as
    // two presses (the button and its neighbour)
    volatile int SlowDown = 0; 

    while (SlowDown < 15) 
    { 
      SlowDown++; 
    } 
      
    //once one row has been set high, receive data from buttons
    //set latch pin high
    PORTD|=B00010000;//digitalWrite(buttonLatchPin, HIGH);
    //shift in data
    //buttonCurrent[i] = shiftIn(buttonDataPin, buttonClockPin, LSBFIRST) >> 3;
    for (j=0;j<4;j++){
      PORTD&=B11110111;//digitalWrite(buttonClockPin,LOW);
      PORTD|=B00001000;//digitalWrite(buttonClockPin,HIGH);
    }
    for (j=0;j<4;j++){
      PORTD&=B11110111;//digitalWrite(buttonClockPin,LOW);
      if ((PIND>>2)&1){//digitalRead(buttonDataPin)
        buttonCurrent[i]|=1<

Step 29: Pots

Picture of Pots
IMG_2559 copy.jpg
IMG_2562 copy.jpg

Connect a black wire to the left lead of a 10K linear taper potentiometer. Connect a green wire to the middle lead. Connect a red wire to the remaining lead. Repeat this for the other potentiometer. Connect the other end of the red wires to 5V, the black wires to ground, and the green wires to Analog in

Use pliers to remove the pin on the side of the pots, so that you can mount it more easily in your project enclosure.

Step 30: Enclosure

Picture of Enclosure
IMG_0234 copy.jpg
IMG_0231 copy.jpg
IMG_0235 copy.jpg
IMG_5344.jpg

I borrowed an idea from former Artist in Residence Mads Hobye for my enclosure. Mads founds these sleek boxes at the container store and used them to make project enclosures for the various musical instruments he built during his stay. These boxes are particularly convenient because they have a bevel around the top that allows you to easily mount a 5mm acrylic front panel.

I used a laser cutter to cut out two USB ports (one for the Arduino and one for MIDI out) in the bottom of the enclosure. Then I used a drill to make holes for two pots, a power switch, and a charging jack. The vector files are attached.

I laser cut a front panel from translucent white 5mm acrylic so that it would snap fit into the wood box. the eps file for the front panel is attached below.

Step 31: Final Firmware

For the final firmware, I've extracted all the code that controls the buttons and leds into a library to make it more tidy, all of this is in a class called SugarCube. I was inspired by the work I've been doing on the Instructables iOS app, and wrote the event handling pieces of the code so that they work in a similar way that an iPhone deals with touch and other gestural events. Basically I created a set of methods that each app can subscribe to, things like "deviceWasShaken" or "buttonPressed". When the SugarCube class detects one of these events, it tells the current app to execute the corresponding method. If you're interested in seeing an example of this structure in action, check out SimpleMIDIKeyboard.cpp, it shows how few lines of code are needed to wire up all the button and analog controls to MIDI outputs. I hope to eventually write out a little more complete documentation for how to write your own apps based on this framework, please let me know if there is interest. This is by far my biggest piece of C++ code, and I am by no means an expert in C++, I'd love to hear an expert's thoughts on how I did!

Step for running the code:

Download the zip file from github

unzip

rename the folder to "SugarCubeLibraryFiles"

open the file SugarCubeLibraryFiles.ino in Arduino

connect your Arduino and upload

Step 32: Future Work

This project has the potential to be expanded upon quite a bit. Unfortunately, I just don't have the time to invest in exploring all the possibilities, but here's some ideas I had for things to look into:

More apps: The current implementation of this device allows you to boot into 16 different applications, but I've only written seven so far. There's a ton of great ideas over on the monome website for grid based controllers, it'd be great to see some of that translated into Arduino.

Gyro Control: As I mentioned earlier, I threw an x/y gyroscope in the controller, but I've yet to write an app that actually uses it. I'd love to hear if someone has an idea for how this could work with MIDI.

Wireless: When I started this project, my major design objectives were portability and plug and play ease of use. I wanted to try to break away from the model of the electronic controller that necessitates a computer to run, in an effort to bring electronic music out of the traditional studio environment. In keeping with that idea, I'd like to eventually get this controller to wirelessly send MIDI to my phone to make it totally portable. I have one of these bluetooth boards from Red Bear Labs, and I think there might be some way to send the data to my phone, translate it into CoreMIDI and run it though a MIDI synth, but I just haven't explored the idea enough yet. If anyone has any insight, I'd love to hear your thoughts.

Step 33: Appendix: Cut PCB for Control Buttons

Picture of Appendix: Cut PCB for Control Buttons
IMG_9922 copy.jpg
IMG_9923 copy.jpg
IMG_9924 copy.jpg

Originally, I planned to have four extra "control" buttons on the side of the controller that I was going to use in various applications. I started wiring it up, but eventually scrapped it. I haven't written any code for these buttons, and they are in no way integrated into the apps I've written, but I figured I'd still include the images that I took during that process in this Instructable in case it's useful to anyone.

Cut the 2x2 sparkfun pcb as shown in the pictures above. Solder white LEDs and diodes on the pcb as in steps 2 and 3.

Step 34: Appendix: Control Buttons Wiring Part 1: PCB

Cut a piece of ribbon cable and solder 8 wires to the sparkfun PCB holes labelled "switch gnd" and "led gnd". Solder four more wires to the holes labelled "switch" and "blue." See the images for more info.

On one half of the PCB (the one labelled "green" and "blue") you will have to rewire some of the traces that were broken when the PCB was cut. Both connections to the positive switch rail will need to be connected to each other and then connected to the "green" led trace as shown in fig 4. I did this by removing one strand of a piece of stranded wire and poking it through the vias on the PCB. Use a dab of solder to secure the electrical connection between the copper strand and the PCB (fig 7). You will also have to solder a wire between the two "blue" positive rails (also shown in fig 4). Once this is done, test for continuity and cover the exposed copper with electrical tape to prevent short circuits (fig 6).

On the other half of the PCB, use a jumper wire to connect the "red" and "blue" sockets of one of the LEDs together (see fig 7). This will connect the anode of your white LEDs to the ribbon cable.

Step 35: Appendix: Control Buttons Wiring Part 2: Socket

Picture of Appendix: Control Buttons Wiring Part 2: Socket
IMG_9966 copy.jpg
IMG_9967 copy.jpg
IMG_9964 copy.jpg

Clamp a 16 pin socket onto the ribbon cable as shown in fig 1. Solder two rows of male header pins to the protoboard so that the control buttons fit onto the board as shown in fig 3. Trim any excess ribbon cable.

Step 36: Appendix: Control Buttons Wiring Part 3: Header Pins

Picture of Appendix: Control Buttons Wiring Part 3: Header Pins
IMG_0188 copy.jpg
IMG_0189 copy.jpg

Solder 3 more male header pins to snap to digital pins 11-13. Since the spacing between Arduino digital pins 0-7 and pin 8-13, I had to drill holes in my perfboard and scrape off some of the copper traces. See the images above for more information.

Step 37: Appendix: Control Buttons Wiring Part 4: Connections to LEDs

Picture of Appendix: Control Buttons Wiring Part 4: Connections to LEDs
IMG_9972 copy.jpg
IMG_0190 copy.jpg
IMG_0192 copy.jpg
IMG_0193 copy.jpg

Solder four 68ohm resistors to the pins which connect to the LED cathodes. Connect the other end of these resistors to pins 4-7 of the 74HC595 with jumper wires (yellow).

We'll be using pin 11 of the Arduino to supply positive voltage to the LEDs, but one Arduino pin cannot source enough current to drive the LEDs by itself. I used a 222 NPN transistor in an emitter-follower configuration to boost the power of pin 11's signal. Connect pin 11 to the base (middle pin) of the transistor. Connect the collector to the Arduino's 5V supply and the emitter to the header pins which connect to the LED anodes (fig 5).

Step 38: Appendix: Control Buttons Wiring Part 5: Connections to Buttons

Picture of Appendix: Control Buttons Wiring Part 5: Connections to Buttons
IMG_0195 copy.jpg
IMG_0196 copy.jpg
IMG_0199 copy.jpg
IMG_0200 copy.jpg

Solder a jumper wire between pin 13 of the Arduino and the header pins which attach to the button anodes.

On the reverse side of the perfboard I soldered four jumper wires from the button cathode pins to 10k resistors connected to ground (fig 4). I did this to save space on my PCB so that it would fit in an enclosure better. I also soldered four jumper wires from the non grounded side of the 10k resistors to 165 pins 3-6.

1-40 of 108Next »
MatthewT726 days ago

Does anyone happen to have a PCB design of this already? Fritzing/Eagle/DipTrace? If not, im in the process of making one as i wouldnt mind making some additional changes and making these over and over with perfboard gets really time consuming =-)

amandaghassaei (author)  MatthewT710 days ago

nice! let me know how that goes, it might make sense for me to eventually move documentation over to a wiki if there's interest in doing mods and stuff. Have you successfully finished a perfboard version yet?

Yep! It took me a few tries because I'm apparently terrible at those solder bridges but I eventually got it. I'm in the process of printing a prototype shield so once I verify it's good I'll post up the schematic and pcb design :-)
kennethharris2 months ago

I really like it.. Well done

stevenelson552 months ago

Really mind blowing

adamrussell2 months ago

This is amazing

denniscook2 months ago

Fantastic, it works beautifully

kierondeane3 months ago

Hi Amanda is there a way to adapt the button test code to print the button presses straight to the serial monitor. im trying to encorporate part of the code into a bigger patch.

markkuki made it!3 months ago

My version of a Arduino SugarCube based on this instructable. Mine has 4 pots, no gyroscope, no accelerometer, no battery power, just a MIDI controller for my project studio. I edited all the code to suit my own basic needs, uploaded the firmware and everything it works great! Thanks Amanda! :)

WP_20150402_21_32_31_Pro.jpg
kierondeane5 months ago

hi i have completed this build but am getting this error when uploading the final code.


This report would have more information with

"Show verbose output during compilation"

enabled in File > Preferences.

Arduino: 1.0.6 (Mac OS X), Board: "Arduino Uno"

sugarcube/SugarCube.cpp.o: In function `SugarCube':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:13: multiple definition of `SugarCube::SugarCube()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:13: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:13: multiple definition of `SugarCube::SugarCube()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:13: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::timer1Setup()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:77: multiple definition of `SugarCube::timer1Setup()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:77: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::timer2Setup()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:99: multiple definition of `SugarCube::timer2Setup()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:99: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setDefaultPinConnections()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:121: multiple definition of `SugarCube::setDefaultPinConnections()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:121: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setLedLatchPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:137: multiple definition of `SugarCube::setLedLatchPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:137: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setLedClockPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:144: multiple definition of `SugarCube::setLedClockPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:144: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setLedDataPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:149: multiple definition of `SugarCube::setLedDataPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:149: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setButtonLatchPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:154: multiple definition of `SugarCube::setButtonLatchPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:154: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setButtonClockPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:159: multiple definition of `SugarCube::setButtonClockPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:159: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setButtonDataPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:164: multiple definition of `SugarCube::setButtonDataPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:164: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setXAccPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:169: multiple definition of `SugarCube::setXAccPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:169: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setYAccPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:174: multiple definition of `SugarCube::setYAccPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:174: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setPot1Pin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:179: multiple definition of `SugarCube::setPot1Pin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:179: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setPot2Pin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:184: multiple definition of `SugarCube::setPot2Pin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:184: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setXGyroPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:189: multiple definition of `SugarCube::setXGyroPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:189: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setYGyroPin(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:194: multiple definition of `SugarCube::setYGyroPin(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:194: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getStateOfButton(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:239: multiple definition of `SugarCube::getStateOfButton(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:239: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getStateOfButtonRow(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:247: multiple definition of `SugarCube::getStateOfButtonRow(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:247: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getXAxisGyroVal()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:321: multiple definition of `SugarCube::getXAxisGyroVal()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:321: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getYAxisGyroVal()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:326: multiple definition of `SugarCube::getYAxisGyroVal()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:326: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getPot1Val()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:331: multiple definition of `SugarCube::getPot1Val()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:331: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getPot2Val()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:336: multiple definition of `SugarCube::getPot2Val()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:336: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::turnOnLED(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:347: multiple definition of `SugarCube::turnOnLED(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:347: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::turnOffLED(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:352: multiple definition of `SugarCube::turnOffLED(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:352: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setLEDState(unsigned char, unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:355: multiple definition of `SugarCube::setLEDState(unsigned char, unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:355: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setLEDsByArray(unsigned char*)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:364: multiple definition of `SugarCube::setLEDsByArray(unsigned char*)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:364: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setLEDRow(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:397: multiple definition of `SugarCube::setLEDRow(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:397: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::turnOnLED(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:402: multiple definition of `SugarCube::setLEDCol(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:402: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::clearLEDs()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:410: multiple definition of `SugarCube::clearLEDs()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:410: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::buttonCheck(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:494: multiple definition of `SugarCube::buttonCheck(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:494: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setXGyro(int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:583: multiple definition of `SugarCube::setXGyro(int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:583: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setYGyro(int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:591: multiple definition of `SugarCube::setYGyro(int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:591: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setPot1(int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:599: multiple definition of `SugarCube::setPot1(int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:599: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setPot2(int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:607: multiple definition of `SugarCube::setPot2(int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:607: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::checkForShake()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:615: multiple definition of `SugarCube::checkForShake()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:615: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setDelegate(Delegate*)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:727: multiple definition of `SugarCube::setDelegate(Delegate*)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:727: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::timer2Routine()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:704: multiple definition of `SugarCube::timer2Routine()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:704: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setupSerialCommunication()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:679: multiple definition of `SugarCube::setupSerialCommunication()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:679: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setupMIDICommunication()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:645: multiple definition of `SugarCube::setupMIDICommunication()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:645: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::sendMIDI(unsigned char, unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:666: multiple definition of `SugarCube::sendMIDI(unsigned char, unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:666: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::pitchBend(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:661: multiple definition of `SugarCube::pitchBend(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:661: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::noteOff(unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:656: multiple definition of `SugarCube::noteOff(unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:656: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::noteOn(unsigned char, unsigned char, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:651: multiple definition of `SugarCube::noteOn(unsigned char, unsigned char, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:651: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::scaleAcc(int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:577: multiple definition of `SugarCube::scaleAcc(int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:577: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setYAcc(int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:566: multiple definition of `SugarCube::setYAcc(int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:566: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setXAcc(int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:555: multiple definition of `SugarCube::setXAcc(int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:555: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getYAxisAccVal()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:316: multiple definition of `SugarCube::getYAxisAccVal()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:316: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getXAxisAccVal()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:311: multiple definition of `SugarCube::getXAxisAccVal()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:311: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::analogValFromPin(unsigned char, int)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:546: multiple definition of `SugarCube::analogValFromPin(unsigned char, int)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:546: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::checkAnalogPins()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:535: multiple definition of `SugarCube::checkAnalogPins()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:535: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::initAnalogPins()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:525: multiple definition of `SugarCube::initAnalogPins()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:525: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setLEDsByBitmap(unsigned char*, unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:377: multiple definition of `SugarCube::setLEDsByBitmap(unsigned char*, unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:377: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::numPressedButtons(unsigned char*)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:283: multiple definition of `SugarCube::numPressedButtons(unsigned char*)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:283: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getPressedButtons(unsigned char (*) [2])':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:265: multiple definition of `SugarCube::getPressedButtons(unsigned char (*) [2])'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:265: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getStateOfButtonCol(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:252: multiple definition of `SugarCube::getStateOfButtonCol(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:252: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::shift(unsigned char)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:421: multiple definition of `SugarCube::shift(unsigned char)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:421: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::timer1Routine()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:690: multiple definition of `SugarCube::timer1Routine()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:690: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getButtonStatesBitmap(unsigned char, unsigned char*)':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:217: multiple definition of `SugarCube::getButtonStatesBitmap(unsigned char, unsigned char*)'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:217: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::getButtonStatesArray(unsigned char (*) [4])':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:201: multiple definition of `SugarCube::getButtonStatesArray(unsigned char (*) [4])'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:201: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::setupInputsAndOutputs()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:55: multiple definition of `SugarCube::setupInputsAndOutputs()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:55: first defined here

sugarcube/SugarCube.cpp.o: In function `SugarCube::init()':

/Users/kierondeane/Documents/Arduino/libraries/sugarcube/SugarCube.cpp:39: multiple definition of `SugarCube::init()'

sketch_feb23a.cpp.o:/Applications/sketch_feb23a.ino:39: first defined here

core.a(main.cpp.o): In function `main':

/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/main.cpp:40: undefined reference to `setup'

/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/main.cpp:43: undefined reference to `loop'


any help would be greatly appreciated

amandaghassaei (author)  kierondeane4 months ago

maybe try a fresh download? what version of arduino are you using?

im using the newest version of the arduino ide and arduino uno. all test codes such as buttons and led test code works the rest get this same error

amandaghassaei (author)  kierondeane4 months ago

I think maybe you put the folder in Arduino/libraries? you don't actually have to do that, you can just download the zip from github, unzip, change the folder name to "SugarCubeLibraryFiles" and then open the SugarCubeLibraryFiles.ino file inside.

I tested it on the latest version of arduino, should work. Jut make sure you have the right board selected.

Sorry if that was confusing!

markkuki7 months ago

Hello again! :) Had to take a long break from this due to other school work keeping me busy. Ok, I re-read steps 19-24 with your updated notes taken into account. The "Test Buttons" arduino code when run on my build results in the following inverted behavior: all the LEDs are lit up after uploading the code and while pressing a button each LED momentarily turns off (i.e. when pressed) and is lit back up after release of button. I don't know why this is and I have allegedly checked all my other connections to the best of my ability that is.... :( P.S. Note, Step 18: Test LEDs code is working as it should = OK. I went all the way back to re-trace the steps 1 thru 24 documentation to see what I might have done wrong.

WP_20141208_03_33_26_Pro.jpg
amandaghassaei (author)  markkuki7 months ago

did you work this out? sounds like the leds are fine but something is up with the button wiring. Are the diodes in the right direction?

Does are in the right direction, yes. Still having this issue, and yes something is wrong with the button wiring. any suggestions?

amandaghassaei (author)  markkuki6 months ago

are the pull down resistors there? can you attach a clear pic of what you've got? and you're running the code from step 24?

Yes, running the code from step 24. All the buttons respond (more or less) there is just inverted operation of the buttons compared to that of your implementation (is really the only difference I can tell). Here are some more pics.

Note, I burned some of the traces from the PCB board so I had to create a jump lead for one of the 8 group of header pins that connect to the ribbon clamp.

I fear the only thing there is left to do is to re-do the 8 header pins and resistors because they are a mess. As you mentioned to me a while ago, the DIPs are pretty resilient and should be okay so I keep looking at the 8 header pins as the source of this glitch.

The discoloration of the solder came from earlier cleaning during troubleshooting because I didn't use distilled water (I think). Disregard the scratches, I used a stanley knife to make sure none of the globbed solder points were touching each other on the edges.

Also note, I do have a protoboard in case it might help to re-build a sub-circuit or two on that first before going back to soldering again. Also, I'm getting a new solder because the one a bought is too hot and cannot be adjusted.

Any help would be greatly appreciated. I just hope I don't have to start from scratch because this project was expensive.

WP_20150123_05_58_22_Pro.jpgWP_20150123_05_58_48_Pro.jpgWP_20150123_05_59_04_Pro.jpgWP_20150123_05_59_43_Pro.jpg
amandaghassaei (author)  markkuki6 months ago

Do you have a multimeter? what's the voltage at the swt-gnd pins when no buttons are pressed?

I got 4.904 Volts when no buttons are pressed, I measured from the 5V arduino pin with the red probe to the swt-gin pins (pull down resistors going to arduino gnd) with the black probe. Those are points.

Could you perhaps give me an example value of what I should be getting and a point in the circuit unrelated to my problem. This would give me more confidence in my measurements. Thanks! :)

markkuki markkuki5 months ago

Update, I completely rebuilt the header pin section with all the resistors and everything for the ribbon cable that goes to the Sparkfun buttonPad. Still same result, "Test LED" code works perfectly but inverted behavior of the Buttons (they are all light up as soon as I upload your "Test Buttons" code and if I press the button the led shuts off when pressed & lights back up as soon as button is released). Should I check anything with the digital pins at the arduino or the HC195 connections?

markkuki markkuki5 months ago

and I tested the buttons with the pushbutton mini circuit and code that is lighting up the LED 13 embedded on the Arduino board. Result = all OK :)

After doing more research, the pull down resistors are behaving like pull up resistors on the switches but I just need help or need to do more research on the pins of the shift registers and arduino digital pins in order to finally isolate the problem.

WP_20150228_01_41_50_Pro.jpg
markkuki markkuki4 months ago

Victory! :) I finally figured it out! On my own, which is obviously the most rewarding way! Anyone else reading this & waiting for a reply from Amanda it might take a while because she went back to school and her studies are taking up a lot of her time and if I understand it correctly she no longer works at Instructables... source re: her website.

amandaghassaei (author)  markkuki4 months ago

great! sorry I couldn't help more what was the problem? Should I change something in the instructable?

No worries at all, I think your instructable is fine. This was my mistake all along. At the header pins I dragged the solder over too much over the pull down resistors (for the l.e.d GND) and then proceeded to make a carbon copy of the same mistake when I rebuilt the header pins on solder and retry. To troubleshoot, I rebuilt the entire circuit on breadboard to be able to make fast changes and disconnect pins at will. Now, I just have to manage to re-solder correctly without burning off any traces otherwise I have to re-do the header pin section one more time (no biggie, whatever it takes). Thanks Amanda for the help thus far, I think soon I will be able to complete the project and your help has been appreciated along the way. Cheers for that and congrats on getting into MIT (I read this on your website or somewhere it was written I'm pretty sure). :)

victory_for_now.png
amandaghassaei (author)  markkuki4 months ago

thanks! keep me posted on your build

liampower10 months ago

I've gotten an adafruit trellis button pad and controller (https://learn.adafruit.com/adafruit-trellis-diy-open-source-led-keypad/overview) which interfaces with the arduino through an on board chip multiplexer, communicating through the i2c protocol. How would I go about converting the sugarcube firmware to work with the adafruit trellis? Is it possible? My coding skills are pretty weak so any help is greatly appreciated.

Thanks

amandaghassaei (author)  liampower7 months ago

you could adapt this to work with the trellis, but you'll have to do a fair amount of coding to get it to work with i2c

mle1010 months ago

When I connect to my computer through the Arduino USB port, I am able to see it in the serial port drop down in Hairless and am able to control MIDI sounds in FL studio but when I connect through the USB of the MIDI to USB cable, I get the message USB not recognized and it does not appear in Hairless. I tested the cable prior to taking it apart and it worked fine. Do you know what could be causing this discrepancy from Arduino USB port and MIDI to USB cable USB port?

amandaghassaei (author)  mle1010 months ago

you should only use hairless if you're connecting through plain old usb, the point of hairless is to convert a "usb" message into a midi message in your computer. If you have a MIDI to usb cable and you are able to get that into fl studio, you should be good to go. right?

pj.jones.589512 months ago

AWESOME!! Whats the total cost? :)

markkuki1 year ago

Amanda, I have multimeter incase you are able to help with troubleshooting. On step 24 right now. After uploading your code, only one row of buttons lights up and they all light up at the same time when pressed (4 LEDs). All other buttons are non-responsive as of now.

NOTE: I am omitting the gyroscope and accelerometer. Note sure if or how much this changes things with the DIP chips? I have been following the schematics until this point and noting your mistakes in the pictures and fixing them as best as I could interpret them.

Steps 21-23 are a lot more confusing than the previous 20 steps.

Documentation is key for others to build properly. I think it is not ideal to show an image and then say "don't do it like that."

Seems you might be on vacation again? Hope you are enjoying it and looking forward to a reply when there is time. :)

IMG_3960.JPG

I'm about to attempt the same thing... I just want the MIDI output part of this build...

My biggest question is this... what portions of the code can I scrap? Obviously, the gyroscope and rotary knobs, but I'm not sure about the rest. Coding Arduino's are still a weak spot of mine...

I basically want to assign each button a MIDI note, as the software I want to control can listen for MIDI notes on each playback button. When the SC button is pressed, it triggers that soundbyte from the software.

amandaghassaei (author)  bacarudaguy1 year ago
If you tie the analog pins to ground it should work as is. If you want to get fancy you can go in the code and comment out the parts where it's grabs accel/gyro data.
amandaghassaei (author)  markkuki1 year ago

did the code that just cycles through the buttons work correctly? I've updated the button schematic, are there other errors in the documentation? the gyro and acc should not affect the code in step 24. Where do I show an image and then say to do it differently?

I replied to baracudaguy an update on how my troubleshooting is going so far and what I have already eliminated as a point of failure. I think I fried my 74HC165 chip somehow but do not have another one on hand and won't be able to buy a new one until Friday morning when I am back home. Are you able to help with troubleshooting techniques to determine if the DIP is dead? Never done that kinda diagnosis before.

re: your question ... Step 22 - 74HC165 Part 3: (fig. 1) "these
should be connected to the analog pins, the design changed while I was
building, please refer to the schematic rather than this image."

Sorry, I just got a little confused because I thought there should be no mention of the analog pins until Step 28 and Step 29. Therefore, it begs the question what you mean by "these" what should be connected to the analog pins instead of digital pins that you were connecting in Step 22?

In my case, I am using 4 potentiometers as Attack, Decay, Sustain, Release for example, so I understand I will be using only 4 analog pins and the rest are free I think.

amandaghassaei (author)  markkuki1 year ago

I realized that I put it in the schematic, but I never mentioned in the text how to power the buttons - I think that may be your problem. Reread steps 19-24, I've made some edits that hopefully help with the clarity. I doubt you have damaged the 165, I've used them a lot and found them pretty sturdy chips.

Markkuki - have you checked all your solder connections on the 4x4 pcb?

Tested so far on Sparkfun PCB / perfboard (I am discretely testing everything (including components I know are working) since I didn't know where the best place would have been to start and this is good practice for me either way):

LEDs = OK (tested with Arduino code from Step 18)

4 x 100 Ohm resistors = OK

Diodes = OK (tested with multimeter to exact instructions that came with multimeter)

Ribbon Clamp Female Pins 1-16 = OK (discretely tested with multimeter)

Male Header Pins 1-16 for Ribbon = OK

NOTE: After cleaning with 91% isopropyl alcohol and toothbrush (believe it or not) now all rows are non-responsive aka not lighing the buttons.

NOTE: Steps not necessarily in the order I preformed each troubleshooting check.

Slowly but surely elimating potential points of failure. As I type this, I am waiting for my perfboard to dry from cleaning and will resolder the SWT GND pins that have the 10K Ohm resistors on them. The continuity I checked OK was at the male header pins but my soldering was messy so not necessarily continious from the lead wires at the header pins going to the 74HC165 socket. Meaning, if I touched certain spots of the joined solders I could not get a signal (multimeter in "beep mode" so to speak).

Furthermore, I do not have another 74HC165 chip to test/swap in... so who knows that DIP could have been defective straight out of the bag since it was not in a anti-static vacuum sealed bag or I damaged somehow by accident.

mle101 year ago

Great project! I am on step 25 and am getting no response from my sugarcube when uploading the code and the running the individual beatslicer app. In step 24, I needed to set the pin modes individually using pinMode() to get it to work. I am using a SainSmart Mega 2560 R3 instead of an arduino uno though. Do you know of any differences between these that would cause some of your code not to work? Any advice would be greatly appreciated!

1-40 of 108Next »