Engineering Projects/Music projects/Howard Community College/fall2011/502 The Tin Can Band
Electronic Sections Expected
[edit | edit source]Problem Statement
[edit | edit source]From the "Next Steps" section of Music Team:
"The next team must get a note to play based on the analogRead function. This should be done more accurately with a potentiometer at first, rather than just holding the arduino to your temple. A good place to start is with breaking down the code I provided, and figuring out why it does not play a note at any given time (which it should - the if statements just have the pitch of the note different from one another, rather than the presence of a note), and then reconstruct it so that it does play a note.
From there, using previous team's knowledge, it should be possible to connect the Hall Effect Probe to the arduino, pass a magnet through its sensor, and through MIDI shield to arduino to keyboard connections, play a note. At that point, it is fairly easy to get six Hall Effect Probes working on one arduino (using the 7 analog pins provided on the arduino board), and then setting up the the actual tin can to play the notes on a hand crank."
In essence, we were tasked with creating a basic system that plays a note based on the input that is external from the arduino - which the previous team wanted to do via the analogRead function. Additionally, we wanted to be construct a relatively system that plays a note on a keyboard when we pass a magnet through a sensor.
Team Members
[edit | edit source]Summary
[edit | edit source]Over our time with this project, we managed to get a keyboard to interact with a potentiometer using an arduino board and a MIDI shield. There's a code written to do this, however it does have its problems (see the narrative). In order to better analyze these problems, we found a way to print values used by the arduino board in this code to the serial monitor - a window integrated with the arduino environment that allows you to see whatever you want.
Team Weekly Reports:
Poster
[edit | edit source]This is the apparatus used to analyze the resistance and voltage that should be read by the arduino. A digital multimeter was used to read the voltage on the potentiometer pins going into the analog inputs on the MIDI shield. Adjustments made to the potentiometer effect the voltage going into the arduino. This voltage is read as an input with the program, which then produces an output that we were trying to analyze.
Story
[edit | edit source]We updated code from the last project to make it a bit easier to adjust. This way we only have to adjust the int sensorThreshold to test different voltage values.
//Potentiometer Light Code
int sensorValue = 0;
int sensorThreshold = 1023;
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
sensorValue = analogRead(0);
digitalWrite(13, LOW);
if (sensorValue >= sensorThreshold) { //If analogRead reads a value greater than or equal to 512
digitalWrite(13, HIGH); //Light is on
}
if (sensorValue < sensorThreshold) { //If analogRead reads a value less than 512
digitalWrite(13, LOW); //Light is off
}
}
It's obvious just holding an arduino board to our temple isn't nearly an accurate enough way deliver an input for analogRead to interpret. The next logical step before tackling the Hall Effect Probe was to instead use a potentiometer to control the values read by the pin - and instead of having it control a note being played, just turn on the LED in pin 13. Our reasoning for this was because of a potential problem that was discussed with the last group: Using certain analog devices require a baud rate of 9600 bits per second (bps), whereas MIDI Protocol requires 31250 bps. I'm only trying to deal with one problem at a time, so we tried to get consistent results with this code first. We went on to study potentiometers.
What we learned about potentiometers and voltage:
- With the Wikipedia page on Ohms we researched voltage. We found that:
- P = (V^2)/R
- Where P is power in Watts, V is voltage, and R is resistance.
- The potentiometer is used to adjust the resistance, and therefore, the amount of voltage read by the analog pin. Resistance is changed by turning the rod clockwise or counterclockwise.
- There are three wires on the potentiometer. As far as working them with the arduino is concerned, one wire goes to power supply, another ground, and the third to where you wish power to be supplied to.
The potentiometer we used was actually broken - the wire snapped off the first time we tried to put a wire into an arduino pin. It was soldered back on. In order to solder it back on, we had to have a soldering gun/iron, wet sponge, and soldering wire - more detail into the necessary items can be found here. The process of soldering can be fairly complex or simple, depending on the devices used in the process. A detailed explanation for soldering in general can be found here. Once the wire was re-attached, the potentiometer was tested with a multimeter, where it was determined that what we had on hand was a 1 mega-ohm potentiometer.
While looking for the best way to test the potentiometer on the arduino site, we came across a code specifically meant to be used in conjunction with the potentiometer. The code is as follows:
//Reading a Potentiometer Sample Code
int potPin = 0; // select the input pin for the potentiometer
int ledPin = 13; // select the pin for the LED
int val = 0; // variable to store the value coming from the sensor
void setup() {
pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT
}
void loop() {
val = analogRead(potPin); // read the value from the sensor
digitalWrite(ledPin, HIGH); // turn the ledPin on
delay(val); // stop the program for some time
digitalWrite(ledPin, LOW); // turn the ledPin off
delay(val); // stop the program for some time
}
Essentially, what this code does, is it causes the LED on pin 13 to stay lit up, and then turned off, for the value found by the analog pin reading the voltage. It is a very simple way to see how resistance effects the interpreted voltage. The code we refined from the last team's work is similar in this ultimate objective, but goes about it in a different manner; rather, it simply causes the light to turn on once a certain voltage is reached. Initial testing with this code made us realize that our potentiometer, as it currently stood, needed one more wire. We found an old broken one, cut off the wire on that, and soldered it on to our potentiometer. We then hooked it up to the arduino and ran this code. Our results were as follows:
- Our first time testing different resistances, we noticed a kind of electronic burning smell we've only experienced when trying to put together an old computer. Both the board and potentiometer were fine. The smell disappeared after our first attempt.
- Turning the pot fully counterclockwise resulted in a dimly lit LED light that was always on, never blinking.
- Turning the pot fully clockwise resulted in the LED light just being off altogether. Additionally, the power LED would dim and then turn off as well.
- When turning the potentiometer from fully clockwise to counterclockwise, the light still (generally) blinks at a seemingly constant rate, until a certain threshold is reached approximately 1/3rd of the way to fully counterclockwise, at which point the LED light just remains dim, never blinking, like when it's turned fully counterclockwise.
From this test we drew the conclusion that when turned fully clockwise, all power is being diverted from the arduino into the 5v pin, through the unrestricted potentiometer, and into the analog pin, leaving insufficient power for the power LED pin to be used, meaning that resistance is at its lowest when the potentiometer is rotated fully clockwise. Additionally, after the potentiometer is turned counterclockwise past a certain point, the arduino has difficulty reading the voltage in the analog pin because of how little voltage is getting through the potentiometer, and as a result, the light just dims.
We then tried using the Potentiometer Light Code with the arduino, expecting it to stay off when turned fully counterclockwise. As it was turned clockwise, the LED pin should have turned on, and stayed on. Instead, it just remained off at any given position. When fully clockwise, the power LED turned off again, and when it was turned counterclockwise from this position even just a hair, it would come back on. Additionally, the LED pin would blink rapidly for a short length of time, before remaining off. That blink was consistent, and was for a length of time after the potentiometer was moved - how much it was moved, or where it was moved to, had absolutely no discernible effect on the blinking.
To try and get results more similar to what we expected, we tested several solutions:
- Wiring the potentiometer into the arduino differently. We tried several different combinations, but they had no effect.
Note: one wire snapped off while we were trying different combinations. As a result, from here on out, we were only able to test solutions with one wire in the 5v, and one in analog pin 0, and none in grounding. The light just continued to stay on, no matter what we did. Fully clockwise and fully counterclockwise did not dim the LED pin, nor did the power LED turn off when turned fully clockwise.
- We analyzed the code we refined. We found no theoretical problems, but a second opinion is something we're still searching for. Just to try something, we added a delay of 200 milliseconds after the "if" parameters to give the code enough time to reasonable display that the LED is in fact on. This had no effect, so we removed it in all future iterations of testing.
- We checked that our code was reading the right pin number, and that the wires were in the correct pins - they were.
- We experimented with different threshold values. We saw no change in the LED pin.
- 512 - the "halfway" point, or 2.5V
- 1023 - the "maximum" point, or 5v
- 1 - the "minimum" point that could still be interpreted with this code, or 0v
- 736 - an arbitrary value
- 316 - an arbitrary value
- 493 - an arbitrary value
- We tried setting the LED pin to "off" using "digitalWrite(13, LOW);" before any of the if parameters in the void loop. We saw no change in the LED pin, which is strange, because if the analog pin just weren't reading anything, the light should have just been off.
The conclusion we drew was that we would need to re-sodder the wire on that potentiometer before we could continue to test solutions (we did not have the tools necessary at home). What throws us off, however, is the fact that apparently some kind of voltage is being read that causes the LED to turn on, or else the bit of code we threw in to make the default status of the LED pin be "off" would have just kept it off.
After speaking with the instructor, we realized our potentiometer, as it was when we received it, had a connection between the middle and top node (red and blue wires). As a result, they essentially acted as one node, and thus skewed the results of our testing last week in a way we hadn't accounted for. We cut this connection with a pair of wire cutters. Additionally, we decided to just cut off the remaining two wires on the potentiometer - one wire was like the one that had snapped off (brittle), and we weren't sure how much longer it would last, while the other one was fraying and relatively difficult to manage. We snapped these off with wire cutters as well.
We found a "thing" that appeared to be some kind of computer component. The wires were relatively long (~4 in), and the ends were crimped with some kind of metal holding. The ends of them fit perfectly into the arduino pins. We cut a red, green, and blue wire off that, stripped the opposite end of them, and twisted the frayed ends tightly so none were loose. We soldered these three wires to the potentiometer (much better than we did the first time), and they became securely fastened.
The next step was to hook up a digital multimeter to the poteniometer, and analyze the way it would interact with voltage. By hooking up the alligator clips (the multimeter) to two nodes that were not connected yielded a maximum resistance of 1,000,000 ohms - or 1 mega-ohm, which confirmed what was previously found when we first received the potentiometer. By switching the multimeter to read volts, and attaching the alligator clips to the crimped ends of the wires, we found we were able to read the level of voltage going through the potentiometer and into the arduino - essentially being able to see what voltage reading should be read by the arduino.
We attached the red wire to ground, blue wire to analog input pin #0, and the green wire to 5v, one alligator clip to the green wire, the other to blue. Additionally, we uploaded the "Reading a Potentiometer Sample" code into the arduino. The multimeter read ~5.0v while the light blinked incredibly quickly. This is the opposite of what we expected - when the arduino recognizes a higher voltage, it should have a value close to 1023 from analogRead, which was used in the delay timer, and as such should have a slower blinking rate. Despite this, we found these results to be quite consistent. As we adjusted the resistance with the potentiometer, we found that as voltage increased (up to ~5.0v), so did the rate at which the LED pin blinked. The opposite was true as well, ~0.0v had a (relatively) incredibly slow blinking rate whereas we predicted it would have a fast one. We switched which alligator clip was on which wire to see if we somehow gave the wires an inverse relationship with our apparatus, but the multimeter instead read the same values as they originally did, only they were negative. Because the magnitude of the values were not changed, and we weren't sure if voltage was even a scalar quantity, so we put it back the way we originally had it.
Voltage Reading | Qualitative Blinking Rate | Ohms Reading (on 20m scale) |
---|---|---|
0.0 | ~1 seconds | 0.0 |
1.0 | ~0.9 seconds | 10.3 |
2.0 | ~0.7 seconds | [No Reading] |
3.0 | ~0.3 seconds | [No Reading] |
4.0 | ~0.15 seconds | [No Reading] |
5.0 | [Too fast to approximate] | [No Reading] |
This table displays the general trend of voltage vs blinking rate. When the voltage was 2.0, the resistance wasn't being read properly by the multimeter.
Despite the fact that this wasn't precisely what we originally predicted, this was, generally, what we expected to happen - by using the potentiometer to alter resistances (and therefore the voltage read by the analog pin), we were able to change the rate at which the light blinked. The next step for us was to use a code that we had written instead of one we were given. We uploaded the "Potentiometer Light" code into the arduino. We had the sensorThreshold at 1023. Only voltage values interpreted as 1023 should turn the light on; originally we thought that would have been 5.0v, but in light of recent events, we changed our prediction to having the light turn on at ~0.0v. We were right, and went on to test this with a different sensor Threshold value (511).
We loaded this into the arduino, and it loaded fine. At ~3.0v the light was off, however, seemingly arbitrarily, the arduino board just powered off as we were writing down data. The multimeter read ~0.0v, and the power LED was off as well as the LED pin. No matter how qw changed resistance with the potentiometer, none of the lights would come on, and the multimeter continued to read ~0.0v. We started taking parts off the arduino (the clips and potentiometer) to load just the blinking light code to see if we broke the board, but the moment we took one alligator clip off, the board powered back on. It then behaved accordingly, the LED pin turning off at approximately where we predicted, and turning on in a similar manner (We were unable to look at the voltage, as we decided to leave the multimeter disconnected for a little while). After playing with turning the light on/off for a time, we put the alligator clips back on, and everything resumed working as normal. Our theory is that the multimeter was somehow sapping a reserve power from the arduino, but we really have no idea, and had no way to test this theory, as we were unable to reproduce this anomaly; the board worked fine from here on out.
From here we decided that, now that we can effectively use the analogRead to alter an output with the arduino, we went to try and use the Potentiometer Tone Code from the previous team's work. We decided to streamline it a bit, and came up with:
/Potentiometer Tone Code
int sensorValue = 0;
int sensorThreshold = 512;
int LEDpin = 13;
int analogPin = 0;
int timeDelay = 100;
void setup() {
pinMode(LEDpin, OUTPUT);
Serial.begin(31250);
}
void loop() {
sensorValue = analogRead(analogPin);
if (sensorValue >= sensorThreshold) {
digitalWrite(LEDpin, HIGH);
noteOn(0x90, 0x3C, 0x100);
delay(timeDelay);
noteOn(0x90, 0x3C, 0x00);
}
if (sensorValue < sensorThreshold) {
digitalWrite(LEDpin, LOW);
noteOn(0x90, 0x46, 0x100);
delay(timeDelay);
noteOn(0x90, 0x46, 0x00);
}
}
void noteOn(int cmd, int pitch, int velocity) {
Serial.write(cmd);
Serial.write(pitch);
Serial.write(velocity);
}
We just tidied up this code by replacing the pin numbers and delay values with integers. Additionally, we changed the delay in both "if" tests to a constant 100 milliseconds. We tried uploading this, and attaching everything together to play notes on the keyboard. We were met by a constant thumping at a rate of ~0.1 seconds. The light, however, continued to work the way we expected it to, turning on/off after turning the potentiometer approximately halfway (at this point we didn't have access to a digital multimeter).
Solutions we tested that contributed towards playing proper notes:
- We just wanted to see if the board and midi shield were working correctly at all - we tried uploading a code that we knew worked with the keyboard (the "Mary Had a Little Lamb" code), and went to see if that still played properly - it did, so we knew the problem was one with our code, and not the hardware
- We knew that we had the right kind of format for "if" tests in our code because the blinking light test we had just been working on worked fine. However, we weren't sure if keeping the part of the code that effected the LED pin was creating a problem with the note playing, so we just removed that - it didn't do anything noticeable to the code.
- W tried changing the timeDelay in the second "if" test, just to see if we could at least augment the rate at which the keyboard was thumping - and we was succesful. After turning the potentiometer ~halfway, we found a difference in the timing of the thumping. However, it did not play a note.
- We tried removing the "silent" note (the one after the delay with a velocity of 0x00), to no effect.
- We tried implementing a default "else" block instead of the second "if" test, and removing the note in that else block, instead replacing it with turning the LED light on. After initial testing, we realized we needed to have the light actually turn off in case the "if" test were successful so we could appropriately interpret results. The code appeared as such:
int sensorValue = 0;
int sensorThreshold = 512;
int LEDpin = 13;
int analogPin = 0;
int timeDelay = 100;
void setup() {
pinMode(LEDpin, OUTPUT);
Serial.begin(31250);
}
void loop() {
sensorValue = analogRead(analogPin);
if (sensorValue >= sensorThreshold) {
digitalWrite(LEDpin, LOW);
noteOn(0x90, 0x3C, 0x100);
delay(timeDelay);
}
else {
digitalWrite(LEDpin, HIGH);
delay(timeDelay);
}
}
void noteOn(int cmd, int pitch, int velocity) {
Serial.write(cmd);
Serial.write(pitch);
Serial.write(velocity);
}
- It worked as we predicted, the thumping would continue until we turned the potentiometer a certain amount, at which point it would stop and the light would come on. This lead me to believe the problem was in the way the note was being played in the first place.
- We looked at the values we had inside the noteOn function. Command and pitch were fine, however, we looked at velocity - 0x100 is equal to 256 decimal. The range of midi protocol values is [0, 127] (decimal). 256 is way above that, and never would have worked at all. We tried using a hexadecimal value inside this range - 0x40 (64 decimal) - instead of the 0x100 we had just used in our previous code. It worked wonderfully, the note playing at the rate of the timeDelay value we had set until we turned the potentiometer ~halfway, at which point the note would stop, and the light would turn on.
From this point on we kind of just built our code back up, adding new components that we had either stripped it of in trying to get it to function properly, and adding new ones to try and test how far we could take this.
We tried breaking the analogRead value range [0, 1023] into 3 different segments along the intervals: [0, 341), [341, 682), [682, 1023]. Each interval corresponds to its own different note, and which note is chosen is dependent upon the value that analogRead returns from interpreting the voltage. Our end result was this:
int sensorValue = 0; //Creates the sensorValue integer. The value of 0 just holds its place until it can be defined in line 14
int sensorThreshold_A = 341; //The maximum value of the first of the three intervals
int sensorThreshold_B = 682;
/*The maximum value of the second of the three intervals.
Note: the third interval's maximum is defined by the maximum value that analogRead can return
*/
int analogPin = 0; //Use analog pin #0
int LEDpin = 13; //Digital pin #13 has an LED light attached to it
int timeDelay = 100; //An arbitrary small delay value used in all "if" tests
void setup() {
pinMode(LEDpin, OUTPUT); //Allows the LED pin to be turned on
Serial.begin(31250); //Sets the baud rate to comply with midi protocol
}
void loop() {
sensorValue = analogRead(analogPin); //Reads the voltage in analog pin 0(from [0.0, 5.0] volts), and interprets it on an interval [0, 1023]
if (sensorValue < sensorThreshold_A) { //"If" test to see if the sensorValue falls within the first of the three intervals
digitalWrite(LEDpin, LOW); //In case the LED light was on, this turns it off
noteOn(0x90, 0x3C, 0x40); //Plays the first note
delay(timeDelay);
}
if (sensorThreshold_A <= sensorValue < sensorThreshold_B) { //"If" test to see if the sensorValue falls within the second of the three intervals
digitalWrite(LEDpin, LOW); //In case the LED light was on, this turns it off
noteOn(0x90, 0x46, 0x40); //Plays the second note
delay(timeDelay);
}
if (sensorThreshold_B <= sensorValue) { //"If" test to see if the sensorValue falls within the third of the three intervals
digitalWrite(LEDpin, LOW); //In case the LED light was on, this turns it off
noteOn(0x90, 0x50, 0x40); //Plays the third note
delay(timeDelay);
}
else { //Default "else" block, acts as a kind of warning light. Just in case for some reason the sensorValue doesn't pass any of the "if" tests
digitalWrite(LEDpin, HIGH); //Turns the light on
}
}
void noteOn(int cmd, int pitch, int velocity) { //Defines the noteOn function to work with midi protocol
Serial.write(cmd);
Serial.write(pitch);
Serial.write(velocity);
}
This code was met with a moderate amount of success. 3 different notes would in fact play throughout the entire [0, 1023] interval, however they would overlap seemingly random. Further testing into why this occurred is necessary.
After giving a presentation, we were informed of what is called a "serial monitor". It's a way to, with proper coding, look at the actual values specified in the arduino (like the sensorValue I've been using so often). It was our belief that, if we could actually see those values in real time, we'd be able to look at what the arduino was actually producing, and what it should be producing (say it's playing note A when we think it should be playing note B), and would be able to more precisely view any problems.
We looked through the example codes provided for the arduino, and came across the one for use in conjunction with an accelerometer. It used within it, something called "Serial.print", and we were told this had something to do with printing values to the serial monitor. This made sense, so we searched for the function on the arduino site, and found this code:
//Serial.print Example Code
int x = 0;
void setup() {
Serial.begin(9600); // open the serial port at 9600 bps:
}
void loop() {
// print labels
Serial.print("NO FORMAT"); // prints a label
Serial.print("\t"); // prints a tab
Serial.print("DEC");
Serial.print("\t");
Serial.print("HEX");
Serial.print("\t");
Serial.print("OCT");
Serial.print("\t");
Serial.print("BIN");
Serial.print("\t");
Serial.println("BYTE");
for(x=0; x< 64; x++){ // only part of the ASCII chart, change to suit
// print it out in many formats:
Serial.print(x); // print as an ASCII-encoded decimal - same as "DEC"
Serial.print("\t"); // prints a tab
Serial.print(x, DEC); // print as an ASCII-encoded decimal
Serial.print("\t"); // prints a tab
Serial.print(x, HEX); // print as an ASCII-encoded hexadecimal
Serial.print("\t"); // prints a tab
Serial.print(x, OCT); // print as an ASCII-encoded octal
Serial.print("\t"); // prints a tab
Serial.print(x, BIN); // print as an ASCII-encoded binary
Serial.print("\t"); // prints a tab
Serial.println(x, BYTE); // prints as a raw byte value,
// then adds the carriage return with "println"
delay(200); // delay 200 milliseconds
}
Serial.println(""); // prints another carriage return
}
What this code does is it just has a loop of values, ascending from 0 to 63, and prints those values in decimal, hexadecimal, octal, binary, and as a raw byte value. Essentially all of these are useless for our purposes except for decimal, but it's handy information to know that we can print them as things other than decimal.
The way it works is it prints the "titles" ("No Format", "Dec", "Hex", "Oct", "Byte") in a single row, spacing them with a tab ("\t"). The last line for "Byte" uses "Serial.printin", which essentially does the exact same thing as "Serial.print", except, among other things (which are useless for our purposes), creates a new row, ensuring that all values that follow are now on the second row. It then creates a conditional loop with the "for" statement, which just causes the values go from 0 to 63 in ascending order, and the code lists the values in their respective formats (decimal, hexadecimal, etc), creating a new line after the byte value is displayed. Once all 64 values have been displayed, the conditional loop ends, the void loop ends, and the process repeats.
Note: viewing the serial monitor requires setting a baud rate of 9600, meaning it can't be used in conjunction with the MIDI protocol with any of the arduino boards we currently have access to. However, an arduino mega board would sidestep this issue by allowing me to set multiple baud rates.
Wanting to better learn the format, we wrote our own code to be used in conjunction with a potentiometer:
//Serial.print Potentiometer Test Code
int sensorValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(0);
Serial.print("ANALOG READ VALUES");
Serial.print("\n");
Serial.print(sensorValue, DEC);
Serial.print("\n");
delay(500);
}
We used "Serial.print("\n")" instead of "Serial.printin" simply because everything else that comes with Serial.printin is unnecessary. What this code does is it reads the analog pin 0 for a voltage with analogRead, assigns it a value in the range of [0, 1023], and then prints that value in the serial monitor at a rate of two values printed every second. This means that we can see the analog read values in real time. We wanted to test this, so we hooked the potentiometer up to the arduino and loaded the code.
It worked as intended initially - values would change as we changed the resistance with the potentiometer, though we came across some complications. They, along with some basic properties, are listed below:
- Fully clockwise yields a value of 1023, consistently
- Fully counterclockwise yields a value of 0, consistently
- Turning the potentiometer clockwise from fully counterclockwise will still result in values of 0 for a time; at approximately 1/3 of the way turned, it starts returning positive integers that ascend proportionally as it's turned clockwise. We refer to this point as the resistance threshold. A multimeter should be used to analyze why this occurs, but it is consistent, and therefore easy to account for.
- Initial testing of these values resulted in a seemingly random spike as we turned it counterclockwise from fully clockwise. As it descended from 1023, it would randomly spike up to 1023 and stay there as we turned the potentiometer (when we would otherwise expect a value of, for example, 780 that is descending). Our ability to reproduce this was inconsistent, though it was more likely to happen when we turned the potentiometer counterclockwise rapidly.
- Occasionally turning the pot fully counterclockwise resulted in values no longer being returned in the serial monitor (it would just stop), and an error code from the arduino environment. It wouldn't un-"freeze" itself unless we re-uploaded the code altogether. Just closing and then re-opening the serial monitor was insufficient. This error was generally inconsistent, but was more likely to happen when we turned the potentiometer to fully counterclockwise rapidly.
Our method of finding solutions to these problems were, originally, just trying to reproduce the errors, both the one that caused the random spike to 1023, and the "freezing" error. Our results were sporadic and inconsistent, and googling the error yielded nothing useful. However, while the potentiometer was fully counterclockwise, consistently producing a value of 0, we accidentally knocked it and the arduino off the desk, and we saw that we the freezing error had occured. This led us to believe perhaps the error was a hardware one, and when we went to pick it up, we noticed the green and blue wires (which go to the 5v and ground pin in the arduino, respectively), where exposed, were touching. We knew from our understanding that this wouldn't lead to anything good, and that due to the way they were soldered, it would be all too easy for them to touch without us noticing.
We turned the potentiometer fully clockwise (where it should yield a value of 1023), and reset the code. We turned it counterclockwise (very slowly), and the values began to descend, we touched the two wires together, and suddenly they would read only 1023, no matter how we turned the potentiometer. The moment we let go they returned to whatever value they should have been. We tried this below the resistance threshold, and it would still read 1023 when the wires touched. However, most importantly, we turned the potentiometer fully counterclockwise and touched the wires - immediately we were given the "freezing" error. We tested this a few times with the same exact result, but we were afraid of somehow doing damage to the arduino board if we kept it up.
So most importantly we learned to make sure that the ground and 5v wires don't touch where they're exposed, and it'll be fine. Additionally, our sensorValues will return 0 for multiple resistances with this potentiometer.
With this new information, we wanted to test our code for playing a note with the potentiometer. This was however impossible with an arduino duemilanove, and will be until we can get an arduino mega, but we could write a code that is similar, and essentially does the same thing with a blinking light instead of playing a note. So what we wrote was:
//Potentiometer Interval Code
int sensorValue = 0; //Creates the variable "sensorValue", and assigns it a value of 0 until it can be assigned an actual value with analogRead.
int sensorThreshold_A = 341; //[0, 341) represents the first third of the possible range of values from [0, 1023]
int sensorThreshold_B = 682; //[341, 682) represents the second third of the possible range of values from [0, 1023]. The last is defined when values are >= 682
void setup() {
Serial.begin(9600); //Sets baud rate to 9600 so the arduino can interact with the serial monitor
pinMode(13, OUTPUT); //Allows the LED light attached to digital pin #13 to be turned off and on with digitalWrite
}
void loop() {
sensorValue = analogRead(0); //Assigns sensorValue an actual value based on the voltage read in analog pin #0
Serial.print("ANALOG READ VALUES"); //Prints the title "ANALOG READ VALUES" to the serial monitor
Serial.print("\n"); //New line
Serial.print(sensorValue, DEC); //Prints the value read by analogRead to the serial monitor
Serial.print("\n"); //New line
if(sensorValue == 0) { //If the sensorValue reads a value of 0
digitalWrite(13, LOW);
delay(1000); //Causes the light to blink very slowly, 0.5 times in 1 second
digitalWrite(13, HIGH);
delay(1000);
}
if(0 < sensorValue < sensorThreshold_A) { //If the sensorValue reads a value greater than 0, but less than 341
digitalWrite(13, LOW);
delay(500); //Causes the light to blink slowly, 1 time in 1 second
digitalWrite(13, HIGH);
delay(500);
}
if(sensorThreshold_A <= sensorValue < sensorThreshold_B) { //If the sensorValue reads a value greater than or equal to 341, but less than 682
digitalWrite(13, LOW);
delay(250); //Causes the light to blink at a moderate rate, 2 times in 1 second
digitalWrite(13, HIGH);
delay(250);
}
if(sensorThreshold_B <= sensorValue) { //If the sensorValue reads a value greater than or equal to 682
digitalWrite(13, LOW);
delay(100); //Causes the light to blink rapidly, 5 times in 1 second
digitalWrite(13, HIGH);
delay(100);
}
else { //If all other tests fail - for example there is a value for sensorValue that does not meet any of the "if" tests.
delay(500); //Wait half a second, and then repeat the loop, and therefore, all if tests.
}
}
This code behaves similar to the code we wrote earlier, the only difference is that instead of playing a note, it causes the LED light to blink at different rates. Additionally, it accounts for the fact that sensorValue will be equal to 0 for a relatively large section of values, and lets me see the actual values for it in the serial monitor.
Material List
[edit | edit source]Parts necessary to finish this project:
- Arduino 2009 board - used to write code
- MIDI shield - used to give code access to the MIDI protocol
- Keyboard with a MIDI IN attachment - used to play notes
- Tin can - device used to play notes over time
- Several dozen magnets - objects used as "notes" in final product
- 4-7 Hall Effect Probes - used to interpret the magnets as notes
- Means to mount the tin can - used to hold the tin can in place
- Legos to operate a hand crank to move the tin can once mounted - rotates the tin can at will to play music
Parts on hand:
- Arduino 2009 board
- MIDI shield
- Keyboard with a MIDI IN attachment
- Tin can and appropriate mounting/operating devices - Tin can is currently mounted
- 4-7 Hall Effect Probes
- 2 keyboards, one for working at home, the other in class
Parts ordered:
- Arduino mega board, to interact with both the MIDI protocol and serial monitor
Software List
[edit | edit source]Used software:
- Arduino programming environment
Absolutely essential to programming with an arduino. A link to their site can be found here. It's open source, so free to download.
Time
[edit | edit source]- Time estimated to get a note playing based off of analogRead would have been estimated at approximately 5 hours, where in actuality it was closer to 7 or 8.
- Time estimated to get a note playing with a magnet and a hall effect probe was estimated at around 10 hours (15 total) after getting a note to play from analogRead, where in actuality after approximately 18 hours total this still has not been accomplished.
These discrepancies in theoretical and actual time taken to complete projects is due to troubleshooting issues with the potentiometer and with our code. However, work towards getting the arduino to interact with the hall effect probe is now ready to be done after 18 hours work.
Tutorials
[edit | edit source]The story and team pages actually have a fairly good list of explaining everything, however, they are listed here for convenience.
- The MIDI protocol
- Hexadecimal Calculator
- Arduino references
- For those who need a stronger background in musical theory, this is not a horrible place to start.
- Blinking Light Code, used throughout this project to test to see if the arduino board was properly talking to the computer.
- "If" function, used to create conditional statements
- "If... Else" function, used for greater control over conditional statements than just "if"
- "Serial.begin" function, explains baud rate used for when the arduino interacts with various other devices
- "int" function, explains the usage of integers
- "analogRead" function, elaborates on how to read the voltage input from a device
- This explanation gives details about the serial monitor used with the arduino environment
- "Serial.print" function, talks about printing text or values to the serial monitor
- "Serial.begin" with an arduino mega talks about using multiple baud rates in conjunction with the arduino mega board
Next Steps
[edit | edit source]- Write a code based on the potentiometer tone code that allows for viewing in the serial monitor once the arduino mega board has arrived. Figure out why the notes were overlapping when played, and fix it.
- Work on getting the hall effect probe to interact with the arduino in some elementary fashion - get it to turn on a light, or something easy like that.
- Once the hall effect probe is interacting with the arduino, combine the potentiometer tone code with whatever code was used to get the hall effect probe talking to the board in order to play a note when a magnet passes through the sensor.