Noise from servo feedback?

I’m a complete neophyte hacking my way through projects. So forgive me for not using technical language in describing my project and efforts…

I’ve been working on an art project robot that is responsive to sound and light (moves and draws in response to sound and light levels). It has motors (2 stepper motors) and a servo that move in a variety of ways based on the volume level coming into a mic and the light levels from a photocell

Everything has been working fine with the stepper motors and generally with the photocell readings. But when I started working with the servo and the photocell more actively I noticed what I am assuming is feedback or noise affecting my performance.

The servo starts to create noise that the mic picks up (but I don’t think directly) and it can get into a feedback loop where it’s own noise creates the noise that triggers it to move. Secondarily, if the photocell gets under a strong light source the mic levels also get really high and it also kicks off a lot of activity I don’t want.

I’m kind of guessing both the servo and the photocell are creating noise within the electric circuit, but I have no idea really how to isolate them.

Some background on the project.

  • I built the mic from this example : LM358 microphone amplifier | Low voltage. Mostly harmless...
  • the servo is a Datan S1213
  • the photocell and the servo are on the 3V line, the mic and the light/sound meter are on the 5v, the motors are on a motorshield (adafruit v2.0)
  • I’ve got a 8x8 bicolor backpack to convert light and sound to a meter to give me a rough visual of the light and sound levels

I’m going to try to build a circuit diagram, but that’s not something I’ve done before, so I thought I’d post generally first and then see if I can illustrate my layout.

Dode follows.

/*
A Sound and light controlled roboot for making drawings that respond to environment
 Takes sound and light measurements over 10 cycles to set response variables
 Uses sound to set direction and duration of movement
 Uses light to set speed of movement and as a multiplied on duration of movement.
 Uses light sensor pointed downward check if it is on canvas and corrects if not
 Displays sound and light levels as two 3 pixel wide meters on 8x8 backpack
 */

#include <Wire.h>
#include <Servo.h> 
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
Adafruit_DCMotor *myMotorR = AFMS.getMotor(2);
Adafruit_DCMotor *myMotorL = AFMS.getMotor(3);

int soundPin = 0;
int lightPinUp = 3;
int lightPinDown = 2;
Servo myservo;

void setup() {
  myservo.attach(12);
  matrix.begin(0x74);
  AFMS.begin();
  myMotorL->setSpeed(255);
  myMotorL->run(FORWARD);
  myMotorL->run(RELEASE);
  myMotorR->setSpeed(255);
  myMotorR->run(FORWARD);
  myMotorR->run(RELEASE);
  Serial.begin(9600);
}

//establish conditions, measure environment and set variables for light and sound

void loop() {
  myMotorL->run(RELEASE);
  myMotorR->run(RELEASE);
  int mnS = 1024; 
  int mxS = 0;  
  int mxLU = 0; 
  int mxLD = 0;  
  int pos = 125;
  myservo.write(pos);  
  for (int i = 0; i < 10; ++i) {
    int sound = analogRead(soundPin);
    int lightUp = analogRead(lightPinUp);
    int lightDown = analogRead(lightPinDown);
    mnS = min(mnS, sound);
    mxS = max(mxS, sound);
    mxLU = max(mxLU, lightUp);
    mxLD = max(mxLD, lightDown);
  }

  //using this section to create a sound meter.
  //two "bars" each 3 pixels wide. Green is sound, Red is light.

  matrix.clear();                          
  matrix.fillRect(0,0, (mxS-mnS)/6,3, LED_GREEN);
  matrix.fillRect(0,5, map(mxLU,100,1200,0,8),3, LED_RED);    //adjust number to parameterize light
  matrix.writeDisplay();
  int motorSpeed = map(mxLU, 100,1200 ,100, 255);
  int lightDuration = map(mxLU,100,1200,5,10);     // setting duration of wheel turning to respond to light levels.
  Serial.print(mxLU);
  Serial.print (" - ");
  Serial.print (mxLD);
  Serial.println();

  /*
This sections is for the action routine. 
   two nested if statements
   1) Only moves if lower photocell is above a certain level, if not backs up and turns around, intended to keep on canvas
   2) only moves if sound is above a threshold
   Sets motor speed according to light level on up sensor
   Direction of motor is set randomly to create more dynamic action
   Duration of motor turning is based on light levels and sound levels
   */

  if(mxLD>50){                         //sets sensitivity to being on light colored surface hard to tune based on ambiant light
    if(((mxS-mnS)/6)>1){               //sets sensoitivity of sound to action
      myMotorR->setSpeed(motorSpeed);    
      myMotorL->setSpeed(motorSpeed);       
      if(random(100) >50)                 
      {
        myMotorL->run(FORWARD);  
      }
      else{ 
        myMotorL->run(BACKWARD);
      }
      if(random(100) >50) {
        myMotorR->run(FORWARD);
      }
      else{ 
        myMotorR->run(BACKWARD);
      }
       pos = 125-((mxS-mnS)/3);
       myservo.write(pos);
      delay((mxS-mnS)*lightDuration);  //using light duration as a factor in turn rotation
    }
  }
  else{ 
    myMotorR->setSpeed(255);
    myMotorL->setSpeed(255);
    myMotorR->run(BACKWARD);
    myMotorL->run(BACKWARD);
    delay (500);                   //needs to be enough to get clearance back on canvas
    myMotorR->run(BACKWARD);
    myMotorL->run(FORWARD);
    delay (2000);                // needs to be enough for 180
  }
}

the photocell and the servo are on the 3V line,

What 3v line? Make sure the servo is not powered thru/from the arduino.

Thanks. Can I run it off the motor shield power (dedicated battery pack).

See updated fritzing diagram (first try so forgive my errors) on post.

Here’s my first attempt at a fritzing diagram…

You are running the servo's power from the Arduino regulated 5V line.

Never do this, it risks damage to the Arduino and will probably cause random resets.

The servo needs a high current 6V (5..7.2V) power supply - perhaps that's the same as your motors use? Remember a servo is a motor inside...

Allow 1A per small servo, as a rough rule of thumb.

A Fritzing diagram is a wiring diagram, not a circuit diagram (which is abstract and laid out logically)

Learn circuit diagrams as soon as poss, its the language of electronics...

Thanks for the reply. Sorry for not being able to work in circuit diagrams yet. Very new to this world.

I’d done a few projects with small servos running off the 5v line (e.g. http://www.arduino.cc/en/Tutorial/Sweep) so I thought it was OK to work in this way.

You are correct I’ve got a 4 AA battery pack for the motors. I tried to direct connect the servo to the battery pack (red line) and ground to the arduino, and then use pin 12 for the servo control, but it seems to have the same problem. I’ll keep working along those lines and see if I can get it separated.

kifling: I'd done a few projects with small servos running off the 5v line (e.g. http://www.arduino.cc/en/Tutorial/Sweep) so I thought it was OK to work in this way.

No, servos use a lot of current (~1A for a small one, more for larger/faster) and can put inductive spikes on the rail - you really don't want that on your logic supply.