Piezo not playing clean tone

Hi! A while ago, I built an RFID timing system to time distance running races. Recently I added a piezo to the system to make a noise every time an RFID tag is read. The thing is, whenever an RFID tag is read, it doesn't play a consistent, even tone, it instead makes more of a chirping sound. It only does this when the RFID reader (which draws a lot of power) is on, which leads me to think it may not be receiving enough power.
YouTube video of audio
Any help is appreciated!

So measure the voltage of the system while it is running and see if the voltage drops. If it does you need a supply that can deliver more current.

I don't have a multimeter, but I tried adding a 12V DC power supply to the Arduino (instead of the 5V one it was previously using) and got the same chippy sound. However, the 5V supply delivers 2A and the 12V one delivers 1.5A -- I'm not super experienced in the world of audio and power supplies, so I'm not sure if that makes a difference.

I guess it's time to see the code that attempts to make the piezo operate. And what specs do you have on the piezo?

Well the piezo is just the piezo included with the Arduino Starter kit, and that's all I have on it. In addition, I connected the bare ends of a speaker cable to it so I could plug it in to a regular speaker (makes the same sound, only louder). And here's the software:
This is just a small piece of the program that runs the timer, but it is the only part where the piezo comes in:

int piezo = 9;
int note = 2637;

void playTone(){
 
 tone(piezo, note, 1000);
}

For reference: the playTone() function is called whenever I need a one second beep

Does the piezo make a sound by itself if you connect it to 5v directly ?

1 Like

Is the rfid stuff using the same timer as tone?
Post all code, because often the problem is in the code not shown...
A 5V 2A is better than 12 V 1.5 A ( unless the voltage starts falling at higher currents).

A possible easy fix is to provide a local energy reservoir; assuming the buzzer only takes a low current, then isolate its power supply by a low value resistor (guess ~10 ohms, check the current drawn) and decouple with a large cap (100u). Some calculations with current drawn and voltage dip recharge time etc will confirm if this is plausible for you.

Hi,

Good idea, can you test your piezo on just 5V supply?
Can you please post an image of the piezo?

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

Then you should get one immediatly. Only $10 from a thrift shop. You really are working blind without one.

If you are going theough the Arduino's internal regulator it matters not a jot what current it will supply. You are limited to the current you can get through this internal regulator. While the current through the regulator is rated at 1A you will only get about 200mA because the heat sink on the Arduino is very poor. It will overheat and shut down, so you did not do anything to address the lack of current, despite you thinking you did.

1 Like

As I have said many times before, a capacitor is no substitute or cure for a power supply that can't supply enough current.
Please read what decoupling is really about.
http://www.thebox.myzen.co.uk/Tutorial/De-coupling.html

There are thousand of Xerox multifunction machines with staplers using this principle. I will not get into further discussion with you regarding this.

The OP is NOT using a Xerox piezo.

Some updates: The piezo in question is not in fact a Xerox piezo. It's the one attached to the shield handling all things RFID, the Sparkfun Simultaneous UHF RFID reader. Here's an image (the piezo is the small black circle in the bottom right corner)


Also, here's the software running the system:

#include <SoftwareSerial.h>
SoftwareSerial softSerial(2, 3);
#include "SparkFun_UHF_RFID_Reader.h"
RFID nano;


//place variables - data placement
int place = 1;
float seconds;
float personTime;
unsigned long currentMillis = 0;
unsigned long prevMillis = millis;
unsigned long minutes = 0;
int heat = 1;
bool gunReady = false;
bool panelReady = false;
int rfidcounter = 1;
#define piezo 10
bool data = true;
int note = 2637;

#define buzzgnd 9

//switches and such
const int buttonPin = 6;
int buttonPushCounter = 1;
int buttonState = 0;
int lastButtonState = 0;
int rfidbtn = 8;
int gun = 13;
int gunCounter = 1;
int gunState = 0;
int lastGunState = 0;
int lapno = 1;
unsigned long lastMillis;

// create structure to filter
struct DubFilter {
  uint8_t EPC[12];
  //unsigned long LastTime;     // optionally you could add data to capture
};

// maximum number of unique EPC
#define MaxEPC 40
struct DubFilter dub[MaxEPC];

void(* resetFunc) (void) = 0;
void setup() {
  
//RFID 
pinMode(gun, INPUT);
pinMode(rfidbtn, INPUT);
pinMode(12, OUTPUT);


digitalWrite(buzzgnd, LOW);

Serial.begin(115200);
while(! Serial);

if(setupNano(38400) == false){
  Serial.println("Module failed to respond");
  while (1);
}

nano.setRegion(REGION_NORTHAMERICA);
nano.setReadPower(2000);

// init de-dub
for (uint8_t i=0 ; i < MaxEPC ; i++)
  dub[i].EPC[0] = 0;

Serial.println("System Ready");
delay(500);
Serial.println("Ready to begin first race");
pinMode(buttonPin, INPUT);

pinMode(piezo, OUTPUT);
pinMode(buzzgnd, OUTPUT);
}
void startRace(){
  lapno = 1;
  Serial.print("Race ");
  Serial.print(heat);
  Serial.println(" started");
  
  heat++;
  lap();
}

void lap(){
  Serial.print("Lap ");
  Serial.println(lapno);
 
  place = 1;
  for (uint8_t i=0 ; i < MaxEPC ; i++)
  dub[i].EPC[0] = 0;
  
  lapno++;
}

//where the magic happens
void runTimer(){
     
  currentMillis = millis();
  seconds = currentMillis - prevMillis;
  float personTime = seconds/1000;
unsigned minutes = (personTime + .0005) /60;
      personTime -= minutes * 60;
      
     
     


  //data - THIS IS WHERE IT ALL GOES DOWN
  if(nano.check() == true){
    byte responseType = nano.parseResponse();
    
    if(responseType == RESPONSE_IS_TAGFOUND){
      
      // it is already in the list
     
      if ( DeDub() ) return ;
       playTone();
      Serial.print(place);
        Serial.print(" ");
      byte tagEPCBytes = nano.getTagEPCBytes();
      for(byte x = 0 ; x< tagEPCBytes ; x++){
        if(nano.msg[31 + x] < 0x10) Serial.print("0");
        
        Serial.print(char(nano.msg[31 + x]));
        Serial.print((""));
      }
      
      Serial.print(" ");
      Serial.print(minutes);
      Serial.print(':');
      if ((personTime + 0.0005) < 10)
    Serial.print('0');
      Serial.println(personTime, 2);
      
      place++;

    }
   
  }
 
}
void playTone(){
 
 tone(piezo, note, 1000);
}

/**
 * This routine will check against the table
 * If EPC is already in the table true will be returned.
 * if NOT EPC will be added to the list and false is turned
 */
bool DeDub()  {
  uint8_t i,x;
  bool MissMatch = false; 
  
  // get the num EPC bytes 
  uint8_t tagEPCBytes = 12;

  // check each entry in the table
  for (i = 0 ; i < MaxEPC; i++){
 
    // if empty entry
    if (dub[i].EPC[0] == 0)  break;

    MissMatch = false; 
    for(x = 0 ; x< tagEPCBytes ; x++){

      // check for miss match
      if(nano.msg[31 + x]  != dub[i].EPC[x] ){
        MissMatch = true;
        break;
      }
    }

    // A this point we check for MisMatch (false means we have a Match)
    if (! MissMatch)  return true;

  }

  // EPC was not in the list already
  if (i == MaxEPC) {
    Serial.println("Table is full\nCan NOT add more");
  }
  else {
    // add to the list
    for(x = 0 ; x< tagEPCBytes ; x++){
      // Add to the list
      dub[i].EPC[x] = nano.msg[31 + x];
    }
  }
  return(false);
}
void flash(){
  
}
void stopTimer(){
  seconds = 0;
  place = 1;
  minutes = 0;
  prevMillis = millis();
}
void loop() {
  // put your main code here, to run repeatedly:
  gunState = digitalRead(gun);
buttonState = digitalRead(buttonPin);
  if(buttonState == HIGH){
    if(gunState == HIGH){
      
      if(gunCounter %2 != 0){
  startRace();
  gunCounter++;
      playTone();

  delay(150);
      }
      
     else if(gunCounter %2 == 0){
      gunCounter++;
      Serial.print("Race ");
      Serial.print(heat - 1);
      Serial.println(" Ended");
      Serial.println("Ready to begin next race");
      playTone();

      delay(150);
      
      
     }
     
}
}
else if(buttonState == LOW){
  if(gunState == HIGH){
    lap();
    playTone();
    delay(175);
  }
}

if(gunCounter %2 == 0){
  runTimer();
  }  

  
   if(gunCounter %2 != 0){
    stopTimer();
    for (uint8_t i = 0 ; i < MaxEPC ; i++)
    dub[i].EPC[0] = 0;
   }




int rfidbtnstate = digitalRead(rfidbtn);
if (rfidbtnstate == HIGH){
  rfidcounter++;
    if(rfidcounter %2 == 0){
      nano.startReading();
     digitalWrite(7, HIGH);
     digitalWrite(5, LOW);
      
      //Serial.println("RFID reader activated");
      }
    else if(rfidcounter %2 != 0){
      nano.stopReading();
        digitalWrite(7, LOW);
        digitalWrite(5, HIGH);
        //Serial.println("RFID Reader deactivated");
  } 
  
  delay(200);
}


if(Serial.available() > 0){
  char code = Serial.read();
   if(code == 'r'){
    resetFunc();
  }
  
  if(code == '1'){
   nano.startReading();
    digitalWrite(7, HIGH);
    digitalWrite(5, LOW);
    Serial.println("RFID ON");
    
  }
  if(code == '2'){
    
    nano.stopReading();
    digitalWrite(7, LOW);
    digitalWrite(5, HIGH);
    Serial.println("RFID OFF");
  }
  if(code == '3'){
    Serial.println("Timers Ready");
  }
  if(code == '4'){
    Serial.println("Starter Ready");
  }
  if(code == '5'){
    Serial.println("Starter NOT Ready");
  }
  if(code == '6'){
    Serial.println("Timers NOT Ready");
  }
  if(code == 'a'){
    Serial.println("Valid Start");
  }
  if(code == 'b'){
    Serial.println("False Start, Reset");
  }
  if(code == 'c'){
    Serial.println("Timer Error, False Start");
  }
  
 
}
//end loop

}
boolean setupNano(long baudRate)
{
  nano.begin(softSerial); //Tell the library to communicate over software serial port

  //Test to see if we are already connected to a module
  //This would be the case if the Arduino has been reprogrammed and the module has stayed powered
  softSerial.begin(baudRate); //For this test, assume module is already at our desired baud rate
  while (softSerial.isListening() == false); //Wait for port to open

  //About 200ms from power on the module will send its firmware version at 115200. We need to ignore this.
  while (softSerial.available()) softSerial.read();

  nano.getVersion();

  if (nano.msg[0] == ERROR_WRONG_OPCODE_RESPONSE)
  {
    //This happens if the baud rate is correct but the module is doing a ccontinuous read
    nano.stopReading();

    Serial.println(F("Module continuously reading. Asking it to stop..."));

    delay(1500);
  }
  else
  {
    //The module did not respond so assume it's just been powered on and communicating at 115200bps
    softSerial.begin(115200); //Start software serial at 115200

    nano.setBaud(baudRate); //Tell the module to go to the chosen baud rate. Ignore the response msg

    softSerial.begin(baudRate); //Start the software serial port, this time at user's chosen baud rate

    delay(250);
  }

  //Test the connection
  nano.getVersion();
  if (nano.msg[0] != ALL_GOOD) return (false); //Something is not right

  //The M6E has these settings no matter what
  nano.setTagProtocol(); //Set protocol to GEN2

  nano.setAntennaPort(); //Set TX/RX antenna ports to 1

  return (true); //We are ready to rock
}

That is an active piezo. See the + sign on the top? The tone will stop every time the power is removed, and will signal continuously while power is turned on. Something in your system is turning the power on and off.

Interesting, I'll have to look and see if there's anything making it turn on/off. Would it be a delay() command or something else I should look for?
As a side note, there is a speaker wire attached to the piezo so an external speaker can play the tone. Whatever speaker is connected plays the same tone as well. Would this make any difference?

What makes it turn on and off is a pin on some device, somewhere that is turning the 5 volts on and off to control the piezo. If you connected the wire to the piezo/control pin with a very low resistance device, like a speaker, you likely damaged the device doing the controlling. A schematic of the device would help in answering.

Thank you.

I hate arguing with people who are reluctant to learn. It lets me have more time to help people interested in improving themselves.

Look at the Blink without delay example

A clear page on decoupling :slight_smile: