ITP Notebook

Lab: Tone Output Using an Arduino

September 23, 2020

Physical Computing

Lab Guide

In this lab I learned how to program an Arduino to create sound. I began by wiring my breadboard to connect the Arduino to analog input and a speaker output.

The two FSRs wired in series creates a voltage divider, eliminating the need for any pulldown resistors. Pressing one or the other changes the resistance ratio being tracked by the Arduino code.

Creating a voltage divider with two FSRs Creating a voltage divider with two FSRs

One modification I had to make to the code was to add the delay call which allows the tone to execute for 100 milliseconds before the next tick.

void setup() {
  Serial.begin(9600);
}

void loop() {
  // get sensor reading:
  int sensorReading = analogRead(A0);
  // map the results to pitch range:
  float frequency = map(sensorReading, 0, 1024, 100, 1000);
  // change the pitch, play for 10 ms:
  if (frequency > 31 && frequency < 40000) {
    tone(8, frequency, 100);
  }
  delay(100);
}

Running this code, pressing the left FSR increases the pitch while pressing the right FSR decreases the pitch.

Controlling the pitch using the FSRs

The next step was to upload a static melody that would play when the Arduino starts up. This code sets up the melody for Shave and a Haircut, Two Bits.

#include "pitches.h"
 
// notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3,NOTE_G3, NOTE_GS3, NOTE_G3,0, NOTE_B3, NOTE_C4};
 
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {4,8,8,4,4,4,4,4 };

void setup() {
  // iterate over the notes of the melody:
  for (int thisNote = 0; thisNote < 8; thisNote++) {
    // to calculate the note duration, take one second
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000/noteDurations[thisNote];
    tone(8, melody[thisNote],noteDuration);
 
    //pause for the note's duration plus 30 ms:
    delay(noteDuration + 30);
  }
}
 
void loop() {
  // no need to repeat the melody.
}

The melody plays once on startup.

'Shave and a Haircut, Two Bits' melody

I then changed the wiring by adding a third FSR and connecting each FSR to its own input pin as well as to ground with a pulldown resistor.

Wiring three FSRs to use as note triggers Wiring three FSRs to use as note triggers

The following code treats each FSR as a button that activates when a certain pressure threshold is reached.

#include "pitches.h"

const int threshold = 100; // minimum reading of the sensors
const int speakerPin = 8;
const int noteDuration = 20;

// notes to play, corresponding to the 3 sensors:
int notes[] = { NOTE_A4, NOTE_B4, NOTE_C3 };
// FSR pins
int pins[] = { A0, A1, A2 };

void setup() {}

void loop() {
  for (int thisSensor = 0; thisSensor < 3; thisSensor++) {
    // get a sensor reading:
    int sensorReading = analogRead(pins[thisSensor]);
    // if the sensor is pressed hard enough:
    if (sensorReading > threshold) {
      // play the note corresponding to this sensor:
      tone(speakerPin, notes[thisSensor], 50);
      delay(50);
    }
  }
}

Each FSR is now mapped to a note, creating a three-key musical instrument.

Playing notes using FSRs