Adding a piezo to robot?

I’m trying to add a active piezo to my robot so I can distinguish what decisions it’s making. The problem I have is if I just try to define the buzzer as in this example I get an error when trying to compile the code.
Here is the error message.

Arduino: 1.6.9 (Windows 7), Board: “Arduino/Genuino Uno”
Tone.cpp.o (symbol from plugin): In function timer0_pin_port':</sub> <sub>(.text+0x0): multiple definition of __vector_7’
libraries\NewPing\NewPing.cpp.o (symbol from plugin): (.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino/Genuino Uno.

If I leave out the tone(piezoPin,1000,500); it will compile but that does me no good.
Any help would be much appreciated.

Here is my code if that helps.

#include <AFMotor.h>
#include <Servo.h>
#include <NewPing.h>

#define TRIG_PIN A5
#define ECHO_PIN A4
#define MAX_DISTANCE 400
#define FULL_SPEED 250
#define WARNING_DIST 30
#define WATCH_DIST WARNING_DIST * 2  // trig: should be > 1.414 * EMER..
#define GO_TIME 250
#define FULL_TURN_TIME 750
#define HALF_TURN_TIME FULL_TURN_TIME / 2

boolean goingForward = false;
int piezoPin = 8;


// create objects for sonar, motors and servo.
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
AF_DCMotor motorR(4, MOTOR12_1KHZ);
AF_DCMotor motorL(1, MOTOR12_1KHZ);
Servo myservo;

void setup() {
	myservo.attach(9);  // attach servo to pin 9
	myservo.write(90);  // face servo forward.
	delay(1000);
}

void loop() {
	char action;
	action = planAction();
	doAction(action);
}

char planAction() {
	// plans the next action to perform.  Action is represented as
	// a character, L=full left, l= half left, R=full right, r=half right,
	// F=go forward, B=go backwards.
	// algorithm: if looking to side, turn away if closer than WARNING
        // turn half away if closer than WATCH,
	// if looking ahead, go backward if closer than WARNING.
        // otherwise go forward.
	int d;

	d = lookLeft();
	if (d < WARNING_DIST) { return 'R';}
	if (d < WATCH_DIST) { return 'r';}
	d = lookAhead();
	if (d < WARNING_DIST) { return 'B';}
	d = lookRight();
	if (d < WARNING_DIST) { return 'L';}
	if (d < WATCH_DIST) { return 'l';}
	return 'F';
}

void doAction(char act) {
	if (act == 'R') { doFullRightTurn(); }
	else if (act == 'r') { doHalfRightTurn(); }
	else if (act == 'L') { doFullLeftTurn(); }
	else if (act == 'l') { doHalfLeftTurn(); }
	else if (act == 'B') { doWobblyReverse(); }
	else { doForward(); }
}

int readPing() {
	int cm = 0;

	while (cm < 2) {   
		cm = sonar.ping() / US_ROUNDTRIP_CM;
	}
	return cm;
}

int lookLeft() {
	myservo.write(135);
	delay(270);	// extra delay in case servo is at 45
	return readPing();
}

int lookAhead() {
	myservo.write(90);
	delay(170);
	return readPing();
}

int lookRight() {
	myservo.write(45);
	delay(170);
	return readPing();
}
	
void slowStart() {
	int spd;

	for(spd = 0; spd < FULL_SPEED; spd += 2) {
		motorL.setSpeed(spd);
		motorR.setSpeed(spd);
		delay(4);
	}
}

void wobblySlowStart() {
	int spd;

	for(spd = 0; spd < FULL_SPEED; spd += 2) {
		motorL.setSpeed(spd);
		// random (1,5) chooses a number bewteen 1 and 4
		// decreasing it by 2 set it on average 2.
		// so, we will end up going on a somewhat straight line
		// but expect to be slightly cocked.  This is used to 
		// ensure B and F are not exact mirrors.
		motorR.setSpeed(spd + random(1,5) - 2);
		delay(4);
	}
}

void doForward() {
	motorR.run(FORWARD);
	motorL.run(FORWARD);
	if (!goingForward) {
		slowStart();
		goingForward = true;
	} else {
		delay(GO_TIME);
	}
}
void doWobblyReverse() {
	motorR.run(BACKWARD);
	motorL.run(BACKWARD);
	wobblySlowStart();
	goingForward = false;
}
void doFullRightTurn() {
	motorR.run(BACKWARD);
	motorL.run(FORWARD);
	delay(FULL_TURN_TIME);
	goingForward = false;
}

void doFullLeftTurn() {
	motorR.run(FORWARD);
	motorL.run(BACKWARD);
	delay(FULL_TURN_TIME);
	goingForward = false;
}
		
void doHalfRightTurn() {
	motorR.run(BACKWARD);
	motorL.run(FORWARD);
	delay(HALF_TURN_TIME);
	goingForward = false;
}


void doHalfLeftTurn() {
	motorR.run(FORWARD);
	motorL.run(BACKWARD);
	delay(HALF_TURN_TIME);
	goingForward = false;
}

I get an error when trying to compile the code.

No you don’t. You get that error when the compiler is done, and the linker is working. The linker is telling you that there are two functions that are trying to define an interrupt service routine for the same interrupt.

NewPing wants to do something when the timer interrupt fires. So does tone. You get to decide which ONE you want to use.

Hi Paul

Thanks for the info. So if I understand I can't use tone in my sketch because it's already used in NewPing? Since this is an active piezo do I even need to use tone? Would it be possible to define a pin as an output and just set it to high when I want the piezo to make noise?

So if I understand I can't use tone in my sketch because it's already used in NewPing?

Tone isn't used by NewPing. The timer that tone uses is used by NewPing.

Would it be possible to define a pin as an output and just set it to high when I want the piezo to make noise?

Try it, and see. It may not make a pleasant noise, but that may not matter.

rmhoutz:
Hi Paul

Thanks for the info. So if I understand I can't use tone in my sketch because it's already used in NewPing? Since this is an active piezo do I even need to use tone? Would it be possible to define a pin as an output and just set it to high when I want the piezo to make noise?

An "active" piezo will produce it's tone as long as the pin it's connected to is high (5 volts). You may need to create a function to make the beep longer than just a tiny beep.

Paul

Paul_KD7HB:
You may need to create a function to make the beep longer than just a tiny beep.

Hi Paul

I decided to have it produce a R in morse code when turning right and a L in morse code when turning left.
Here is my code for R. It works great for what I needed it to do.
Thanks for the information.

digitalWrite(7,HIGH);           //Short On
 delay(70);                      //Short Wait
 digitalWrite(7,LOW);             //Short Off
 delay(100);                      //Next
 digitalWrite(7,HIGH);           //Dash On
 delay(300);                      //Dash Wait
 digitalWrite(7,LOW);             //Dash Off
 delay(100);                      //Netx
 digitalWrite(7,HIGH);           //Short On
 delay(70);                      //Short Wait
 digitalWrite(7,LOW);             //Short Off
 delay(100);                      //End Of R

rmhoutz:
Hi Paul

I decided to have it produce a R in morse code when turning right and a L in morse code when turning left.
Here is my code for R. It works great for what I needed it to do.
Thanks for the information.

digitalWrite(7,HIGH);           //Short On

delay(70);                      //Short Wait
digitalWrite(7,LOW);            //Short Off
delay(100);                      //Next
digitalWrite(7,HIGH);          //Dash On
delay(300);                      //Dash Wait
digitalWrite(7,LOW);            //Dash Off
delay(100);                      //Netx
digitalWrite(7,HIGH);          //Short On
delay(70);                      //Short Wait
digitalWrite(7,LOW);            //Short Off
delay(100);                      //End Of R

Clever! But I would have put the high/low and the delay times in a two dimension array and stepped through it one by one and pick up the values for use in the digitalwrite and the delay.

Paul

Paul_KD7HB:
I would have put the high/low and the delay times in a two dimension array

Thanks for the input but that's way over my head I'm no programmer and I'm extremely new to Arduino.
Hopefully one day I'll understand the best way to write code.

Thanks again for all your help.

rmhoutz:
Thanks for the input but that’s way over my head I’m no programmer and I’m extremely new to Arduino.
Hopefully one day I’ll understand the best way to write code.

Thanks again for all your help.

Best way is always a matter of opinion! Best way may be to “get her done” and “get it out the door”.

Paul