An Arduino Uno or Adafruit Metro or other handy microcontroller may be used to make a sound controller. 

The controller will read some buttons and output a tone based on which button is pressed.

If you would like to build this based on the parts you have on hand, a Pro Trinket, a Feather, etc. then there are very few changes to the code other than the pin numbers that the switches and speaker are connected to. The check switches code sees if a switch has been pressed. It uses software switch debouncing to ensure a positive push.

The design below contains an Adafruit audio amplifier on the tone output. This allows one to be further away from the robot and have the robot "hear" the command tones. You can try a piezo speaker shown in the diagram without the amplifier and speaker. If you find your range is not as far as you like, you can add the amplifier and speaker. The tradeoff is you'll be making louder sounds possibly annoying those around you. You can adjust the amplification with the volume control.

I had the 4 button keypad on hand, allowing for left, right, forward, and stop. You can use a larger keypad with a bit of decoding code and use buttons such as 2 for forward, 8 for reverse, 5 for stop, 4 for left, 6 for right. If you would like to add additional commands, you can look at the chart on the "Using the Microphone" page to select the frequencies best to use. Be careful, if you use two tones that are close in frequency they might fall near the same bin on detection and the robot code would not interpret the tone correctly. This is why the 5 tones chosen are several bins away from each other.

// Tone Generator for the Circuit Playground Simple Robot
// Using a set of buttons, play predetermined tones to control the Circuit Playground simple robot
// Anne Barela for Adafruit Industries   September, 2016

const int speakerPin = 11;       // Uno pin 11, Circuit Playground pin 5

// here is where we define the buttons that we'll use. button "0" is the first, button "3" is the 3rd, etc
// uint8_t buttons[] = { 1, 0, 3, 2 };  // for a second Circuit Playground
uint8_t buttons[] = { 4, 3, 6, 5 };     // for Arduino Uno
#define DEBOUNCE 10  // button debouncer, how many ms to debounce, 5+ ms is usually plenty
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons) 
// we will track if a button is just pressed, just released, or 'currently pressed' 
int8_t pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

uint16_t notes[] = { 2795, 3250, 3700, 4192 };  // control tones in Hertz

void setup() { 
  uint8_t i;

  pinMode(2, OUTPUT);   // Ground for 
  digitalWrite(2, LOW); //  the 4 button keypad ground (eases wiring on Uno)
  // Make input & enable pull-up resistors on switch pins
  for (i=0; i < NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT_PULLUP);  
  pinMode(speakerPin, OUTPUT);  // The piezo speaker pin is set as an output

void loop() {
  check_switches();      // when we check the switches, we'll get their current state

  for (uint8_t i = 0; i < NUMBUTTONS; i++) {  // we check the state of the buttons
    if (pressed[i]) {
      //     digitalWrite(13, HIGH);
      // is the button pressed down at this moment
    if (justreleased[i]) { // on button release . . 
       tone(speakerPin, notes[i], 1000);  // Play the tone assigned to the button for 1 second
  for (uint8_t i=0; i < NUMBUTTONS; i++) {  // remember, check_switches() will necessitate clearing the 'just pressed' flag
    justpressed[i] = 0;

void check_switches()
  static int8_t previousstate[NUMBUTTONS];
  static int8_t currentstate[NUMBUTTONS];
  static long lasttime;
  uint8_t index;
  if (millis() < lasttime){ // we wrapped around, lets just try again
     lasttime = millis();
  if ((lasttime + DEBOUNCE) > millis()) {
    // not enough time has passed to debounce
  // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  lasttime = millis();
  for (index = 0; index < NUMBUTTONS; index++){ // when we start, we clear out the "just" indicators
    justreleased[index] = 0;
    currentstate[index] = digitalRead(buttons[index]);   // read the button
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      pressed[index] = !currentstate[index];  // remember, digital HIGH means NOT pressed
    //Serial.println(pressed[index], DEC);
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
Here is the tone generator circuit in a generic plastic box. The robot is next to it.

For short term use, you can use a 9 volt battery and 9 volt barrel adapter clip to power the tone generator. If you plan on heavy use, a 6xAA battery pack would be a better choice.

This guide was first published on Oct 12, 2016. It was last updated on Mar 08, 2024.

This page (Build the Controller) was last updated on Mar 08, 2024.

Text editor powered by tinymce.