Read Switch Inputs for Certain Period  of Time

First, I am novice to Arduino programming and I have been trying to figure out how to count switch inputs over 10 seconds. Basically I have a relay attached to a security system that beeps 1, 2, 3, 4, or 6+ times depending on its state. So 1 is armed , 2 is disarmed, and so on.

The relay is attached to a draw down resistor on digital pin 9. I want to count the number of beeps over 10 seconds from the first beep. However, I'm not sure what loop function to use and I am a little confused about the millis() function in Arduino C. After "listening" for beeps for 10 seconds, I am then going to use a bunch of case statements to send a twitter through the Arduino ethernet shield I have to report on the state.

I'm just not sure about how to read data over that specific period of time. Also, I want to delay another loop of the program for five minutes but want to avoid using delay().

Any thoughts!

Thanks

Paddy

This is untested, but it should work:

#define RELAY 13
#define TIME_LIMIT 10000 //must be in ms

unsigned long time_start;
int beeps = 0;
bool relay_prev_state = false; 
bool *ptr_relay_prev_state = &relay_prev_state;; //creates a pointer, pointing to relay_prev_state

int did_it_beep(int in, bool *previous) //this function takes in an int of the input to watch and its previous state. If a rising edge is detected a 1 is returned. In all other cases, 0 is returned
{
      if(*previous == false && digitalRead(in) == HIGH) //checks for input to go from low to high - rising edge
      {
            *previous = true; //update content of previous
            return 1;
      }
      else if(*previous == true && digitalRead(in) == LOW) //checks for falling edge
            *previous = false; //update content of previous

      
      return 0;
}

void setup()
{
      pinMode(RELAY, INPUT);
}

void loop()
{
      beeps += did_it_beep(RELAY, ptr_relay_prev_state); //update beeps
      
      if(beeps == 1) //if first beep has occured
            time_start = millis(); //set time_start to current value of millis()
      
      while(millis() - time_start <= TIME_LIMIT && beeps >= 1) //while within the 10s range and  atleast 1 beep has occured
      {
            beeps += did_it_beep(RELAY, ptr_relay_prev_state); //update beeps
            //this loop will exit as soon 10s have passed
      }
      
      //Insert your actions here which use int beeps
      
      if(millis() - time_start > TIME_LIMIT) //if 10s have passed
            beeps = 0; //reset beeps to 0

}

In order to count the beeps i am watching for a rising edge (the transition from low to high). You cannot simply increment a counter if the relay is HIGH because the input pulse may exist over many cycles of the loop.

I am also using a pointer. read here if you don’t know what they are: http://www.cplusplus.com/doc/tutorial/pointers.html

Let me know exactly which parts you don’t understand and i can elaborate.

P.S - I doubt my code will work right outa the box, but if it does do not simply copy and paste. It is imperative that you understand each line so as to better yourself.

I haven’t looked closely at the logic but I don’t think you need that pointer. The state is not used outside the function so it can be declared inside as a static variable.

#define RELAY 13
#define TIME_LIMIT 10000 //must be in ms

unsigned long time_start;
int beeps = 0;

int did_it_beep(int in) //this function takes in an int of the input to watch and its previous state. If a rising edge is detected a 1 is returned. In all other cases, 0 is returned
{
static bool relay_prev_state = false;  // declared static so state is maintained across calls

      if(relay_prev_state == false && digitalRead(in) == HIGH) //checks for input to go from low to high - rising edge
      {
            relay_prev_state = true; //update content of previous
            return 1;
      }
      else if(relay_prev_state == true && digitalRead(in) == LOW) //checks for falling edge
            relay_prev_state = false; //update content of previous

      return 0;
}

void setup()
{
      pinMode(RELAY, INPUT);
}

void loop()
{
      beeps += did_it_beep(RELAY); //update beeps

      if(beeps == 1) //if first beep has occured
            time_start = millis(); //set time_start to current value of millis()

      while(millis() - time_start <= TIME_LIMIT && beeps >= 1) //while within the 10s range and  atleast 1 beep has occured
      {
            beeps += did_it_beep(RELAY); //update beeps, this loop will exit as soon 10s have passed
      }
      //Insert your actions here which use int beeps

      if(millis() - time_start > TIME_LIMIT) //if 10s have passed
            beeps = 0; //reset beeps to 0
}

Thank you very much fusive and mem. I will tweak things this weekend and let you know how it goes. I get the gist of the program just by looking through it, timing functions on the Arduino aren't quite as easy as on my desktop.

I've been reading pretty extensively about data logging and am thinking about integrating an SD card into the mix to keep track of things. We'll see though.

Thanks again for the help, I'll update come sat.

Paddy

Hey mem,

thats good stuff, I hadn't thought of that. I do have one issue with it though:

If you are using the function for multiple inputs, it will toggle the same static bool each time, even though each of them should have unique bools. By passing in a pointer to the bool, I am allowing the function to be used for multiple inputs.

FusiveResonance, it has been my experience that it's best to make each function no more complicated than it needs to be to be. YMMV

Have fun!

If you are using the function for multiple inputs, it will toggle the same static bool each time, even though each of them should have unique bools.

If you have data that is associated with specific functions, especially if you want independent states with the same function, I immediately think of a class… such as making a class Relay can remember what the previous state is, and what pins are required, for each relay.

amen halley, I'm a big fan of object oriented programming and my code tends to be largely based around OO concepts.

In this case, the function that i wrote above, doesn't use an object but can very easily be converted to do so given the object.

Mem: Yes, i agree, KISS is an important principle. If you are going to make the prev_state variable a static bool then you might as well take away the int in parameter as the function can only be used for that specific input. Just a thought.