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!