Arduino Code

The Arduino code presented below works equally well on all Trinket/GEMMA versions: v1, v2 and M0. But if you have an M0 board, consider using the CircuitPython code on the next page of this guide, no Arduino IDE required!
Here's the sketch, it's pretty simple.

  • As more or less light hits the face of the CdS photo cell, the resistance changes
  • When the resistance changes, the voltage on the analog pin will vary up and down
  • We read the analog voltage from the analog pin
  • We 'scale' the analog voltage to a frequency, then 'beep' the piezo buzzer to match
  • ...and repeat!
Don't forget! You need to set the speaker pin as an output like in the setup function. While the beep waveform will appear on the pin without it, it will not drive the piezo correctly.
/* Adafruit Trinket/Gemma Example: Simple Theramin

  Read the voltage from a Cadmium Sulfide (CdS) photocell voltage
  divider and output a corresponding tone to a piezo buzzer

  Wiring: Photocell voltage divider center wire to GPIO #2
  (analog 1) and output tone to GPIO #0 (digital 0)

  Note: The Arduino tone library does not work for the ATTiny85 on the
  Trinket and Gemma.  The beep function below is similar.  The beep
  code is adapted from Dr. Leah Buechley at
  http://web.media.mit.edu/~leah/LilyPad/07_sound_code.html
*/

#define SPEAKER   0    // Speaker connected to this DIGITAL pin #
#define PHOTOCELL 1    // CdS photocell connected to this ANALOG pin #
#define SCALE     2.0  // You can change this to change the tone scale

void setup() {
  // Set SPEAKER pin to output to drive the piezo buzzer (important)
  pinMode(SPEAKER, OUTPUT);
}

void loop() {
  // Read PHOTOCELL analog pin for the current CdS divider voltage
  int reading = analogRead(PHOTOCELL);
  // Change the voltage to a frequency.  You can change the values
  // to scale your frequency range.
  int freq = 220 + (int)(reading * SCALE);
  // Output the tone to SPEAKER pin.  You can change the '400'
  // to different times (in milliseconds).
  beep(SPEAKER, freq, 400);
  delay(50); // Delay a bit between notes (also adjustable to taste)
}

// The sound-producing function
void beep (unsigned char speakerPin, int frequencyInHertz, long timeInMilliseconds)
{ // http://web.media.mit.edu/~leah/LilyPad/07_sound_code.html
  int  x;
  long delayAmount = (long)(1000000 / frequencyInHertz);
  long loopTime = (long)((timeInMilliseconds * 1000) / (delayAmount * 2));
  for (x = 0; x < loopTime; x++) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(delayAmount);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(delayAmount);
  }
}

You will note the tone function used in the Uno lesson is not used. The Arduino IDE does not implement tone for the ATtiny85 used for the Trinket and Gemma.

The beep function in the code above will work in a similar fashion. It does not use the hardware pulse width modulation on the microcontroller, so you may use it to output a tone signal on any digital pin you have free.

This guide was first published on Sep 19, 2013. It was last updated on Sep 19, 2013.
This page (Arduino Code) was last updated on Jul 13, 2020.