Analog Output Lab
In the analog output lab, we’re learning to make use of code libraries to control servos and speakers.
Controlling a servo
The first project involves a simple servo motor, connected to power, ground and an Arduino PWM pin (digital 9, in this case), and a potentiometer, connected to power, ground, and an Arduino analog input pin.
The code below is loaded on the Arduino. It reads and scales input from the potentiometer, and uses those values to control servo position through the servo library.
// Controlling a servo position using a potentiometer (variable resistor)
// by Michal Rinott
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 179)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
The results can be seen below:
Servo (Full Range) from Jeff Kirsch on Vimeo.
By changing the mapping from this:
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 179)
to this:
val = map(val, 0, 1023, 0, 90); // scale it to use it with the servo (value between 0 and 90)
we’re able to make the full range of the potentiometer only control movement between 0 and 90 degrees, as shown in this second video.
Servo (Partial Range) from Jeff Kirsch on Vimeo.
Controlling a speaker
Using another library, the Tone library, we’re able to easily produce audio from a speaker connected to one of the Arduino’s digital output pins. Analog input is provided by the same potentiometer as before. The code and results are below.
#include <Tone.h>
Tone mytone; // declare a tone name
void setup() {
// initialize the tone
mytone.begin(8);
}
void loop() {
// read the analog input
int inVar = analogRead(0);
// map the input to a frequency range between 200 and 2000 Hz
int note = map(inVar, 0, 1023, 200, 2000);
// play the note
mytone.play(note);
}
Arduino Synth from Jeff Kirsch on Vimeo.
Create something unique
At first, I wasn’t sure where to go with this part of the assignment; just a bit of a brain freeze moment. I decided to use a flex sensor in a voltage divider circuit as an input, put wasn’t sure what I could do with it that wouldn’t be boring.
Then, all it once, it dawned on me. I’d construct a simple tone-matching game.
Tone Game Tour from Jeff Kirsch on Vimeo.
I hooked a second speaker up to the Arduino and wired in the flex sensor, plus a simple momentary push-button switch. The script below does all the work, producing a randomly-generated pitch from one speaker, while controlling the pitch of another tone based on the input from the flex sensor. A simple boolean test determines if the note controlled by the flex sensor is within +/- 5 Hz of the target note, and if so plays a little “success” progression and selects a new target pitch.
#include <Tone.h>
//defines "BUTTON" as "13"
#define BUTTON 13
Tone mytone; // declare a tone name
Tone mytone2; // declare a second tone name
//create integer variable "randTone" to hold random tone values and initilize to 440 Hz
int randTone = 440;
void setup() {
// initialize the tone controlled by the flex sensor
mytone.begin(8);
//initialize the randomly generated "target" tone
mytone2.begin(7);
//begin serial connection for debugging
Serial.begin(9600);
//set BUTTON as an input
pinMode(BUTTON, INPUT); // and BUTTON is an input
}
void loop() {
//run generateRandTone() when button is pressed
if (digitalRead(BUTTON) == HIGH) {
generateRandTone();
}
// read the flex sensor input
int inVar = analogRead(0);
// map the input to a frequency range between 200 and 2000 Hz
int note = map(inVar, 150, 552, 200, 2000);
// play the note
mytone.play(note);
//play the target note
mytone2.play(randTone);
//print the note value to the serial monitor
Serial.println(note, DEC);
//print the target value to the serial monitor
Serial.println(randTone, DEC);
//test for a match. Returns "True" if note is +/- 5Hz away from the target tone.
if ((randTone > note - 5) && (randTone < note + 5)) {
successRoutine();
}
//Delay ensures note must be held to win, and note to "step"
delay(100);
}
//This function sets the variable randTone to a "random" value between 250 and 1900
void generateRandTone() {
randTone = random(250, 1900);
}
//This function runs when the input note is close enough to match the target note. It plays a quick melody based on the target note, then calls generateRandTone() to produce a new target note for the next round.
void successRoutine() {
mytone.play(randTone);
mytone2.play(randTone);
delay(500);
mytone.play(randTone / 2);
mytone2.play(randTone / 2);
delay(1000);
mytone.play(randTone);
mytone2.play(randTone);
delay(1000);
mytone.play(randTone * 2);
mytone2.play(randTone * 2);
delay(1000);
mytone.play(randTone);
mytone2.play(randTone);
delay(1500);
generateRandTone();
}
A video of the game in action: (Warning, the audio is very, very annoying.)
Tone Game Demo from Jeff Kirsch on Vimeo.
Full instructions for the lab available here.
About this entry
You’re currently reading “Analog Output Lab,” an entry on Jeff Kirsch
- Published:
- 10.15.09 / 11am
- Category:
- Coursework, Fundamentals of Physical Computing
- Tags:
Comments are closed
Comments are currently closed on this entry.