Instrument One (1)

A MIDI instrument - using a PS2 Trackpad as the primary input. See Arduino for my other projects.

Status

The hardware is complete. Software is one of those things, like any artistic rendition, is never complete. However it now successfully plays MIDI scales (semitone stpes for now).

Eye Candy

  • The hardware was built with long wires to make prototype changes easily
  • There is no secondary board, so you will see a few resistors for LEDs and MIDI
  • As Bare Bones boards are $17AUS (2008) there is no connectors - soldered direct
  • There is lots of space in this box to help with prototype
  • Serial access is available externally to allow updated programming (via USB/Serial adapter)
  • On the far side (you can't see) is the 5 pin MIDI DIN Female connector

Hardware

Components required:

  • Arduino Bare Bones board
  • PS2 Mouse or Trackpad or Trackpoint or Trackball - what ever you like
  • 2 LEDs and 1K resistors
  • 2 Input buttons (no resistor needed - Atmel chip has internal pull up resistor)
  • On/Off button for power
  • Power plug for 9 volt battery
  • Case to put it all in
  • DIN5 Connector and 220 ohm resistor for MIDI Connector

What about the Hardware status

  • COMPLETE
    • Building the basic box with PS2 and a couple of LEDs and Buttons (April 2008)
      • LED1 - Status flash - tells us everything is fine
      • LED2 - Information / Feedback
        • Currently flashes 3 times each time a note is sent.
        • Future: Feedback for button presses - e.g. MIDI Channel Change
      • Button1 - Ready for software, e.g. MIDI Channel Change
      • Button2 - Ready for software, e.g. Reset to defaults
      • PS2 Connection
        • Including 2 buttons
  • FUTURE
    • External PS2 Port - allow external PS2 devices such as Mouse or Ball
    • Separate hardware - allow Trackpad to be stuck to clothes (very small)
    • Use the 6 Analogue inputs for Knock Sensors (see [[Intrument2?]]) or further inputs
    • Consider adding further buttons for input
    • Consider an LCD for diagnostics - or at least a LED Segment (via driver)

Software

There are many versions - here is a bash and status.

  • COMPLETE
    • Test PS2 and Hardware to standard Serial (via USB cable) (April 2008)
    • Play MIDI notes through to standard MIDI device (April 2008)
    • Use Trackpad to play notes on MIDI (April 2008)
  • Work in Progress
    • Smooth notes - emulate a theramin
      • Use the Pitch Bender to simulate smooth transition
    • Input Filters
      • Movement is semitone or octave - make spaces between
    • Filter Controls
      • Use buttons on PS2 to control notes being Semitone (default), Tone, Scale (tone, tone, semitone) etc.
    • Repeat
      • Have the box continually repeat notes
      • Hold down a mouse button to use the pad to change frequency and pause (x vs y)
  • Future
    • Talk to Brooke Penrose about stage use / purpose

Useful Stuff

MIDI

What most people don't realise about MIDI is that it is not just a connection to an instrument but the full standard right down to the hardware. So building a MIDI device is building a device that speaks roughly RS232 Serial, only at the Baud Rate of 31250.

Programming MIDI only requires basic serial access but at an unusual port. I am using the internal UART, but I assume software serial could also be used.

PS2

I rewrote from scratch the PS2 library for accessing a keyboard without hardware interrupts and completely non-blocking. It worked, but only some times due to Keyboard output being quite fast and often 2 or 3 bytes worth for one key press. In a tight loop it worked fine but not while doing other things. I will need to go back to looking at hardware interrupt.

Unfortunately this PS2 library is blocking, which means you can't do anything else while waiting for a key press from a keyboard.

This is not an issue with a mouse - you just set the mouse into batch mode and only get data once you ask for it. In this way I can use the PS2 driver as is.

Internal Pull up

My experience with other hardware lead me to use pull up resistors on my inputs and then just pull to ground as floating proved to be just that - random high/low.

What I learnt is that Atmel chips have an internal pull up resistor, so you just need to turn that on and then you can wire your inputs to ground.

NOTE: Either way this offers no protection - so use optic isolators for long wires or unreliable inputs.

References

  • Arduino bare bones board
  • XXX PS2 Library
  • XXX Example MIDI

Source

Here is some of the source...

MIDI Control

Taken from XXX

/* ----------------------------------------------------------------------
 * MIDI - Notes on/off etc
 */

#define midiChannel 1

// Send a MIDI note-on message.  Like pressing a piano key
void noteOn(byte channel, byte note, byte velocity) {
  midiMsg( (0x90 | (channel<<4)), note, velocity);
}

// Send a MIDI note-off message.  Like releasing a piano key
void noteOff(byte channel, byte note) {
  midiMsg( (0x90 | (channel<<4)), note, 0);
}

// Send a general MIDI message
void midiMsg(byte cmd, byte data1, byte data2) {
#ifdef DEBUG
  Serial.print("Command = ");
  Serial.print(cmd, HEX);
  Serial.print(", Data1 = ");
  Serial.print(data1, DEC);
  Serial.print(", Data2 = ");
  Serial.print(data2, DEC);
  Serial.println();
#else
  Serial.print(cmd, BYTE);
  Serial.print(data1, BYTE);
  Serial.print(data2, BYTE);
#endif
}

Read mouse and Set Note

Use this is the main loop to read a mouse and set the note...

  /* get a reading from the mouse */
  mouse.write(0xeb);  // give me data!
  mouse.read();      // ignore ack
  mstat = mouse.read();
  mx = mouse.read();
  my = mouse.read();

  // Current values - keep within Maximums (using factors)
  if (mx != 0) {
    currentX += mx;
    if (currentX < 0) { currentX = 0; }
    if (currentX > (maxNote * factorNote)) { currentX = maxNote * factorNote; }
    currentNote = currentX / factorNote;
  }
  if (my != 0) {
    currentY += my;
    if (currentY < 0) { currentY = 0; }
    if (currentY > (maxVol * factorVol)) { currentY = maxVol * factorVol; }
    currentVol = currentY / factorVol;
  }
  
    // Turn off last note (if it has changed)
    if (currentNote != lastNote) {
      infoSet(3);  // XXX Demonstration - 3 flashes each time note change
      noteOff(midiChannel, lastNote + offsetNote);
      lastNote = currentNote;
      lastVol = currentVol;
      // Turn on new note - this may not be required if no change !
      noteOn(midiChannel, currentNote + offsetNote, currentVol + offsetVol);
    }