Eduardo Nahmad-Achar
Published © GPL3+

Touchscreen Theremin

Portable pocket-size touchscreen theremin, controlling pitch and note duration.

IntermediateFull instructions provided315
Touchscreen Theremin

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
TFT-LCD Touchscreen shield
×1
Speaker: 0.25W, 8 ohms
Speaker: 0.25W, 8 ohms
×1

Story

Read more

Schematics

Schematic

Just plug in the shield to the Arduino board, and connect the speaker between pin 10 and Ground.

Touchscreen Theremin Front Page

The greeting page, touch screen to proceed...

Code

Touchscreen Theremin

Arduino
Portable touchscreen theremin, for controlling frequency and note duration.
/*
 * Theremin using a 240x320 (2.4") touchscreen.
 * Screen is set in landscape mode. Touch on screen at p reads coordinates p=(x,y).
 * Larger side of screen determines frequency (y), while shorter side determines duration (x).
 * (Attach speaker between digital pin 10 and ground; needs to be a PWM-enabled pin.)
 * 
 * N.B.- tone() clashes with PWM on pins 3 and 9, because they use the same timer.
 * The TFT_LCD touchscreen used here uses most of Arduino UNO's pins, but some are for the SD card.
 * If no SD card is being used, we may use one of the PWM-enabled pins in the SD block, 
 * such as pin 10 used here.
 */

#include <Adafruit_GFX.h> 
#include <MCUFRIEND_kbv.h> 
#include <TouchScreen.h>

MCUFRIEND_kbv tft;          // define tft_lcd object (thin film transistor lcd)

#define MINPRESSURE 500     // to avoid spurious events
// #define MAXPRESSURE 1000

// Touch panels vary; calibrate to get proper pins:
/* 
 These are the pins for the shield coordinates,
 obtained from TouchScreen_Calibr_native example
 (in MCUFRIEND.kvb examples):
*/
#define YP A2  // coordinate y plus
#define XM A1  // coordinate x minus
#define YM 6   // coordinate y minus
#define XP 7   // coordinate x plus

const int TS_LEFT=177,TS_RT=952,TS_TOP=213,TS_BOT=956;    // 240x320 ID=0x9340

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);    // define touchscreen object

#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define CYAN 0x07FF
#define LIGHTGREY 0xC618
#define GREY 0x8410
#define WHITE 0xFFFF

#define sp 10           // pin for speaker (connect speaker between pin 10 and ground;
                        //  needs to be a PWM-enabled pin)

int fMin = 130;         // lowest frequency (C3)
int fMax = 1500;        // highest frequency (C7)
int tMin = 100;         // minimum note duration
int tMax = 1000;        // maximum note duration

TSPoint tp;             // (x,y) coordinates of point touched on screen, and 
                        //  z coordinate for pressure

void setup()
{
  Serial.begin(9600);             // only use for debugging
  pinMode(sp, OUTPUT);            // speaker output
  digitalWrite(sp, LOW);

  tft.reset();
  uint16_t ID = tft.readID();     // get ID of screen

  if (ID == 0xD3D3) ID = 0x9486;  // write-only shield
  tft.begin(ID);
  tft.setRotation(1);             // 0 = portrait; 1 = landscape
  tft.fillScreen(LIGHTGREY);

  //welcome screen
  uint16_t width = tft.width() - 1;
  uint16_t height = tft.height() - 1;
  uint8_t border = 10;
  tft.fillScreen(GREY);
  tft.fillRect(border, border, (width - border * 2), (height - border * 2), WHITE); 
  tft.setTextSize (3);
  tft.setTextColor(RED);
  tft.setCursor ((tft.width()/2)-97, 40);
  tft.println("TOUCHSCREEN");
  tft.setCursor ((tft.width()/2)-70, 85);
  tft.println("THEREMIN");
  tft.setCursor ((tft.width()/2)-17, 160);
  tft.setTextSize (2);
  tft.setTextColor(BLACK);
  tft.println("ENA");
  tft.setTextColor(BLUE);
  tft.setCursor ((tft.width()/2)-95, 250);
  tft.println("Touch to Proceed");

  //wait for touch
  do{
    tp= ts.getPoint(); 
    pinMode(XM, OUTPUT);  // Pins for TFT control
    pinMode(YP, OUTPUT);
    } while(tp.z < MINPRESSURE);
    
  tp.x = map(tp.x, TS_LEFT, TS_RT, 0, tft.width());
  tp.y = map(tp.y, TS_TOP, TS_BOT, 0, tft.height());

  // theremin screen
  tft.fillScreen(LIGHTGREY);
  tft.setTextSize (2);
  tft.setTextColor(BLUE);
}


void loop()
{
  // wait for touch:
  do {
      tp= ts.getPoint(); 
      pinMode(XM, OUTPUT);  // Pins for TFT control
      pinMode(YP, OUTPUT);
     } while(tp.z < MINPRESSURE);
     
  // calculate frequency and duration; display them and output sound to speaker:
   if (tp.z >= MINPRESSURE)
    {
      unsigned int dur = map(tp.x, TS_LEFT, TS_RT, tMin, tMax);     // map to note duration in ms
      unsigned int freq = map(tp.y, TS_TOP, TS_BOT, fMin, fMax);    // map to frequency from C3 to C7
      tft.setCursor ((tft.width()/2)-95, 75);
      tft.print("Frequency: ");
      tft.print(freq);
      tft.print("  Hz");
      tft.setCursor ((tft.width()/2)-95, 125);
      tft.print("Duration: ");
      tft.print(dur);
      tft.print("  ms");

      tone(sp, freq, dur);                    // play note
      
      delay(dur + 100);                       // wait for duration of note + 100ms
      noTone(sp);                             // kill sound
      tft.fillScreen(LIGHTGREY);              // clear screen
      tp.z=0;                                 // reset pressure for next touch
    }
}

Credits

Eduardo Nahmad-Achar
1 project • 0 followers
Contact

Comments

Please log in or sign up to comment.