RSS

Key Matrix – Hardware

Short update today.

This last week has been an immensely stressful one. A lot of things had suddenly and horribly gone wrong, but a combination of hard work and coffee have well and truly sorted them out. Embarrassingly, what appeared as the largest and most serious problem turned out to be a dead battery. After I’d finished banging my head against the wall, I set about completing the key matrix.

Having finished wiring up the buttons, I went about testing them. I was worried for a while as I was obtaining unreliable results when testing them individually, but once everything was plugged in at once, it turned out fine, which was a massive relief. Below are a few photos of the completed matrix.

The last update to make is in affixing the veroboard to the instrument. I tried glueing it down, but it wasn’t as robust as I hoped, so I’ve drilled a few holes and am going to try and attach them soon with more solid methods.

               

One of the most frustrating things to come out of this project is the sheer cost of replacing the components I keep accidentally destroying. I call this “The Graveyard of Dead Arduinos”.

I’m on my third Arduino now. Each one has been broken in different ways, all due to my own stupidity, such as pumping too much voltage into the Arduino or accidentally rerouting a high voltage to the wrong place. If I can say one thing to those reading this:

Be very careful where you stick things.

I guess you could apply that advice to more than just electronics, but that’s entirely up to you.

 
Leave a comment

Posted by on May 10, 2012 in Uncategorized

 

More MIDI Problems and Solutions; Hardware

Well, I’ve managed to work out a way to get my notes and buttons to function in the way I want them to, but it’s come at a bit of a cost.

The way I’ve worked it means that I can now have a MIDI note play when the button is pressed down and switch off when it is released. At the moment, however, this only works for the first 6 buttons. When I attempt to make this work for the next set of buttons, IE the second ‘chunk’ of the key matrix, it simply does not register. I am looking into this now, and hope to have it sorted soon.

What I have decided to do for the moment is concentrate on the hardware side of the project. My reasoning is that once the hardware is completed, the software should be easier to work through. At the moment the hardware (IE the wires, Arduino, battery etc) is rather scattered around the desk, and on several occasions I have accidentally knocked or unhooked something when moving the Synthelodeon due to its delicate state. Once I have made it robust, working on the software and coding will be much less stressful.

The first thing I needed to acquire were some taller buttons. The tactile switches I were using at the moment were good for testing, but were not suitable for the final device.

As can be plainly seen, the left buttons are much taller and more suitable than the right ones, as the actual switch protrudes above the wires.

I made the decision to build a second matrix as opposed to removing the buttons from the first key matrix and and replacing them with the newer, taller ones. Although this would take a fair while longer, it is a much safer route to take. If I made a mistake, for example, when replacing the buttons, it could prove disastrous for the whole circuit, whereas this way any mistakes are relatively contained.

Once I had copied the key matrix with the new buttons, I started working on a piece of wood to cover it. I simply found a piece of MDF, whittled a few holes in and stopped. I’ll make it look more appropriate eventually, but for now I just wanted a basic, working cover.

The cover out of the way, I started work on the left hand. I haven’t worked with the left hand at all yet, but it is a simple extension of the key matrix. The hard part is trying to maintain a singular key matrix on two separate pieces of veroboard. I have not yet completed this side, but here it is at the moment:

Incidentally, the tangled mess I mentioned earlier is clearly viewable here.

 
Leave a comment

Posted by on May 6, 2012 in Uncategorized

 

The Benefits of Being Airtight

If there’s one problem I’ve come across that has been the most frustrating, other than having to replace broken parts that I stupidly broke myself, it’s been the issue of sealing the instrument to make it airtight.

As mentioned before, the way that the pressure is being measured is with a pressure sensor fed with a pipe. As the instrument is moved, the pressure changes. Simple! A huge issue, then, is the instrument being airtight. Any small cracks or holes can cause a drop in the measurable pressure, meaning it’s harder to utilise.

The Synthelodeon has been an awkward beast to tame when it comes to sealing it. Firstly, to cover the holes, I nailed a piece of wood large enough to cover each hole onto the body of the Melodizer. After realising there was some form of air leakage, I then attempted to seal up the gaps with PVA glue. When PVA hardens, it forms a brilliant translucent substance that works perfectly for sealing up small holes in wood.

As you can see, there were a few places that needed sealing. Once it had dried, I attempted to use it again, only to discover more holes. So, back to the PVA…

This was the second time. The same thing happened again! So now, as I write this, I’m waiting for the third coat of PVA, in which I have now covered the instrument, to dry.

 
Leave a comment

Posted by on April 21, 2012 in Uncategorized

 

A quick MIDI issue solution!

Done! Well, sort of. I have managed to, with use from this fabulous website tutorial, make a midi note button only play when the button is pressed down. I’ll update properly soon; this is just a minimal update to chronicle how it’s been going with one button. I haven’t tried using multiple buttons yet. 

Here’s hoping it’ll all work smoothly! 

(Famous last words.)

 
Leave a comment

Posted by on April 20, 2012 in Uncategorized

 

A quick MIDI issue update.

Just a quick update here. Having built and tested my MIDI interfacing, I’ve come up against a nasty problem. Whenever the Arduino code loops, it checks to see if a button is being pressed, then it will administer a ‘NOTE ON’ MIDI function if it is. This sounds fine in writing, but you end up with a tremolo effect, which is undesirable. 

I’m working on a way to work around this bug. Somehow, I’m going to make the Arduino realise it only needs to give a new ‘NOTE ON’ message if there wasn’t one previously.

Incidentally, I realise I haven’t posted this yet, so here is my code in its entirety as it stands. It’s not complete, it’s fairly messy, it only tends to around half of the key matrix, but it’s what I have:


int oldBP = 0;
int BP = 0;
int BP2 = 0;
const int numReadings = 50;

int readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average

int inputPin = A0;

void setup() {
Serial.begin(31250); // opens serial port, sets data rate to 9600 bps
pinMode(1, OUTPUT); //
pinMode(2, OUTPUT); //
pinMode(3, OUTPUT); //
pinMode(4, OUTPUT); //
pinMode(5, OUTPUT); //
pinMode(6, OUTPUT); //
pinMode(7, INPUT); //
pinMode(8, INPUT); //
pinMode(9, INPUT); //
pinMode(10, INPUT); //
pinMode(11, INPUT); //
pinMode(12, INPUT); //
}

 

void loop() {

// subtract the last reading:
total= total – readings[index];
// read from the sensor:
readings[index] = analogRead(inputPin);
// add the reading to the total:
total= total + readings[index];
// advance to the next position in the array:
index = index + 1;

// if we’re at the end of the array…
if (index >= numReadings)
// …wrap around to the beginning:
index = 0;

// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits

BP = average / 6;
BP2 = (((average / 6) *-1) + 187);

delay (5); //FIRST CYCLE

digitalWrite(2, HIGH);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);

if (BP < oldBP) { //PULL
if (digitalRead(7) == HIGH) {
SendMidi (0x90, 45, BP2); //A
SendMidi (0x80, 42, BP); //Fsharp
}}
if (BP > oldBP) { //PUSH
if (digitalRead(7) == HIGH) {
SendMidi (0x90, 42, BP); //Fsharp
SendMidi (0x80, 45, BP2); //A
}}

if (BP < oldBP) { //PULL
if (digitalRead(8) == HIGH) {
SendMidi (0x90, 49, BP2); //Csharp
SendMidi (0x80, 45, BP); //A
}}
if (BP > oldBP) { //PUSH
if (digitalRead(8) == HIGH) {
SendMidi (0x90, 45, BP); //A
SendMidi (0x80, 49, BP2); //Csharp
}}

if (digitalRead(7) == LOW) { //STATIONARY
SendMidi (0x80, 45, BP2); //A
SendMidi (0x80, 49, BP); //Csharp
}
if (digitalRead(8) == LOW) { //STATIONARY
SendMidi (0x80, 45, BP2); //A
SendMidi (0x80, 42, BP); //Fsharp
}

if (BP < oldBP) { //PULL
if (digitalRead(9) == HIGH) {
SendMidi (0x90, 52, BP2); //E
SendMidi (0x80, 50, BP); //D
}}
if (BP > oldBP) { //PUSH
if (digitalRead(9) == HIGH) {
SendMidi (0x90, 50, BP); //D
SendMidi (0x80, 52, BP2); //E
}}

if (BP < oldBP) { //PULL
if (digitalRead(10) == HIGH) {
SendMidi (0x90, 55, BP2); //G
SendMidi (0x80, 54, BP); //Fsharp
}}
if (BP > oldBP) { //PUSH
if (digitalRead(10) == HIGH) {
SendMidi (0x90, 54, BP); //Fsharp
SendMidi (0x80, 55, BP2); //G
}}

if (digitalRead(9) == LOW) { //STATIONARY
SendMidi (0x80, 50, BP2); //D
SendMidi (0x80, 52, BP); //E
}
if (digitalRead(10) == LOW) { //STATIONARY
SendMidi (0x80, 54, BP2); //Fsharp
SendMidi (0x80, 55, BP); //G
}

if (BP < oldBP) { //PULL
if (digitalRead(11) == HIGH) {
SendMidi (0x90, 59, BP2); //B
SendMidi (0x80, 57, BP); //A
}}
if (BP > oldBP) { //PUSH
if (digitalRead(11) == HIGH) {
SendMidi (0x90, 57, BP); //A
SendMidi (0x80, 59, BP2); //B
}}

if (BP < oldBP) { //PULL
if (digitalRead(12) == HIGH) {
SendMidi (0x90, 61, BP2); //Csharp
SendMidi (0x80, 62, BP); //D
}}
if (BP > oldBP) { //PUSH
if (digitalRead(12) == HIGH) {
SendMidi (0x90, 62, BP); //D
SendMidi (0x80, 61, BP2); //Csharp
}}

if (digitalRead(11) == LOW) { //STATIONARY
SendMidi (0x80, 57, BP2); //A
SendMidi (0x80, 59, BP); //B
}
if (digitalRead(12) == LOW) { //STATIONARY
SendMidi (0x80, 61, BP2); //Csharp
SendMidi (0x80, 62, BP); //D
}
// SECOND CYCLE

digitalWrite(2, LOW);
digitalWrite(3, HIGH);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);

if (BP < oldBP) { //PULL
if (digitalRead(7) == HIGH) {
SendMidi (0x90, 64, BP2); //E
SendMidi (0x80, 66, BP); //Fsharp
}}
if (BP > oldBP) { //PUSH
if (digitalRead(7) == HIGH) {
SendMidi (0x90, 66, BP); //Fsharp
SendMidi (0x80, 64, BP2); //E
}}

if (BP < oldBP) { //PULL
if (digitalRead(8) == HIGH) {
SendMidi (0x90, 67, BP2); //G
SendMidi (0x80, 69, BP); //A
}}
if (BP > oldBP) { //PUSH
if (digitalRead(8) == HIGH) {
SendMidi (0x90, 69, BP); //A
SendMidi (0x80, 67, BP2); //G
}}

if (digitalRead(7) == LOW) { //STATIONARY
SendMidi (0x80, 64, BP2); //A
SendMidi (0x80, 66, BP); //Csharp
}
if (digitalRead(8) == LOW) { //STATIONARY
SendMidi (0x80, 67, BP2); //G
SendMidi (0x80, 69, BP); //A

}

if (BP < oldBP) { //PULL
if (digitalRead(9) == HIGH) {
SendMidi (0x90, 71, BP2); //B
SendMidi (0x80, 74, BP); //D
}}
if (BP > oldBP) { //PUSH
if (digitalRead(9) == HIGH) {
SendMidi (0x90, 74, BP); //D
SendMidi (0x80, 71, BP2); //B
}}

if (BP < oldBP) { //PULL
if (digitalRead(10) == HIGH) {
SendMidi (0x90, 73, BP2); //Csharp
SendMidi (0x80, 78, BP); //Fsharp
}}
if (BP > oldBP) { //PUSH
if (digitalRead(10) == HIGH) {
SendMidi (0x90, 78, BP); //Fsharp
SendMidi (0x80, 73, BP2); //Csharp
}}

if (digitalRead(9) == LOW) { //STATIONARY
SendMidi (0x80, 71, BP2); //B
SendMidi (0x80, 74, BP); //D
}
if (digitalRead(10) == LOW) { //STATIONARY
SendMidi (0x80, 73, BP2); //Csharp
SendMidi (0x80, 78, BP); //Fsharp
}

if (BP < oldBP) { //PULL
if (digitalRead(11) == HIGH) {
SendMidi (0x90, 76, BP2); //E
SendMidi (0x80, 81, BP); //A
}}
if (BP > oldBP) { //PUSH
if (digitalRead(11) == HIGH) {
SendMidi (0x90, 81, BP); //A
SendMidi (0x80, 76, BP2); //E
}}

if (digitalRead(11) == LOW) { //STATIONARY
SendMidi (0x80, 76, BP2); //E
SendMidi (0x80, 81, BP); //A
}

delay(1);

 

oldBP = BP;

}

void SendMidi (int cmd, int value, int vel) {
Serial.write (cmd);
Serial.write (value);
Serial.write (vel);
}

 
Leave a comment

Posted by on April 17, 2012 in Uncategorized

 

Implementing MIDI, Part Two

So, we’ve sorted out the problems. They were, for reference:

  1. Finding the right cable to interface MIDI with the computer;
  2. Arduino writing the data as MIDI;
  3. Finding some way of reading the MIDI data created by Arduino;
  4. Setting the readings from the pressure sensors to act as the volume for the midi notes;
  5. Altering the pitch of the note based on the pressure;
  6. Inverting the amplitude when the melodeon was drawn;
  7. Preventing minute fluctuations in pressure from altering the note’s pitch.

Seven nasty problems, but almost all of them have been sorted in one way or another, or at least addressed and considered. I will pay attention to the solutions of each in turn below.

1. Cable

This could have easily been the most problematic in a lot of ways. The simple issue was finding hte right cable! I managed to get my hands on a 5-pin DIN to DIN to USB cable, which was perfect, and also was lucky enough to secure a 7 pin female DIN connector, so it was little trouble wiring it up and utilising it.

2. Writing MIDI

Writing MIDI was possibly the largest problem I had encountered up until this point. MIDI data can only be read in a certain way, and thus obviously can only be written using a specific method. It took a fair bit of reading and working with my aforementioned colleague, Jason Gollings, to finally suss out what was needed, and it turned out to be fairly simple. Once you understand the basics, writing MIDI in Arduino is dead simple:

First, just remember that MIDI is made up of three basic things: the Command, the Pitch (also known as Value) and the Velocity. Below, the coding command for Arduino to create MIDI, called SendMidi (), can be seen with 3 pieces of data after it, inside the brackets. The 0x90 is the

Command, and is in hecideximal format. The Command tells the Arduino whether to turn the note on or off. In this case, the 0x90 is telling the Arduino “Turn the note On”. The 0x80 is the same, but tells the Arduino to turn the note off.

The second piece of data is the Pitch, or Value. MIDI understands that the number 45 corresponds to a particular pitch of note, in this case, A. 42 corresponds to F sharp. The note name is after the command, written with a // before it, meaning it is regarded as a comment and ignored, as far as coding is concerned.

Lastly, the BP and BP2 in this case refer to the velocity. Normally, this would be a number, ranging from 0 to 127, but in this case, it is made of two letters. The BP stands for Bellows Pressure, and refers to the pressure coming in from the sensors. This is then scaled to a number between 0 and 127 and applied as Velocity.

Other things to notice from this screengrab: The first part, the “if (BP <  oldBP) {” etc, means simply: “if the Bellows Pressure now is smaller than it was a few milleseconds ago, then do the following, if not, move on down the code”. I need this distinction to allow different notes to play from the same button, so long as the Melodeon is moving in different directions.

To complete the code, the following snippet needs to be included at the bottom of the sketch:

To be honest, I’m not sure why, but take it from me, you need it.

3. Reading MIDI

This was, as I discovered later, not as huge a problem as I had at first thought. MIDI requires a BAUD rate of 32500, and Arduino cannot naturally read data at 32500, which simply meant that if I tried to read the data through the Arduino’s Serial.print function I would just get a string of gibberish. This is exactly what did happen to me, until I discovered a program called Midi Monitor, and since then I’ve been able to accurately read MIDI data on the computer, alongside Arduino.

4. Utilising Pressure as Volume

 Most of this was covered way, way back in part 2, but not all of it, so I’ll continue about pressure here. The pressure readings I was getting from the sensors consistently gave me measurements of around 6x what I needed. As I said earlier, MIDI notes can only be written as between 0-127 in volume, so a small amount of scaling was needed.

BP = (average / 6);   //BP = Bellow Pressure

And that was it!

5. Altering the Pitch based on Pressure

It seems simple on paper, but this was surprisingly tricky to figure out. We should refer back to this screenshot:

As I mentioned earlier, the above code says “if BP is smaller than oldBP, do something, if not, do something else”. One of the hardest things to figure out was obtaining a ‘previous’ rating, the ‘oldBP’ command. I needed to come up with a way to tell the Arduino to remember a previous value and compare it to the current value, in this case, the BP, or the value obtained from inside the bellows. Eventually, I wrote the following piece of code to be placed at the end of the sketch:

What this says, in layman’s, is “wait for one millisecond and then make ‘oldBP’ equal to ‘BP'”. Combined with another delay function at the beginning of the loop, this means the BP value is attributed to oldBP, to be used as desired.

Hopefully, the above image should start to make sense!

6. Inverting the Amplitude

Another problem I mentioned in my last post. Normally, the harder you pull or push the instrument, the louder the note is. The way I had coded my Synthelodeon meant the harder you compressed it, the louder the note, and the harder you drew it, the quieter, which was obviously wrong. The following formula sorted out that problem for me:

BP2 = (((average / 6) *-1) + 187);

The astute pedants amongst you may notice I’ve changed the value to + 187 from +127, and this is because the notes on the draw were not large enough. The ‘average’ command is a reference to the solution for the next problem:

7. Fluctuations

The minor fluctuations in air pressure was something I hadn’t considered until it became a problem. It necessitated the implementation of an average function in the code to allow the velocity of the midi notes to move more gradually, meaning there wouldn’t be hundreds of note changes every second per button. The code was fairly complex, and I have copied it from the Arduino website. It looks like the following:

const int numReadings = 50;

int readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average

 

// subtract the last reading:
total= total – readings[index];
// read from the sensor:
readings[index] = analogRead(inputPin);
// add the reading to the total:
total= total + readings[index];
// advance to the next position in the array:
index = index + 1;

// if we’re at the end of the array…
if (index >= numReadings)
// …wrap around to the beginning:
index = 0;

// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits

BP = average / 6;
BP2 = (((average / 6) *-1) + 187);

 

There are dozens of comments all overthe code that explain the purpose and funtino much better than I could, so I encourage you to read them yourself, but basically it says: “take 50 readings of the pressure and make a moving average of the lot”. I haven’t quite got this part perfected yet; it’s hard to get a balance between taking too many readings for an average and not enough. Too many slows the response of the instrument and makes the note-changing function lethargic, but not enough readings makes the fluctuations too great. You may be able to see what I mean with the link below (the first clip of the Synthelodeon in action!):

 

So, a lot of problems, and a lot of solutions! There is still room for improvement, of course, but the end is in sight.

Synthelodeon in action!

 
Leave a comment

Posted by on April 12, 2012 in Uncategorized

 

Implementing MIDI, Part One

So, here we go! I haven’t properly and entirely implemented MIDI yet, as in there are still a few nasty bugs in the system. Below is a rough timeline of what happened:

First: I encounter MIDI with regards to Arduino for the first time. I found a few articles, namely this one and this one, and having read them it seemed that using MIDI shouldn’t be too hard at all. After all, MIDI data is just numbers, and the Arduino is perfect for converting analogue signals into numbers, so it should all just work, right?

Wrong.

The first problem was in finding the right cables. The ports on either end of MIDI cables have a specific shape, known as DIN connectors. Traditionally, MIDI cables have 5 pins (though in fact only 3 of these are used), and although I couldn’t find a 5 pin DIN cable, I managed to find a 7 pin, which works just as well. This was fairly simple to wire up, and I also got my hands on a MIDI-to-USB cable for interfacing with my computer.

The second problem I came across was in what is known as the ‘Baud Rate’. I don’t know much about it, but what I do know is this: The Arduino’s ‘Serial Monitor’ (the program used to represent what is going on inside the Arduino with simple text and numbers) uses a rate of 9600, whereas MIDI needs 32500. This means that if a user tries to view the MIDI data within the Arduino program, all they get is a string of gibberish. I used a program called ‘Midi Monitor‘ to allow me to understand what MIDI data my computer was reading/writing.

The third problem was writing data from the Arduino in MIDI format. Several of my fellow students, especially Jason Gollings (whose fascinating blog can be found here), were also working with MIDI, and found that some older versions of the Arduino software were not able to write MIDI data properly, which had caused a lot of scratched heads before we realised this. I owe Jason a drink for his help in understanding MIDI. A little further probing uncovered we needed to use ‘hexidecimal format’, a style of writing numbers and commands that MIDI understands.

The fourth problem was in figuring out how to use readings from the pressure sensor to set the amplitude of the MIDI note. This wasn’t as huge a problem as I thought it would be, and after a simple conversion of vales to fall within the range of 0-127 (the maximum and minimum data vales that MIDI can understand with regards to volume) this problem seemed sorted. At least, that’s I thought, until I ran into:

The fifth problem was figuring out how to change the note depending on the direction of the bellows. How will I write the code so the Arduino knows in which direction the bellows are moving and alter the notes accordingly?

The sixth problem was concerning amplitude. Consider this: at this moment I had managed to create a system that could create a note when a button was pressed and the bellows were squeezed with the amplitude being set by the BP (Bellows Pressure), ie the higher the BP the higher the amplitude. However, when the Synthelodeon was drawn, the pressure would decrease, and although the note would correctly change, the amplitude was inverted, ie the harder you drew the instrument, the quieter the note. This was totally the opposite of what I needed! I eventually sorted this bug by a short mathematical formula:

Drawn_Bellow_Amplitude = (((average / 6) *-1) + 127);

The ‘average’ function brings me to my next problem:

The seventh problem was a later one. I had finally figured out a way to create MIDI notes that could change pitch depending on the BP, change amplitude (in both directions), be read and written by an Arduino and interpreted by any software that used MIDI to write music, such as Logic Pro. I found, however, that as the Arduino was reading Pressure Vales thousands of times a second, with minutely fluctuating results, that as far as the Arduino could understand, the bellows were moving in and out hundreds of times a seconds, with gradual upwards or downwards trends, much like a stock market graph. By implementing an ‘average’ section of code, I was able to take about 30 readings and calculate a moving average on-the-fly, giving a much nicer, smoother rating.

As this is rather text-heavy and long, the MIDI saga will be continued in part 2.

 
Leave a comment

Posted by on April 4, 2012 in Uncategorized