Amplifier circuit for 12V piezo speaker

Maybe. All I see is 5-12volt@200mA and ~4kHz.
Could be a piezo with driver, but it could also be a mechanical car-type claxon.
Better safe than sorry.

Could be a piezo with driver, but it could also be a mechanical car-type claxon.

Then you did not look at the photo he posted, did you?

Or the link.

(Sorry, but people who answer without actually reading the thread just become a trifle annoying sometimes. :roll_eyes: )

Unplug the yellow wire from the Arduino, and plug it into the ground rail (top/blue rail) of your breadboard.

So I re-ran my test set-up having not changed a thing other than pulling the MOSFET out and plugging it right back into the same spot and MAGICALLY it now fully stops making noise whatsoever when the pin is pulled low in between the high states. I'm not sure what matter of sorcery has befallen me, but it seems to be functional now....hopefully it STAYS this way...

Prime suspect here is the "solderless breadboard". The FET has much chunkier leads than pretty much any other thing you plug in, so on a poor breadboard - a common discussion point here - it may permanently widen the spring clips (note they work one way on the 5-pin "vertical" connections and the other way on the horizontal "common" strips) and cause a loose connection when a narrower wire is later put in.

Because the FET gate is such a marvellously high impedance, if unconnected, it may choose to keep itself "high" and the FET switched on until you connect it otherwise.

Because the FET gate is such a marvellously high impedance, if unconnected, it may choose to keep itself "high" and the FET switched on until you connect it otherwise

You know, now that you mention all of that, I am convinced that that must be it. I have in fact noticed that the FET's leads are a real pain in the butt to stick into the board a lot of the time. And if these are common issues with these pieces of hardware, and I was able to get it working by just plugging it back in properly, that must be the case. Thank you for making me aware of that.

The purpose of this project is to have an alarm system attached to my data probe which reads in temperature and ph data. My problem is the inconsistent functionality of my LEDs and speaker which is a 12V siren (model: X-5735-LW350-S-2-R) hooked up to a MOSFET (model: IRLB8748PBF). Speaker tested with this 12V circuit and arduino. Works fine on its own.

My code monitors incoming readings through the alarm() function. The objective is to throw an alarm whenever a reading meets any 1 of the 4 threshold conditions (low ph, high ph, low temp, high temp).
While 1 or multiple conditions remain out of bounds, the alarm should remain on. Simultaneously, there are 4 LEDs. 1 for each condition. The appropriate LEDs should whichever conditions are met should remain on until the temp or ph data is brought back into the acceptable range.

However, currently, the speaker is not turning on at all. The LEDs will turn on the first time their condition is met and shut off the first time the readings come back into the acceptable range, but they will not turn on ever again, even when the readings go back out of their respective bounds. However, I do still see the appropriate print statements telling me things like "low ph", etc. every single time that the readings are out of bounds. I'd appreciate your guidance in finding a solution to these problems. Thank you.

My code as is (most of the logic for speaker & LEDs are in the alarm() function, but I included the rest for context and debugging purposes):

#include <Ezo_i2c.h> //include the EZO I2C library from
#include <Wire.h>    //include arduinos i2c library
#include <Process.h>
#include <Bridge.h>
#include <String.h>

Ezo_board EC = Ezo_board(1, "ph");         //create EC circuit object, at address is 99 named "ph"
Ezo_board RTD = Ezo_board(2, "RTD");

bool reading_request_phase = true;         //selects our phase

uint32_t next_poll_time = 0;                   //holds the next time we receive a response, in milliseconds
const unsigned int response_delay = 5000;

float ph = 0;
float temp = 0;

const int alarm_stop_button = 10;         //stops the alarm manually by writing false to alarmMode
const int alarm_reset_button = 11;        //restarts the alarm after a manual stop by writing true to alarmMode   
const int low_temp_LED =  4; 
const int high_temp_LED = 5;
const int high_ph_LED = 6;  
const int low_ph_LED = 8;
const int speakerPin = 9;  

int buttonState1 = 0;                      //button state tracker for alarm_stop_button
int buttonState2 = 0;                      //button state tracker for alarm_reset_button
bool alarmMode = true;                    //false if alarm stopped, true while alarm running

char ph_key[] = "s1_ph";                  
char temp_key[] = "s1_temp";

void setup() {
  Wire.begin();                            //start the I2C
  Serial.begin(9600);                     //start the serial communication to the computer
  pinMode(low_temp_LED, OUTPUT);
  pinMode(high_temp_LED, OUTPUT);
  pinMode(low_ph_LED, OUTPUT);
  pinMode(high_ph_LED, OUTPUT);
  pinMode(alarm_stop_button, INPUT);
  pinMode(alarm_reset_button, INPUT);
  pinMode(speakerPin, OUTPUT);

void alarm(float ph_data, float temp_data) {

  if (ph_data >4.000 || ph_data < 3.000 || temp_data > 25.000 || temp_data < 24.000){
    digitalWrite(speakerPin, HIGH); 
//  else{
//    digitalWrite(speakerPin, LOW);
//  }
  if (ph_data >4.000 && alarmMode == true){
    Serial.print(" high ph ");
    pinMode(high_ph_LED, LOW);
  if (ph_data < 3.000 && alarmMode == true) {
    Serial.print(" low ph ");
    pinMode(low_ph_LED, LOW);
  if (temp_data > 25.000 && alarmMode == true){
    Serial.print(" high temp ");
    pinMode(high_temp_LED, LOW);
  if (temp_data < 24.000 && alarmMode == true){
    Serial.print(" low temp ");
    pinMode(low_temp_LED, LOW);

void receive_reading(Ezo_board &Sensor) {               //decodes readings after read command issued

  Sensor.receive_read();              //get response data & put in [Sensor].reading variable if successful

  switch (Sensor.get_error()) {             //switch case based on what the response code is.
    case Ezo_board::SUCCESS:

      if (Sensor.get_name() == "ph") {
        ph = Sensor.get_reading();
      if (Sensor.get_name()=="RTD") {
        temp = Sensor.get_reading();         
      Serial.print(Sensor.get_reading(), 3);  //the command was successful, print the reading 

    case Ezo_board::FAIL:
      Serial.print("Failed ");          //means the command has failed.

    case Ezo_board::NOT_READY:
      Serial.print("Pending ");       //the command has not yet been finished calculating.

    case Ezo_board::NO_DATA:
      Serial.print("No Data ");       //the sensor has no data to send.

void loop() {

 buttonState1 = digitalRead(alarm_stop_button);         //turn alarm off manually
 if (buttonState1 == HIGH) {
   alarmMode = false;

 buttonState2 = digitalRead(alarm_reset_button);        //manually restart alarm
 if (buttonState2 == HIGH) {
   alarmMode = true;
 if (reading_request_phase) {

   if((RTD.get_error() == Ezo_board::SUCCESS) && (RTD.get_reading() > -1000.0)){
   next_poll_time = millis() + response_delay;   //set when the response will arrive
   reading_request_phase = false;                  //switch to the receiving phase
  else {                                                     //if were in the receiving phase
    if (millis() >= next_poll_time) {                  //and its time to get the response
      receive_reading(EC);                             //get the reading from the PH circuit
      Serial.print("  ");
      receive_reading(RTD);                           //get the temperature from the circuit
      Serial.print("alarmMode: ");
      reading_request_phase = true;                //switch back to asking for readings

Circuit layout also included in the attachments for reference.

Not your current problem, but I spot a bug that keeps this from running as a permanent installation.

next_poll_time = millis() + response_delay;
if (millis() >= next_poll_time)

That will fail at millis rollover. You shouldn't be predicting a future time. Store the previous time and compare to the current time with subtraction to see how long it has been. That's the only safe way to do it so it works past the rollover. See the "Blink Without Delay" example for an example of what it looks like.



Please read this before adding any more posts.

Threads merged.