Simple keyboard using the tone() function

Simple keyboard using the tone() function

This is a thread about the built-in example "Simple keyboard using the tone() function" tutorial and its 02.Digital/toneKeyboard code.

/*
  Keyboard

  Plays a pitch that changes based on a changing analog input

  circuit:
  - three force-sensing resistors from +5V to analog in 0 through 5
  - three 10 kilohm resistors from analog in 0 through 5 to ground
  - 8 ohm speaker on digital pin 8

  created 21 Jan 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

  https://docs.arduino.cc/built-in-examples/digital/toneKeyboard/
*/

#include "pitches.h"

const int threshold = 10;  // minimum reading of the sensors that generates a note

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

void setup() {
}

void loop() {
  for (int thisSensor = 0; thisSensor < 3; thisSensor++) {
    // get a sensor reading:
    int sensorReading = analogRead(thisSensor);

    // if the sensor is pressed hard enough:
    if (sensorReading > threshold) {
      // play the note corresponding to this sensor:
      tone(8, notes[thisSensor], 20);
    }
  }
}

Wokwi simulation: ArduinoBIE_toneKeyboard

Per these posts and these guidelines, if you've got something to say about the example, its schematics, its explanation, or you have a better way of doing it, please share.

I think that this example is a bit awkward, in that is in the digital section but uses force sensitive resistors and analogRead().

It does turn the analog readings into digital decisions with threshold:

...but it doesn't seem like a natural part of the digital section.

A 3-button keyboard might be a natural extension of a one-button setup, but the force sensitive resistors and thresholding logic distract from that. Also, with the for loops, it might be a good example in the control section.

Additionally, the comments seem to be confused about "three" sensors versus "to analog in 0 through 5":

Showing all 6 buttons on analog 0 though 5 to ground would help highlight the utility of arrays and for loops for duplicated circuitry.

For instance:

imagehttps://wokwi.com/projects/427049511998951425

// https://wokwi.com/projects/427049511998951425
// Using an array of buttons

// Adapted from Arduino Built-in example Keyboard
// https://wokwi.com/projects/409953647477353473
// Code from https://docs.arduino.cc/built-in-examples/digital/toneKeyboard
// Other simulations https://forum.arduino.cc/t/wokwi-simulations-for-arduino-built-in-examples/1304754

/*
  Keyboard

  Plays a pitch that changes based on a button press

  circuit:
  - five buttons from ground to A0 to A5
  - 8 ohm speaker on digital pin 8

  modified 2025-04-01
  created 21 Jan 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/toneKeyboard
*/

#include "pitches.h"

const int numberOfKeys = 6;
const int pressedLevel = LOW;  // reading of the keys that generates a note

// notes to play, corresponding to the keys:
int notes[] = {
  NOTE_D4, NOTE_E4, NOTE_C4, NOTE_C3, NOTE_G3, NOTE_C3
};
const int buttons[] = {
  A0, A1, A2, A3, A4, A5
};

void setup() {
  for (int thisKey = 0; thisKey < numberOfKeys; thisKey++) {
    pinMode(buttons[thisKey], INPUT_PULLUP);
  }
}

void loop() {
  for (int thisKey = 0; thisKey < numberOfKeys; thisKey++) {
    // get a sensor reading:
    int sensorReading = digitalRead(buttons[thisKey]);

    // if the sensor is pressed:
    if (sensorReading == pressedLevel) {
      // play the note corresponding to this sensor:
      tone(8, notes[thisKey], 20);
    }
  }
}

For someone working through the digital examples, an array of digitalRead() buttons might be an easier next step.

Or if the toneKeyboard example is meant to demonstrate reading force sensitive resistors with analogRead() and tone(), why not make the force sensitive resistors alter the tones, rather than transform it into a digital signal?

For example:

void loop() {
  for (int thisSensor = 0; thisSensor < 3; thisSensor++) {
    // get a sensor reading:
    int sensorReading = analogRead(thisSensor);

    // if the sensor is pressed hard enough:
    if (sensorReading > threshold) {
      // play the note corresponding to this sensor:
      tone(8, map(sensorReading,threshold,1023,notes[thisSensor],notes[(thisSensor+1)%3]), 20);
    }
  }
}
1 Like

Is it capable of playing chords if you press 3 or more buttons?

No. The for loop quickly cycles through the buttons and changes the frequency on pin 8. More than one button and it will just be muddy.

What if the buttons are polled first and then the tone is generated, would that be doable?

See:

https://forum.arduino.cc/t/playing-chords-with-arduino-and-one-buz

or

or

or their related threads.

That is a dead link. Perhaps you meant Playing chords with Arduino and one buzzer, but that thread contains no solutions.

1 Like