Servo motor with sound sensor

I am running the following code to run the motor activated by sound. Need help with code to run the motor for 1 minute before stopping when the "digitalValue==LOW". Thanks


// Include the library
#include <Servo.h>

// Create the servo object
#define servoPin 9

Servo myservo;

// Create a variable to store the servo position:
int  angle = 0;

 
int  sensorDigitalPin = 3;    // Select the Arduino input pin to accept the Sound Sensor's digital output
int  digitalValue;            // Define variable to store the digital value coming from the Sound Sensor
int  Led13 = 13;              // Define LED port; this is the LED built in to the Arduino (labled L)
                             
void setup()
{
  pinMode(sensorDigitalPin,INPUT);  // Define pin 3 as an input port, to accept digital input
  pinMode(Led13,OUTPUT);            // Define LED13 as an output port, to indicate digital trigger reached
  myservo.attach(servoPin); // attach the servo to our servo object
  myservo.write(0);
}
    
void loop(){
  
  digitalValue=digitalRead(sensorDigitalPin); // Read the value of the digital interface 3 assigned to digitalValue 
  
  if(digitalValue==HIGH)    // When the Sound Sensor sends signal, via voltage present, light LED13 (L)
  
 { 
  // scan from 0 to 180 degrees
  for(angle = 0; angle < 180; angle++)  
  {                                  
    myservo.write(angle);               
    delay(15);                   
  } 
  // now scan back from 180 to 0 degrees
  for(angle = 180; angle > 0; angle--)    
  {                                
    myservo.write(angle);           
    delay(15);       
  } 
} 

else
    
  {
    myservo.write(0); // stop the motor
  }
  
 
}

For timing events, use the millis() function. Have a look at this excellent Blink Without Delay tutorial: https://www.baldengineer.com/blink-without-delay-explained.html

Hi,
Welcome to the forum. Thanks for posting your code in code tags.

I am confused about the question. What are you seeing now? Does your servo do a sweep when digitalValue is HIGH?

Are you wanting the servo to do this when digitalValue is LOW?
Or do you want to have the servo keep doing a sweep back and forth for one minute when digitalValue is LOW?

Yes , the servo sweeps 0-180 when it is high, but stops as soon as the sound is gone.

I am trying to use this on a swing cradle for a baby to swing when crying is detected., and would like it to sweep for a little while after baby stops crying.

Thanks for the tip. I will look into it.

I have used millisTimer with another project.

  if (digitalValue == HIGH) // When the Sound Sensor sends signal, via voltage present, light LED13 (L)
  {
    unsigned long startTime = millis();
    while (millis() - startTime < 60000ul)
    {

Ok, that should be easy enough to fix.

What you would want to do is to have a variable which stores the current time as long as the sensor is HIGH. Then set a 1 minute timer without delay, as per jremington above.

Lets assume everything after the if(digitalValue==HIGH) above is a function called sweepServo().

Pseudo-code could be like this (not tested):

long timeOfLastSweep = 0;
long extraTime = 1000*60*1; // millisec in second * sec in min * minutes of extra sweep

if(digitalValue==HIGH) {
  timeOfLastSweep = millis();
  sweepServo();
}

if (digitalValue == LOW) {
  if (millis() - timeOfLastSweep < extraTime) {
    sweepServo()'
}

}


Thanks for your prompt reply and advise. Worked perfectly.`// Include the library

#include <Servo.h>

// Create the servo object
#define servoPin 9

Servo myservo;

// Create a variable to store the servo position:
int  angle = 0;


int  sensorDigitalPin = 3;    // Select the Arduino input pin to accept the Sound Sensor's digital output
int  digitalValue;            // Define variable to store the digital value coming from the Sound Sensor
int  Led13 = 13;              // Define LED port; this is the LED built in to the Arduino (labled L)

void setup()
{
  pinMode(sensorDigitalPin, INPUT); // Define pin 3 as an input port, to accept digital input
  pinMode(Led13, OUTPUT);           // Define LED13 as an output port, to indicate digital trigger reached
  myservo.attach(servoPin); // attach the servo to our servo object
  myservo.write(0);
}

void loop() {

  digitalValue = digitalRead(sensorDigitalPin); // Read the value of the digital interface 3 assigned to digitalValue

  if (digitalValue == HIGH) // When the Sound Sensor sends signal, via voltage present, light LED13 (L)

  {
    unsigned long startTime = millis();
    while (millis() - startTime < 80000ul)


    {
      // scan from 0 to 180 degrees
      for (angle = 0; angle < 180; angle++)
      {
        myservo.write(angle);
        delay(15);
      }
      // now scan back from 180 to 0 degrees
      for (angle = 180; angle > 0; angle--)
      {
        myservo.write(angle);
        delay(15);
      }
    }
  }

  else

  {
    myservo.write(0); // stop the motor
  }


}`

Thanks for your quick reply and advise. I tried your solution, but could not get the servo to stop. I would appreciate if you can take a look at the code and let me know what I did wrong as I am very new at this.

// Include the library
#include <Servo.h>

// Create the servo object
#define servoPin 9

Servo myservo;

// Create a variable to store the servo position:
int  angle = 0;


int  sensorDigitalPin = 3;    // Select the Arduino input pin to accept the Sound Sensor's digital output
int  digitalValue;            // Define variable to store the digital value coming from the Sound Sensor
int  Led13 = 13;              // Define LED port; this is the LED built in to the Arduino (labled L)

long timeOfLastSweep = 0;
long extraTime = 1000 * 60 * 1; // millisec in second * sec in min * minutes of extra sweep

void setup()
{
  pinMode(sensorDigitalPin, INPUT); // Define pin 3 as an input port, to accept digital input
  pinMode(Led13, OUTPUT);           // Define LED13 as an output port, to indicate digital trigger reached
  myservo.attach(servoPin); // attach the servo to our servo object
  myservo.write(0);
}

void loop() {

  digitalValue = digitalRead(sensorDigitalPin); // Read the value of the digital interface 3 assigned to digitalValue

  if (digitalValue == HIGH) // When the Sound Sensor sends signal, via voltage present, light LED13 (L)

  {
    timeOfLastSweep = millis();

    {
      // scan from 0 to 180 degrees
      for (angle = 0; angle < 180; angle++)
      {
        myservo.write(angle);
        delay(15);
      }
      // now scan back from 180 to 0 degrees
      for (angle = 180; angle > 0; angle--)
      {
        myservo.write(angle);
        delay(15);
      }
    }
  }

  if (digitalValue == LOW) {
    if (millis() - timeOfLastSweep < extraTime)

    {
      // scan from 0 to 180 degrees
      for (angle = 0; angle < 180; angle++)
      {
        myservo.write(angle);
        delay(15);
      }
      // now scan back from 180 to 0 degrees
      for (angle = 180; angle > 0; angle--)
      {
        myservo.write(angle);
        delay(15);
      }
    }
    else

    {
      myservo.write(0); // stop the motor
    }
  }
}

Hi,
sorry about not getting back to you sooner. Was out of town.

I looked at your code and reviewed why the servo was not stopping: the extra sweep time had to be folded into the part where the servo is first checked and activated.

I also created a simple function called servoSweep. Please look at it first: you will find that it is simply your code for sweeping back and forth once only. It is declared at the beginning and the definition is at the end. The Arduino IDE does not require the declaration but I find it a good C++ habit to get into. Other IDEs will not allow a function to be used before declaration.

I also don't have access to the sensor you are using, so I did INPUT_PULLUP for the sensor pin and used a push button for testing purposes, which of course means that HIGH and LOW had to be swapped.

I also threw in a bunch of print statements.

Something I have not fixed is that only when the program first starts, the sweep for 1 minute activates even if the push-button is not pressed. I will leave that up to you to see if you can fix that, if needed.

Hope this helps. Please let us know.

// Include the library
#include <Servo.h>

#define servoPin 9
Servo myservo;  // Create the servo object

int  angle = 0; // Create a variable to store the servo position:
int  sensorDigitalPin = 3;    // Select the Arduino input pin to accept the Sound Sensor's digital output
int  digitalValue;            // Define variable to store the digital value coming from the Sound Sensor
int  Led13 = 13;              // Define LED port; this is the LED built in to the Arduino (labled L)

long timeOfLastSweep = 0;
long extraTime = 1000 * 60 * 1; // millisec in second * sec in min * minutes of extra sweep

void servoSweep(); // declare the servoSweep function

void setup() {
  pinMode(sensorDigitalPin, INPUT_PULLUP); // Define pin 3 as an input port, to accept digital input
  pinMode(Led13, OUTPUT);           // Define LED13 as an output port, to indicate digital trigger reached
  myservo.attach(servoPin);         // attach the servo to our servo object
  myservo.write(0);
  Serial.begin(115200);
}

void loop() {
  digitalValue = digitalRead(sensorDigitalPin); // Read the value of the digital interface 3 assigned to digitalValue
  Serial.print("digitalValue in low: ");
  Serial.println(digitalValue);

  if (digitalValue == LOW) // When the Sound Sensor sends signal, via voltage present, light LED13 (L)
  {    
    Serial.print("Time of Last Sweep in low: ");
    Serial.println(timeOfLastSweep); 
    servoSweep();

  timeOfLastSweep = millis();
  }

  if (digitalValue == HIGH) {
    Serial.print("Time of Last Sweep in high: ");
    Serial.println(timeOfLastSweep);

    if (millis() - timeOfLastSweep < extraTime) {
      Serial.print("Difference betwenn millis and last sweep time: ");
      Serial.println(millis()-timeOfLastSweep);
      Serial.println();

      servoSweep();
    }
    else  {
      myservo.write(0); // stop the motor
    }
  }
}

void servoSweep(){
      for (angle = 0; angle < 180; angle++)  {
        myservo.write(angle);
        delay(15);
      }      
      for (angle = 180; angle > 0; angle--)  { // now scan back from 180 to 0 degrees
        myservo.write(angle);
        delay(15);
      }
}

Thanks for taking time to evaluate my code. It is greatly appreciated.

I have run your code with sound sensor. Servo start moving as soon as the code is uploaded and do not stop. Also, it never triggers the (digitalValue == HIGH) even when the LED is active.

If I take the servoSweep(); command out of the following section, servo do not start at the beginning and reacts to sound. However, it stops after one sweep and sweep one time again when sound is detected

 if (digitalValue == LOW) // When the Sound Sensor sends signal, via voltage present, light LED13 (L)
  {    
    Serial.print("Time of Last Sweep in low: ");
    Serial.println(timeOfLastSweep); 
    servoSweep();

serial monitor:

17:33:02.532 -> digitalValue in low: 0
17:33:02.532 -> Time of Last Sweep in low: 0
17:33:07.961 -> digitalValue in low: 0
17:33:07.961 -> Time of Last Sweep in low: 5421
17:33:13.420 -> digitalValue in low: 0
17:33:13.420 -> Time of Last Sweep in low: 10842
17:33:18.844 -> digitalValue in low: 0
17:33:18.844 -> Time of Last Sweep in low: 16264
17:33:24.247 -> digitalValue in low: 0
17:33:24.247 -> Time of Last Sweep in low: 21685
17:33:29.685 -> digitalValue in low: 0
17:33:29.685 -> Time of Last Sweep in low: 27107
17:33:35.109 -> digitalValue in low: 0
17:33:35.109 -> Time of Last Sweep in low: 32528
17:33:40.530 -> digitalValue in low: 0
17:33:40.530 -> Time of Last Sweep in low: 37950
17:33:45.978 -> digitalValue in low: 0
17:33:45.978 -> Time of Last Sweep in low: 43371
17:33:51.376 -> digitalValue in low: 0
17:33:51.376 -> Time of Last Sweep in low: 48793
17:33:56.796 -> digitalValue in low: 0
17:33:56.796 -> Time of Last Sweep in low: 54214
17:34:02.236 -> digitalValue in low: 0
17:34:02.236 -> Time of Last Sweep in low: 59636
17:34:07.658 -> digitalValue in low: 0
17:34:07.658 -> Time of Last Sweep in low: 65057
17:34:13.072 -> digitalValue in low: 0
17:34:13.072 -> Time of Last Sweep in low: 70478

Here is a suggestion for keeping the servo from doing a sweep at the start:

long extraTime = 1000 * 60 * 1; // millisec in second * sec in min * minutes of extra sweep
long timeOfLastSweep = extraTime;

I just ran the code again and it seems to work.

Remember, I am using a pull-up resistor and a button.
So, my logic is opposite. Is your sensor HIGH when active? If so, please reverse the logic in my code.