Running Motors Causes Servo to Run

I had no clue where to put this, so I put it in Programming Questions

I am frustrated beyond belief. I have a robot that has two DC motors attached to either side, and a servo slightly above the right motor. When I send the command to move forward, the servo runs???, and the two motors go about an inch before stopping.

Here's my code:

 if (ch == '8') {
          forward();
}

 void forward() {
      digitalWrite(13, HIGH); //Establishes forward direction of Channel B
      digitalWrite(8, LOW);   //Disengage the Brake for Channel B
      analogWrite(11, 255);  

      digitalWrite(12, LOW);  //Establishes for direction of Channel A
      digitalWrite(9, LOW);   //Disengage the Brake for Channel A
      analogWrite(3, 255);  

      delay(1000);
}

This also happens when I go backward. But, when I control one wheel it works fine. Another thing I'd like to mention is when I comment the delay(1000), only one wheel moves. When the delay is in, both wheels move.

Help is appreciated.
Thanks in advance.

Where is the rest of the code? Why do you suppose the problem is in the small piece you have posted?

How is it all wired up?
Where is the power coming from?

Is it possible that the battery voltage falls too low when the motors run?

...R

The wiring is not wrong, because I've been over it a hundred times.

  • The servo goes when It's told to go, and stops when it's supposed to stop, when directly commanded
  • The motors go without the servo, which had led me to believe that it might be a voltage problem

The power is coming from a battery pack of 4 AA's plugged in to the power jack in the Arduino.
I really, really would not like to have another power source, just for one servo.

Do you really want all of the code? I would have thought that the only part affecting the problem was the snippet I showed you.

You think the flaw is in that snippet. It "clearly" isn't as it is too simple to have a flaw.

So the flaw lies elsewhere - which we cant look at. What s the "ch" variable? Where/how often is the if called .. and so on

There are (speaking from having read a few of these mystery reports by now) usually
1: Running out of memory (RAM) on he Arduino causing all sort of mystical happenings. Seeing the whole code helps diagnose that.
2: Yes, you have connected the wires together the way you want to, but is the circuit valid? Are you powering the servo/motors through/bypass the Arduino board? What motor driver are you using to boost the Arduino-pin to motor strength?
2b: Power decoupling is totally underestimated.

I’m using the Arduino Motor Shield.
The code is littered with comments, etc, and you will probably find lots of beginner mistakes.
And, byte size:
9,272 bytes (of a 32,256 byte maximum)

Here it is:

#include <Servo.h>
#include <EEPROM.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>

/*
robot.ino
@author Michael Antkiewicz
Used to init the robot
*/

int dirA = 12;
int dirB = 13;  // not used in this example
int speedA = 10;
int speedB = 11; // not used in this example

Servo rightHand;
Servo leftHand;

int speed = 230;
int speed2 = 255;

int front = 0;
int back = 1;

const int location = 1;



/* Distance Sensor */
const int trigPin = 3;
const int echoPin = 4;
const int inchLimit = 7; //Max amount of space between robot and object
const int centLimit = 8; //Max amount of space between robot and object
/* End Distance Sensor */

const int motor_speed_high = 255;
const int motor_speed_backward = -255;
boolean tooClose = false;



void setup() {
  Serial.begin(9600);
  
  
//Setup Channel A
  pinMode(12, OUTPUT); //Initiates Motor Channel A pin
  pinMode(9, OUTPUT); //Initiates Brake Channel A pin

  //Setup Channel B
  pinMode(13, OUTPUT); //Initiates Motor Channel A pin
  pinMode(8, OUTPUT);  //Initiates Brake Channel A pin
  //EEPROM.write(location, 0);
  
  rightHand.attach(7);
  leftHand.attach(6);

}

void loop()
{
//StepForward();
//delay(4000);
//SoftwareServo::refresh();

 if (Serial.available() > 0) {
        char ch = Serial.read();
        Serial.print("Received: ");
        Serial.println(ch);
        if (ch == '8') {
          forward();
        } else if (ch == '0') {
          brake();
        } else if (ch == '2') {
          backward();
        } else if (ch == '4') {
          // left
          left();
        } else if (ch == '6') {
          right();
        } else if (ch == 'm' || ch == 'M') {
            int val = EEPROM.read(location);
            String newval = convertBitToString(val);
            Serial.print(newval);
        } else if (ch == 'v' || ch == 'V') {
            Serial.print(readVcc());
        } else if (ch == 'S' || ch == 's') {
            Serial.println("Going to sleep...");
            sleepNow();
        } else if (ch == 'w' || ch == 'W') {
            Serial.println("Waking up...");
            pinInterrupt();
        } else if (ch == 'C') {
            rightHand.write(90);
            //leftHand.write(180);
        } else if (ch == 'D') {
            rightHand.write(5);
            //leftHand.write(0);
        }
    }
      

    /*
    String serial = readSerial();
    if (serial.indexOf("Memorize") >= 0) {
      serial.replace("Memorize", "");
      serial = split(serial, ':');
      Serial.println(serial);
    }
    */

//brake();

//backward();

  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration, inches, cm;
 
  // The sensor is triggered by a HIGH pulse of 10 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(trigPin, OUTPUT);
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
 
  // Read the signal from the sensor: a HIGH pulse whose
  // duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
 
  // convert the time into a distance
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
  /*
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  */
  if (inches <= inchLimit) {
    //brake();
    //EEPROM.write(location,cm);
  }
  
 
delay(100);
}

void setspeed()
{
  analogWrite(speedB, speed); // set speed (PWM) 
  analogWrite(speedA, speed2); // set speed (PWM) 
}


void forward() {
  /*Motor A forward @ full speed 
  digitalWrite(12, HIGH);  
  digitalWrite(9, LOW);   
  analogWrite(3, 255);    
  
  //Motor B forward @ full speed
  digitalWrite(13, HIGH); //Establishes forward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 255);   //Spins the motor on Channel B at full speed
  Serial.print(analogRead(3));
  */
  
  /* //Motor A forward @ full speed
  digitalWrite(12, HIGH); //Establishes forward direction of Channel A
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  analogWrite(3, 255);   //Spins the motor on Channel A at full speed

  //Motor B backward @ half speed
  digitalWrite(13, LOW);  //Establishes backward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 25);    //Spins the motor on Channel B at half speed

  
  delay(3000);

  
  digitalWrite(9, HIGH);  //Engage the Brake for Channel A
  digitalWrite(9, HIGH);  //Engage the Brake for Channel B
 


  delay(1000);
  */

    //Motor B forward @ full speed
      digitalWrite(13, HIGH); //Establishes forward direction of Channel B
      digitalWrite(8, LOW);   //Disengage the Brake for Channel B
      analogWrite(11, 255);   //Spins the motor on Channel B at full speed
              //Motor A forward @ full speed
      digitalWrite(12, LOW);  //Establishes for direction of Channel A
      digitalWrite(9, LOW);   //Disengage the Brake for Channel A
      analogWrite(3, 255);    //Spins the motor on Channel A at half speed

      delay(1000);
}

void left() {
  digitalWrite(dirB,back); // set direction
  analogWrite(speedB, 255); // set speed (PWM) 
}

void brake() {
  digitalWrite(dirB,front); // set direction
  analogWrite(speedB, 0); // set speed (PWM) 
  digitalWrite(dirA,front); // set direction
  analogWrite(speedA, 0); // set speed (PWM) 
}

void right()
{ 
  digitalWrite(dirB,front); // set direction
  analogWrite(speedB, 255); // set speed (PWM) 
}

void backward() {
    //Motor B forward @ full speed
      digitalWrite(13, LOW); //Establishes forward direction of Channel B
      digitalWrite(8, LOW);   //Disengage the Brake for Channel B
      analogWrite(11, 255);   //Spins the motor on Channel B at full speed
      
      //Motor A forward @ full speed
      digitalWrite(12, HIGH);  //Establishes for direction of Channel A
      digitalWrite(9, LOW);   //Disengage the Brake for Channel A
      analogWrite(3, 255);    //Spins the motor on Channel A at half speed
      delay(1000);
}


long microsecondsToInches(long microseconds)
{
  // According to Parallax's datasheet for the PING))), there are
  // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
  // second).  This gives the distance travelled by the ping, outbound
  // and return, so we divide by 2 to get the distance of the obstacle.
  return microseconds / 74 / 2;
}
 
long microsecondsToCentimeters(long microseconds)
{
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}

String convertBitToString(int value) {
  int val = value;
  String newval = String(val);
  newval.replace("1", "Battery ");
  newval.replace("2", "is ");
  newval.replace("3", "low ");
  newval.replace("6", "high ");
  newval.replace("4", "I ");
  newval.replace("5", "am ");
  newval.replace("7", "my ");
  newval.replace("8", "close ");
  newval.replace("9", "distance ");
  // 792
  newval.toLowerCase();
  return newval;
}

int combine(int a, int b) {
   int times = 1;
   while (times <= b)
      times *= 10;
   return a*times + b;
}


long readVcc() {
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result; // Back-calculate AVcc in mV
  return result;
}

void sleepNow()
{
    // Set pin 2 as interrupt and attach handler:
    attachInterrupt(0, pinInterrupt, LOW);
    delay(100);
    //
    // Choose our preferred sleep mode:
    set_sleep_mode(SLEEP_MODE_IDLE);
    //
    // Set sleep enable (SE) bit:
    sleep_enable();
    //
    // Put the device to sleep:
    digitalWrite(13,LOW);   // turn LED off to indicate sleep
    sleep_mode();
    //
    // Upon waking up, sketch continues from this point.
    sleep_disable();
    digitalWrite(13,HIGH);   // turn LED on to indicate awake
}
                //
void pinInterrupt()
{
    detachInterrupt(0);
}

String readSerial() {
  String content = "";
  char character;

  while(Serial.available()) {
      character = Serial.read();
      content.concat(character);
  }

  if (content != "") {
    return content;
  }
}

I haven't read thoroughly the code (which you should put between [ code] tags :wink: ) , but I see that you declare several local String objects . This will probably lead to memory problems .

I went back and deleted unnecessary variables, and commented out strings, to no avail.

There is some sort of deep problem.

I have gotten so frustrated, that I took out the old sketch and uploaded the blink example sketch.

The robot is still running it's wheels and moving the servo uncontrollably.

The wiring is not wrong, because I've been over it a hundred times.

Hmmm..., then you said the below. It appears you are attempting to power the servo/motors from the arduino. It also appears you have seen warnings not to do so. So what is the story?

The power is coming from a battery pack of 4 AA's plugged in to the power jack in the Arduino.
I really, really would not like to have another power source, just for one servo.

michael-:
The power is coming from a battery pack of 4 AA's plugged in to the power jack in the Arduino.

Four AA cells would produce somewhere in the range 5V-6V depending on the battery type and condition.

The recommended input voltage for the Arduino power jack is 7-12V. If you supply it at less than 7V then the voltage regulator may not be able to maintain a 5V output, which will produce erratic behaviour. Using the same power supply for a servo, motors and an Arduino is not a good idea at the best of times, but is especially unwise when the supply was already marginal to begin with; even more so if the servo is being powered via the Arduino's 5V regulator, as you seem to be implying.

Then what do you recommend me to do to power the robot?

Should I use a 9v rechargeable battery?

I noticed that some of your pinMode commands are not in the setup loop. Maybe put them there and see if that helps.

Also, as far as powering everything from one source, what I did is use the vIn pin to split the power supply to another voltage regulator on a proto shield. I'm using Uno, btw, and according to the schematic, the vIn pin splits the power supply current between the power jack and the Uno's internal regulator. My servos are powered off the proto's regulator. If you dont know what I mean I can post a schematic. That being said, try using a 6 AA power pack. That would boost your voltage and your current, without adding too much weight.
If you dont want to add a proto shield, you could use a tiny proto board. Voltage regulators are 3 components and take up like 9 holes on my proto shield.

I'm using a breadboard to make all the connections.
And, yes I just noticed some pinModes are in a method.

Did you see my post above? The robot starting going crazy, so I uploaded the blink sketch. The robot moves one motor and the servo continuously, without being instructed to. Even with the blink sketch in, it still goes wild.

Any idea why?

Any idea why?

It appears the main issue is how you are trying to power the arduino and the servo/motors.

I wouldn't think the whole robot would go nuts if I underpowered it?

I wouldn’t think the whole robot would go nuts if I underpowered it?

The motors/servo when powered from the arduino and try to move may cause the arduino voltage to drop so low that the arduino reboots. Your arduino is probably rebooting over and over again.

Oh.
Should I then power it with a 9v battery?

You need to know (and tell us) how much current the motors will require, and how you are controlling them, before you can expect to receive useful advice. Budget 1 ampere for each straining servo, too.

A battery pack with four brand new AA alkaline batteries will supply about 3 amperes, but the voltage will instantly drop from 6 to about 3 volts, causing the Arduino to fail and possibly restart. The small, rectangular 9 volt batteries are a cruel joke.

I honestly don't know how much current the motors require.
I'm controlling the motors through the Arduino Motor Shield
If 9v batteries are a joke, which batteries should I use?
And, how do I find out how much current the DC motors require?

michael-:
Oh. Should I then power it with a 9v battery?

You could try powering just the arduino with a rechargeable 9v battery. The servo/motors need an external power supply. Below is a typical way to power a servo.