How is my variable getting reset without instructions to do so?

Beginner here, seeking help with a surprising output.

I'm programming an alarm clock that turns off when a target is hit. I have both parts working - the alarm clock and the target sensor - but I've made an unidentified error in getting the alarm to turn off when the target is hit.

I also get duplicates of some serial monitor lines. That's probably unrelated, but in case it's not, I figured I'd mention it.

The target is being read correctly, and 'alarmstate' set to 0, which should end the alarm, but the buzzer doesn't stop. I see in the serial monitor that the 'alarmstate' is being set back to 1.

Why is that? The code setting alarmstate = 1 is in the setup, not in the loop of the program.

The loop does have a brief check to reset the alarmstate to 1 at midnight, but the problem remains even when I remove those lines. Then the setup is the ONLY place the alarmstate is set to 1.

How is it getting back to 1?

Thanks, oh Arduino gurus. This one is puzzling me.

#include <DS3231.h>
#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
DS3231  rtc(SDA, SCL);
Time  t;

#define buz 11

int Hor;
int Min;
int Sec;

const int knockSensor = A0; // the piezo is connected to analog pin 0
const int threshold = 550;  // high threshold value to decide when the detected sound is a knock or not
const int threshold2 = 470; // low threshold

int sensorReading;      // variable to store the value read from the sensor pin
int end_time;    // variable to set how long the starting buzzer activates
// A starting buzzer makes it easier to test the target whent the program is loaded
// but it can be commented out if you just want the alarm clock to run
int alarmstate;  // make alarm to active. Set to zero to turn off.

void setup()

{  


// setting base values for the variables
sensorReading = 500;
end_time= 0;
alarmstate = 1;

  // this limits the starting buzzer to (end_time/1000) seconds and prints the value
 //  end_time=millis()+60000;  un-comment this to activate the starting buzzer for 60 seconds.
 

  // Alarm Clock Code begins here
  Wire.begin();

  rtc.begin();

  Serial.begin(9600);

    // Note length of starting buzzer, in seconds. Oddly, this prints twice. 
    Serial.print("end time = ");
    Serial.println((end_time/1000));

  pinMode(buz, OUTPUT);

  lcd.begin(16,2);     

  lcd.setCursor(0,0);

    lcd.print("Arduino Alarm ");

  lcd.setCursor(0,1);

  lcd.print("      Target ");

 
    
  delay(100);

  // Un-comment these 3 lines to set the date and time, then re-comment after running once.
 // rtc.setDOW(SUNDAY);     // Set Day-of-Week to SUNDAY
  // rtc.setTime(15, 37, 30);     // Set the time to 12:00:00 (24hr format)
// rtc.setDate(9, 5, 2021);   // Set the date to Sep 5th, 2021

}



void loop()
{

 // Update and display time
  t = rtc.getTime();
  Hor = t.hour;
  Min = t.min;
  Sec = t.sec;
  lcd.setCursor(0,0);
  lcd.print("Time: ");
  lcd.print(rtc.getTimeStr());
 lcd.setCursor(0,1);
 lcd.print("Date: ");
 lcd.print(rtc.getDateStr());

// reset alarm active state at midnight
if( Hor == 00 &&  Min == 00 )
{
  alarmstate=1;
} 


  // this sounds a buzzer when the program starts, making it easy to test the target.
  // it runs for (end_time/1000) seconds, or until the target is hit
  // when the target is hit, end_time is set to zero, so the starting buzzer isn't re-activated.
if( (millis()<=end_time)  && (sensorReading < threshold || sensorReading > threshold2)) //Comparing the current time with the Alarm time
{
  // prints the time in seconds that this initial routine has been running
    Serial.print("seconds = ");
    Serial.println((millis()/1000));
    
Buzzer();
Buzzer();

lcd.clear();
lcd.print("Alarm ON");
lcd.setCursor(0,1);
lcd.print("Alarming");

Buzzer();
Buzzer();

} 

delay(100);



 if( Hor == 16 &&  (Min == 45 || Min == 46)  && (alarmstate = 1))//Comparing current time with  Alarm time and seeing if the alarm is turned on.

{
sensorReading = analogRead(knockSensor);
     Serial.print("Sensor Reading = ");
    Serial.println(sensorReading);
             Serial.print("Alarm State = ");
    Serial.println(alarmstate);


if (sensorReading < threshold && sensorReading > threshold2)
{
Buzzer();
Buzzer();

lcd.clear();
lcd.print("Alarm ON");
lcd.setCursor(0,1);
lcd.print("Alarming");
Buzzer();
Buzzer();
} 
else
{
     Serial.print("Sensor Reading = ");
    Serial.println(sensorReading);
    Serial.println("Target hit!");
    alarmstate=0;
         Serial.print("Alarm State = ");
    Serial.println(alarmstate);
} 

    // set end_time to zero so that this loop stops playing the starting buzzer
    end_time = 0;
  delay(100);  // delay to avoid overloading the serial port buffer

}
} 



void Buzzer()

{

digitalWrite(buz,HIGH);

delay(10);

digitalWrite(buz, LOW);

delay(100);

}

image

:thinking: :question:

2 Likes

Ahem. Nothing to see here, move along, move along.

I don't know if it's less or more embarrassing to note that I didn't post this before going over the code multiple times. But if you need me, I'll be hiding under that blanket over there.

Thanks, Chris.

2 Likes

This would have been a good time to use a boolean ('bool') variable. If you had used:
bool alarmstate = false;
you would naturally use;
if (alarmstate)
instead of
if (alarmstate == 1)

2 Likes

Oh, thanks, John - I'm still working on this, so I can incorporate that code.

Using a 'bool' variable is new to me, and I'm following the reference info on this site. Do I read correctly that I can change between 'false' and 'true' either with

bool alarmstate = false;
bool alarmstate = true;

or with a toggle, like this?

alarmstate = !alarmstate;

And to clarify, this means, 'do these instructions only if the state is true,' yes?

Yes.

1 Like