12V Siren clicks when signaled, but does not produce continuous sound.

Hello there.

My project involves a probe that reads temperature and pH data. One objective of the project is to sound an alarm when pH or temperature data are outside of preset bounds. I have a function called alarm() that takes the data in and determines when to sound the alarm and turn on the corresponding LEDs. I am using the following 12V siren in my design:


And the circuit is set up like this currently:

While I am able to make the siren produce a sound for every data point that is outside the preset bounds, I'd like the sound to be continuous until either the data is back in the acceptable range (3-4pH, & 24-25 degrees celsius). The siren only makes a short clicking noise when I write to its pin with digitalWrite or with tone() as can be seen in my sketch:

#include <Ezo_i2c.h> //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib
#include <Wire.h>    //include arduinos i2c library
#include <Process.h>
#include <Bridge.h>
#include <String.h>

Ezo_board EC = Ezo_board(1, "ph");         //create a EC circuit object, w/ address 99 and name "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() {
//  Bridge.begin();
  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 (alarmMode == 1 && (ph_data > 4.000 || ph_data < 3.000 || temp_data > 25.000 || temp_data < 24.000)){
    tone(speakerPin, 1000, 1000); 
  }
  if(24.000 <= temp_data <= 25.000 || 3.000 <= ph_data <= 4.000){
    noTone(speakerPin);
  }
  if(3.000 <= ph_data <= 4.000){
    digitalWrite(high_ph_LED, LOW);
    digitalWrite(low_ph_LED, LOW);
    Serial.print(" ph is ok ");
  }  
  if (ph_data > 4.000){
    digitalWrite(high_ph_LED,HIGH);
    Serial.print(" high ph ");
  }
  if (ph_data < 3.000) {
    digitalWrite(low_ph_LED,HIGH);
    Serial.print(" low ph ");
  }
  if(24.000 <= temp_data <= 25.000){
    digitalWrite(high_temp_LED, LOW);
    digitalWrite(low_temp_LED, LOW);
    Serial.print(" temp is ok ");
  }   
  if (temp_data > 25.000){
    digitalWrite(high_temp_LED,HIGH);
    Serial.print(" high temp ");
  }
  if (temp_data < 24.000){
    digitalWrite(low_temp_LED,HIGH);
    Serial.print(" low temp ");
  }
}


void receive_reading(Ezo_board &Sensor) {    //function decodes reading 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") {
//        run_Curl(Sensor.get_reading(), ph_key); 
        ph = Sensor.get_reading();
      }   
      if (Sensor.get_name()=="RTD") {
//        run_Curl(Sensor.get_reading(), temp_key);
        temp = Sensor.get_reading();         
      }
      Serial.print(Sensor.get_reading(), 3);  //the command was successful, print the reading 
      break;

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

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

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


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)){
     EC.send_read_with_temp_comp(RTD.get_reading());
   }
    
   else{
     EC.send_read_with_temp_comp(25.0);
   }
    
   RTD.send_read();
    
   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.println(); 
      alarm(ph,temp);
      
      Serial.print("alarmMode: ");
      Serial.print(alarmMode);
      Serial.println();
        
      reading_request_phase = true;            //switch back to asking for readings
    }
  }
}

Any idea what might be causing this and how I could achieve my desired results? I would appreciate your help!

My best guess is the 9V battery cannot supply enough current to operate the Siren.

You will need something with more power.

You would not use tone() with a siren. The siren is either ON or OFF, so use digitalWrite().

The battery has a 12volt label on it...

You didn't connect source of the fet (siren ground) to Arduino ground.
Leo..

JohnRob:
My best guess is the 9V battery cannot supply enough current to operate the Siren.

You will need something with more power.

The program I used to illustrate that didn't have a picture for a power supply of 12V, hence the 12V note I wrote on top of the battery. Apologies if that was confusing, but I do have a power supply that is able to proivde 12V or more, and I have it set to 150mA since max is 200mA. Although I know that this siren can be used at lower voltage because I can connect the power supply directly to its leads and it'll still sound the alarm all the same at 5V too. Haven't tried any lower because the datasheet claims it is rated for 5-15V operation.

jremington:
You would not use tone() with a siren. The siren is either ON or OFF, so use digitalWrite().

Yeah, I was having the same issue with digitalWrite() before I tried out tone(). I'll change it back to digitalWrite(), but there must be more to it than that. Any idea what else might be causing this issue?

and I have it set to 150mA since max is 200mA

That would be a problem, since the siren draws 200 mA in normal operation. Set the power supply to 400 mA or higher and see if the siren works.

Wawa:
The battery has a 12volt label on it...

You didn't connect source of the fet (siren ground) to Arduino ground.
Leo..

Alright, so I connected the source on the FET to the ground bar on the other side of the breadboard that is wired up to GND on my arduino. That does not appear to have changed anything however. What is this connection supposed to accomplish electronically?

jremington:
That would be a problem, since the siren draws 200 mA in normal operation. Set the power supply to 400 mA or higher and see if the siren works.

I set the current to 0.4A, and then 0.44A, still didn't see any change in behavior. :confused:
When I connect the siren leads straight to the power supply, I'm able to get it to sound off at full blast with only 5V and 150mA, however. So I'm really puzzled as to why this isn't working. Any more thoughts or ideas?

Check and double check the continuity of all connections. The horizontal power and ground tracks on some breadboards are not connected across the vertical divide.

jremington:
Check and double check the continuity of all connections. The horizontal power and ground tracks on some breadboards are not connected across the vertical divide.

I can check that, but if the rest of my circuit works fine, then wouldn't that prove that those connections between vertical divides are there? All of the LEDs and buttons and even the data loggers are all on separate divides from the wires connecting the horizontal strips to 5V and GND on my arduino, as per my diagram.

  if (24.000 <= temp_data <= 25.000 || 3.000 <= ph_data <= 4.000) { // NO!
    noTone(speakerPin);
  }

You need to use individual comparisons and && them together.

You need to use individual comparisons and && them together.

I see your point! What if I used this:

if (temp_data > 24.000 && temp_data < 25.000 && ph_data > 3.000 && ph_data < 4.000){
  digitalWrite(speakerPin, LOW);
}

Better, but you have changed the logic to all && when there was previously an || as well...

Better, but you have changed the logic to all && when there was previously an || as well...

Good point, but now that I think about it, I think that I WOULD want that || to be an && because all 4 of those conditions must be met simultaneously for the speaker to not be sounding off. I also realized that I did not include the alarmMode == 0 condition in that statement, which would explain why I couldn't get the siren to shut up when I hit the button. I will be back after some testing. Thank you!

Hi,
Did you write your code in stages?
Proving each stage as you code, before adding the next?

Write a code JUST to switch the siren ON and OFF, nothing else in the code, just the siren output pin.
This will prove your circuit, before worrying about your code.

Tom... :slight_smile: