Servo stops with PCM

The following code has two motion detectors with two servo motors and a sound file. The motion is detected and then moves the servos and plays sound.

On the first iteration the servo works as expected but after the sound plays the next and following iterations the servo no longer moves. But on each motion detection the sound works but no servo motion.

This is on an UNO and the servos and sound are connected with external power.

I figure it has something to do with how the loop works but I am not sure what to try next. Any suggestions?


#include <PCM.h>
#include "angryBirdSound.h"
int soundLength = 0;

#include <PWMServo.h>

PWMServo ltservo, rtservo;  // create servo object to control a servo


int pos = 0;    // variable to store the servo position
long rnum;
int ltWing=9;
int rtWing=10;

int ledPin = 13;                // choose the pin for the LED
int backNest = 7;               // choose the input pin (for PIR sensor)
int frontNest = 8;
int pirState = LOW;             // we start, assuming no motion detected
int backVal = 0;                    // variable for reading the pin status
int frontVal = 0;                    // variable for reading the pin status

#include <loopTimer.h>
#include <millisDelay.h>
#include <BufferedOutput.h>

//Example of using BufferedOutput to release bytes when there is space in the Serial Tx buffer, extra buffer size 80
createBufferedOutput(bufferedOut, 80, DROP_UNTIL_EMPTY);

millisDelay soundDelay;
millisDelay servoDelay;


void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.println(i);
    delay(500);
  }
  bufferedOut.connect(Serial);  // connect buffered stream to Serial
  
  servoDelay.start(500); // start the ledDelay, toggle every 1000mS
  soundDelay.start(1000); // start the printDelay, print every 5000mS
  
  ltservo.attach(ltWing);  // attaches the servo on pin 9 to the servo object
  ltservo.write(0);
  rtservo.attach(rtWing);
  rtservo.write(0);
  //randomSeed(analogRead(0));
  
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(backNest, INPUT);     // declare sensor as input
  pinMode(frontNest, INPUT);     // declare sensor as input
  
  //soundLength = sizeof(angryBirdSound);
  soundLength = sizeof(smallSound);

  //startPlayback(sample, sizeof(sample));

}

// the task method
void playSound() {
  if (soundDelay.justFinished()) {   // check if delay has timed out
    soundDelay.repeat(); // start delay again without drift
    //ledOn = !ledOn;     // toggle the led
    bufferedOut.print("play sound");
    //startPlayback(angryBirdSound, soundLength);
    startPlayback(smallSound, soundLength);

    //digitalWrite(led, ledOn ? HIGH : LOW); // turn led on/off
  } // else nothing to do this call just return, quickly
}

void moveServo() {
  if (servoDelay.justFinished()) {
    servoDelay.repeat(); // start delay again without drift
    for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        ltservo.write(pos);              // tell servo to go to position in variable 'pos'
        rtservo.write(pos);
        delay(3);                       // waits 15ms for the servo to reach the position
    }

     delay(1000);

    for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
       ltservo.write(pos);              // tell servo to go to position in variable 'pos'
       rtservo.write(pos);
       delay(3);                       // waits 15ms for the servo to reach the position
    }
    //delay(1000);
    //bufferedOut.println(millis());   // print the current mS
    
  } // else nothing to do this call just return, quickly
}


void loop()
{
  
  bufferedOut.nextByteOut(); // call at least once per loop to release chars
 // loopTimer.check(bufferedOut); // send loop timer output to the bufferedOut

  backVal = digitalRead(backNest);  // read input value
  frontVal = digitalRead(frontNest);  // read input value
  if ((backVal == HIGH) || (frontVal == HIGH)) {            // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    if (pirState == LOW) {
      // we have just turned on
      bufferedOut.print("Motion detected!");

      //Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
      
      //startPlayback(angryBirdSound, sizeof(angryBirdSound));
      //startPlayback(smallSound, sizeof(smallSound));
      
      moveServo();
      playSound();

/*
      for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        ltservo.write(pos);              // tell servo to go to position in variable 'pos'
        rtservo.write(pos);
        delay(3);                       // waits 15ms for the servo to reach the position
      }

      delay(1000);

      for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
        ltservo.write(pos);              // tell servo to go to position in variable 'pos'
        rtservo.write(pos);
        delay(3);                       // waits 15ms for the servo to reach the position
      }
      //delay(1000);
      //startPlayback(angryBirdSound, soundLength);
      delay(3000);
*/

    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    if (pirState == HIGH){
      // we have just turned of
      bufferedOut.print("Motion ended!");
      //Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}



What are these and do you think you could supply a little bit of technical data?

I think the PCM library and the Servo library use the same timer hardware. Try the ServoTimer2 library.

HC-SR501 PIR motion sensors. These are working just as should it is the interaction with the servo and PCM.

I might guess that moveServo() having over 2 seconds of real delays in it is messing with the servoDelay "every 500ms" timing. But it's only a guess, I've never used millisdelay,

Steve

Took me a while to install this library, but after doing so same problem. I also did the mapping you suggested, in another thread. And I will keep working on it with this library. Just wanted to let you know I am working on it. Thank you for the suggestion.

That is a good observation. I do think it is related to time somehow. That is why I introduced that library to see if that would help. I have played with the Delay numbers and it seems to be making a difference but not enough to solve the problem. The servos move in first iteration then after the sound plays the servo stops. Could it be memory is getting overwritten. The sound is stored in PROGMEM.

HI,

Are ALL the gnds connected together?
Can you please post a circuit diagram?
PLEASE not a Fritzy picture.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

And my updated sketch.


#include <PCM.h>
#include "angryBirdSound.h"
int soundLength = 0;

//#include <PWMServo.h>
#include <ServoTimer2.h>

//PWMServo ltservo, rtservo;  // create servo object to control a servo
ServoTimer2 ltservo, rtservo;  // create servo object to control a servo


int pos = 0;    // variable to store the servo position
long rnum;
int ltWing=2;
int rtWing=4;

int ledPin = 13;                // choose the pin for the LED
int backNest = 7;               // choose the input pin (for PIR sensor)
int frontNest = 8;
int pirState = LOW;             // we start, assuming no motion detected
int backVal = 0;                    // variable for reading the pin status
int frontVal = 0;                    // variable for reading the pin status

#include <loopTimer.h>
#include <millisDelay.h>
#include <BufferedOutput.h>

//Example of using BufferedOutput to release bytes when there is space in the Serial Tx buffer, extra buffer size 80
createBufferedOutput(bufferedOut, 80, DROP_UNTIL_EMPTY);

millisDelay soundDelay;
millisDelay servoDelay;


void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.println(i);
    delay(500);
  }
  bufferedOut.connect(Serial);  // connect buffered stream to Serial
  
  servoDelay.start(2000); // start the ledDelay, toggle every 1000mS
  soundDelay.start(3000); // start the printDelay, print every 5000mS
  
  ltservo.attach(ltWing);  // attaches the servo on pin 9 to the servo object
  ltservo.write(0);
  rtservo.attach(rtWing);
  rtservo.write(0);
  //randomSeed(analogRead(0));
  
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(backNest, INPUT);     // declare sensor as input
  pinMode(frontNest, INPUT);     // declare sensor as input
  
  //soundLength = sizeof(angryBirdSound);
  soundLength = sizeof(smallSound);

  //startPlayback(sample, sizeof(sample));

}

// the task method
void playSound() {
  if (soundDelay.justFinished()) {   // check if delay has timed out
    soundDelay.repeat(); // start delay again without drift
    //ledOn = !ledOn;     // toggle the led
    bufferedOut.print("play sound");
    //startPlayback(angryBirdSound, soundLength);
    startPlayback(smallSound, soundLength);

    //digitalWrite(led, ledOn ? HIGH : LOW); // turn led on/off
  } // else nothing to do this call just return, quickly
}

void moveServo() {
  if (servoDelay.justFinished()) {
    servoDelay.repeat(); // start delay again without drift
    for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        // Servo1.write(map(pos, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
        rtservo.write(map(pos, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
        ltservo.write(map(pos, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
        delay(3);                       // waits 15ms for the servo to reach the position
    }

     delay(1000);

    for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
      rtservo.write(map(pos, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
      ltservo.write(map(pos, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
      delay(3);                       // waits 15ms for the servo to reach the position
    }
    //delay(1000);
    bufferedOut.println(millis());   // print the current mS
    
  } // else nothing to do this call just return, quickly
}


void loop()
{
  
  bufferedOut.nextByteOut(); // call at least once per loop to release chars
 // loopTimer.check(bufferedOut); // send loop timer output to the bufferedOut

  backVal = digitalRead(backNest);  // read input value
  frontVal = digitalRead(frontNest);  // read input value
  if ((backVal == HIGH) || (frontVal == HIGH)) {            // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    if (pirState == LOW) {
      // we have just turned on
      bufferedOut.print("Motion detected!");

      //Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
      
      moveServo();
      playSound();

    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    if (pirState == HIGH){
      // we have just turned of
      bufferedOut.print("Motion ended!");
      stopPlayback();
      //Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}