If statement to play audio continuously when false

Hi, I’m trying to make a gesture triggered speaker, so you hold your hand near the device to hear an audio clip.

My current setup contains the following:

  • Arduino Uno
  • 4 Ohm 3 W speaker
  • Micro SD card module
  • Micro SD card containing audio.wav file
  • HC-SRO4 Ultrasonic Sensor

I want audio.wav to play when I hold my hand near the ultrasonic sensor, stop when I move my hand away, then start from the beginning when I move my hand near again.

I’ve got as far as triggering audio.wav to play when I put my hand near and stop when I move my hand away. My issue is that audio.wav keeps repeating the first second of the audio clip when I put my hand near, and not the whole piece of audio. I’ve tried putting a delay of 10 seconds after the audio.play(“audio.wav”) however this obviously means that if I move my hand away before the 10 seconds is up, the audio carries on.

If anyone knows how I can get the audio to play continuously only when my hand is near the ultrasonic sensor, your advice and ideas would be greatly appreciated. Thanks in advance

Here’s my full code…

#include "SD.h"
#define SD_ChipSelectPin 5
#include "TMRpcm.h"
#include "SPI.h"
#define trigPin 3
#define echoPin 4

TMRpcm audio;

void setup(){
audio.speakerPin = 9;
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
if (!SD.begin(SD_ChipSelectPin)) {
Serial.println("SD fail");
return;
}

audio.setVolume(2);
}

void loop(){
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration / 2) / 29.1;
  Serial.println(distance);
  
  
  if (distance >= 20 || distance <= 0) {
    Serial.println("no object detected");
    audio.stopPlayback();
  }
  else {
    Serial.println("object detected");
    audio.play("audio.wav");
    delay(10000);
  }


  delay(300);
}

You need to detect when your hand becomes close enough, not when your hand is close enough. See the StateChangeDetection example in the IDE

The library you are using has (a lot) more functions than play() and stopPlayback(). It would be worth the trouble to determine ALL the functions that is has.

UKHeliBob:
You need to detect when your hand becomes close enough, not when your hand is close enough. See the StateChangeDetection example in the IDE

Thank you so much for pointing me in the right direction UKHeliBob!
The StateChangeDetection example in the IDE and this tutorial helped

Here’s my current working code…

#include "SD.h"
#define SD_ChipSelectPin 5
#include "TMRpcm.h"
#include "SPI.h"
#define trigPin 3
#define echoPin 4
TMRpcm audio;
int lastSensorState = LOW;   // sensor's previous state
int threshold = 20;   // an arbitrary threshold value

void setup(){
audio.speakerPin = 9;
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
  if (!SD.begin(SD_ChipSelectPin)) {
    Serial.println("SD fail");
    return;
  }
audio.setVolume(5);
}

void loop(){
  int duration, d, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  d = (duration / 2) / 29.1;
  distance = abs(d); //Changes negative results to absolute value
  Serial.println(distance);
  
  // read the sensor:
  int sensorState = distance;
 
  // if it's above the threshold:
  if (sensorState >= threshold) {
    // check that the previous value was below the threshold:
     if (lastSensorState < threshold) {
        // the sensor just crossed the threshold
        Serial.println("Sensor exited the threshold");

        //stop audio
        audio.stopPlayback();
     }
  }  

    // if it's below the threshold:
  if (sensorState <= threshold) {
    // check that the previous value was above the threshold:
     if (lastSensorState > threshold) {
        // the sensor just crossed the threshold
        Serial.println("Sensor entered the threshold");
        
        //play audio 
        audio.play("audio.wav");
     }
  }  
  
  delay(300);

  // save button state for next comparison:
  lastSensorState = sensorState;


}