Adding tone() Stops Motors from working!

So. I have a RC car turned into a robot. I wanted it to play a two tone sound when it decides it needs to turn around. (When the Ping))) Sensor is 36 inches from what it is reflecting off of.) Every time I add const int piezoPin = 4; and the tone() functions, my motors don't go forwards or backwards. Here's my code.

/*
RC Car to Robot Conversion
by Nathan Brown

Used to convert an RC car into a robot that uses a PING sensor to avoid obstacles,
and an Arduino motor shield for motor control.

*/
//initialize speaker pin
const int piezoPin = 4;  
// this constant won't change.  It's the pin number
// of the sensor's output:
const int pingPin = 7;

void setup() {
  Serial.begin(9600);
  //establish motor direction toggle pins
  pinMode(12, OUTPUT); //drive motor -- HIGH = forwards and LOW = backwards
  pinMode(13, OUTPUT); //turn motor -- HIGH = left and LOW = right
  
  //establish motor brake pins
  pinMode(9, OUTPUT); //brake (disable) the drive motor
  pinMode(8, OUTPUT); //brake (disable) the turn motor

  //Turns brake off for drive motor
  digitalWrite(9, LOW); 

  //Turns brake on for turn motor
  digitalWrite(8, HIGH); 

  //Sets initial speed of drive motor
  analogWrite(3, 200);
  
  //Sets initial direction of drive motor
  digitalWrite(12, HIGH);
}

void loop()
{
  
  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration, inches, cm;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // short LOW pulse before to assure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): 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(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
  //
  //if objects are less than 24 inches away
  //the robot reverses and turns to the right
  //for 2 seconds
  //
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  
 
   if (inches < 36){
    
    //brake drive motor and pause 3/10 second
    digitalWrite(9, HIGH);
    tone(piezoPin,2000,100);
    Serial.print("Piezo triggered @ 2000 Hertz for 100 milliseconds.");
    Serial.println();
    delay(300);
    tone(piezoPin,1000,300);
    Serial.print("Piezo triggered @ 1000 Hertz for 300 milliseconds.");
    Serial.println();
    Serial.print("Stopping");
    Serial.print(".");
    Serial.print(".");
    Serial.print(".");
    Serial.println();
    //
    //setting turn motor
    //
    if (random(100) > 50){ // custom-----
    //turn off brake for turn motor 
      digitalWrite(8, LOW);
    Serial.print("Going Backwards.");
    Serial.println();
    Serial.print("Turning Right.");
    Serial.println();
    //set turn motor direction
      digitalWrite(13, HIGH);

    //activate turn motor
      analogWrite(11, 255);
    
    //
    //setting drive motor
    //
    
      //turn off brake of drive motor
      digitalWrite(9, LOW); 
    
    //set drive motor backwards direction
      digitalWrite(12, LOW);
    
    //activate the drive motor
      analogWrite(3, 200);

    
    //backup for 2 seconds
      delay(2000);
    
    //
    //stopping
    //
    
    //brake both motors
      digitalWrite(8, HIGH);
      digitalWrite(9, HIGH);
     Serial.print("Going Forwards.");
     Serial.println();
    
  }
  else{//turn off brake for turn motor 
      digitalWrite(8, LOW);

    //set turn motor direction
      digitalWrite(13, LOW);
      
      Serial.print("Going Backwards.");
      Serial.println();
      Serial.print("Turning Left");
      Serial.println();
    //activate turn motor
      analogWrite(11, 255);
    
    //
    //setting drive motor
    //
    
      //turn off brake of drive motor
      digitalWrite(9, LOW); 
    
    //set drive motor backwards direction
      digitalWrite(12, LOW);
    
    //activate the drive motor
      analogWrite(3, 200);

    
    //backup for 2 seconds
      delay(2000);
    
    //
    //stopping
    //
    
    //brake both motors
      digitalWrite(8, HIGH);
      digitalWrite(9, HIGH);
     Serial.print("Going Forwards.");
     Serial.println();
    
}
   }
  //when nothing is within 12" 
  //the robot simply drives forwards
  //
  
  else{
    
    //
    //Setting drive motor
    //
    //set drive motor forward direction
    digitalWrite(12, HIGH);
    
    //turn off brake of drive motor
    digitalWrite(9, LOW);    
    
    //activate drive motor
    analogWrite(3, 200);
  
  
  }
  
  delay(100);
}

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;
}

Tone makes use of the internal timer, which is conflicting with the use of those timers for PWM (analogwrite)

Any idea how to fix this? I would like to be able to trigger my speaker when it changes to reverse.

OP Cross posting wastes time.

DO NOT CROSSPOST

AWOL:
OP Cross posting wastes time.

DO NOT CROSSPOST

I'm sorry I'm new what is crossposting? Posting off topic and what does OP mean?

Original Poster
DO NOT POST THE SAME QUESTION IN DIFFERENT PARTS OF THE FORUM.

IT WASTES TIME.

EVEN MORE TIME, NOW.

I wasn't sure which one to put it under so I put it in both :stuck_out_tongue: I'll delete the other one.

cherryguy:
Any idea how to fix this? I would like to be able to trigger my speaker when it changes to reverse.

From the tone section of the reference manual; "Use of the tone() function will interfere with PWM output on pins 3 and 11 (on boards other than the Mega). "

wanderson:
From the tone section of the reference manual; "Use of the tone() function will interfere with PWM output on pins 3 and 11 (on boards other than the Mega). "

Yes, is there an alternative method for triggering a piezo speaker?

What's being suggested is that you use two different pwm pins to control your motor speed.

Hmmm, how? Its all kinda over my head. Any hints would be nice :smiley:

cherryguy:
Hmmm, how? Its all kinda over my head. Any hints would be nice :smiley:

Change this,

 //activate turn motor
      analogWrite(11, 255);

so it uses one of the unaffected PWM pins (ie, not 3 or 11), look at the analogWrite section of the reference manual for your options.

Well... I'm using a motor shield with the motors plugged into channel A and B terminals on the motorshield.

Whose motor shield? Does it not provide the ability to use alternative pins? If not, then you need to replace the motor shield with one that does, give up on using tone (pick a piezo that doesn't need it), or give up on the Arduino environment (core) and write straight AVR C/C++ to accomplish your tasks...

The Arduino Motorshield R3 http://arduino.cc/en/Main/ArduinoMotorShieldR3.

Doesn't look like that shield provides the option of using different pins, so you are left with options 1-3 from my post.

Okay, if I was to use a method other than tone what method would I use?

Tone could be implemented in software that didn't rely on modifying the timers associated with PWM, but the simplest, easiest solution is to replace your piezo element with one that doesn't require being driven by a frequency, when driven by a HIGH signal, they emit a tone, and when the driver is low they don't... Just like an LED. Only costs a buck or two.

I plugged the red wire (positive +) into Brake A on pin 9 so it beeps whenever the brake is engaged.

One other option is to remove the shield from the arduino and wire them together manually. Then you can use whatever pins you like.