How to stop a squealing theremin?

Hello; I'm a rank beginner. I have the Arduino Uno kit and was attempting to make a theremin/proximity sensor using a Sainsmart HC-SR04 ultrasonic sensor (bought on Amazon: Amazon.com) .

I've got the theremin part working fine: as I move my hand in front of the sensor, I get a range of tones in the A minor pentatonic scale...but when I remove my hand so the sensor cannot "see" it, the audio emits a very high squeal (about D7, I think). I want it to be silent when my hand is out of the calibrated range, not to squeal! I see others have asked about this problem, but most of the time they didn't receive an answer...and the few times I found answers, I don't know how to execute them yet.

A possible way to fix it: limit the range (eg: when objects are more than 3 or so feet away, be silent), which might be accomplished by silencing the device when the echo return is 3 milliseconds or more away. But I don't know how to do that. I've tried fiddling with various sections of the code and so far, no success.

If it's not a simple bit of code you can easily show me, perhaps you could direct me to a tutorial or give me some keywords or something to help get me on the right track.

If this is entirely the wrong section to post this question, please let me know which would be the correct section and I'll repost it there (and delete this post if possible), hopefully without incurring the wrath of the Admins :wink:

Thank you very much for any help you can give me!

Here's the code (taken from Arduino Project Hub: Arduino Theremin with A Minor Pentatonic):

/*
   Arduino Theremin with A minor pentatonic scale
   pollux labs, 2020
   All rights reserved.
*/

const int trigger = 5;
const int echo = 4;

const int piezo = 10;

int distance = 0;
int distanceHigh = 0;

int lengthOfScale = 0;

int note = 0;

//A Minor pentatonic scale
int scale[] = {
  147, 165, 196, 220, 262, 294, 330, 392, 440,
  523, 587, 659, 784, 880, 1047, 1175, 1319, 1568,
  1760, 2093, 2349
};

//C Major scale
//int scale[] = {
//  131, 147, 165, 175, 196, 220, 247, 262, 294,
//  330, 349, 392, 440, 494, 523, 587, 659, 698,
//  784, 880, 988, 1047
//};


void setup() {
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);

  while (millis() < 5000) {
    digitalWrite(trigger, HIGH);
    digitalWrite(trigger, LOW);
    distance = pulseIn(echo, HIGH);

    if (distance > distanceHigh) {
      distanceHigh = distance;
    }
  }

  for (byte i = 0; i < (sizeof(scale) / sizeof(scale[0])); i++) {
    lengthOfScale += 1;
  }
}

void loop() {
  digitalWrite(trigger, HIGH);
  digitalWrite(trigger, LOW);

  distance = pulseIn(echo, HIGH);

  note = map(distance, 250, distanceHigh, scale[0], scale[lengthOfScale - 1]);

  for (byte j = 0; j < (lengthOfScale); j++) {

    if (note == scale[j]) {
      tone(piezo, note);
      break;
    }
    else if (note > scale[j] && note < scale[j + 1]) {
      note = scale[j];
      tone(piezo, note);
      break;
    }
  }
  delay(30);
}

Here's what the hardware looks like:
Connect the cables for VCC and GND to your Arduino Uno with 5V and GND.
The cable from the echo pin on the sensor is connected to digital pin 4, Trig is connected to digital pin 5.First, connect the four wires to your ultrasonic sensor.
Connect the cables for VCC and GND to your Arduino Uno with 5V and GND.


Next, plug the piezo buzzer directly into the Arduino at the opposite pin header. Plug one leg into GND and the other into digital pin 10.

AAnd
hh
Arduino Theremin with A Minor Pentatonic

To stop it making any noise you need to call a function noTone() which isn't anywhere in your code so far. So after you set distance you will need to check to see if it is very high, maybe greater than distanceHigh and if it is then call noTone() otherwise carry on to do all the existing note code.

Give it a try and see how you get on. If you have problems post your attempt here and we can probably sort it out for you.

Steve

You use an if statement to see if the distance is too great, then as slipstick said call no tone. Like this at the start of your loop function

 void loop() {
  digitalWrite(trigger, HIGH);
  digitalWrite(trigger, LOW);

  distance = pulseIn(echo, HIGH);
  if(distance > maxDistance) noTone() ; return

Now all you have to find is the value to give the variable maxDistance.
Make a version of the code that prints out the distance and see what it is. Then declare that variable to be slightly less than this value outside of a function.

Thank you for your help! Can you please tell me how to define the maxdistance variable? I tried plugging in your snippet of code at the beginning of the loop function, but it's complaining that "maxdistance not declared in this scope." Then I farted around trying to define it as a constant with the other constants...no go, won't load. It doesn't actually need to be a variable--I just want it to be 3-4 feet, or an echo distance of about 3 milliseconds. Can I just plug that number in somehow? or if we can just tell it to noTone once distancehigh is exceeded, that would also work...but as this is my first project, I have no idea how to do that. I also tried taking the whole contraption outside, so that there would be no wall echoes, etc. to confuse the ultrasonic sensor...but it still makes a tone when I take my hand away—though for some reason, it's much lower, several octaves lower than the squeal it makes indoors, but not the silence I'm seeking.

Thanks again for your patience! Meanwhile I'll go slog through some more tutorials... :wink:

I think greater than 'distanceHigh' is the value you should use. That's why in #1 I said "maybe greater than distanceHigh".

Steve

Can you please tell me how to define the maxdistance variable?

int maxDistance = 1000;

At the start of the code, outside of any function. The value here of 1000 should be replaced by the actual number you find works.

It doesn't actually need to be a variable

True, just put a number in place of the variable name in the if statement.

if we can just tell it to noTone once distancehigh is exceeded, that would also work...

Yes that is what that if statement is doing.

Can you try what I told you:-

Now all you have to find is the value to give the variable maxDistance.
Make a version of the code that prints out the distance and see what it is. Then declare that variable to be slightly less than this value outside of a function.

What results do you get?

Can you consider that this project is too complex for you at this time and you might be better served learning some simple code technique like the examples that are in the IDE.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.