On button state change run loop once

Hi guys, I have a switch that when it changes state i want it to run a simple loop once.

Basically I have wired the arduino into a telephone, it dials a specific number.
I want it to dail the number (run the loop) when the phone is off the hook.
I have a small switch in there that changes state . I.e switched to high when the phone is picked up.
At this point I need the ardunio to use the switch in its permanent state to run the code once, so it only dials the number once and doesn't continue the loop and keep dialing the number.

When the phone is put down the switched it closed and is low.
I can swop the high and low around by the way I wired it but. Don't see that as important.

Thanks guys!
Stu

If you use a while loop checking when the button is HIGH in the setup(), it will only run once. You can leave loop() blank.

void loop(){

static bool AlreadyDialedTheNumberOnce = false;

if (whatever conditions causes you to dial  && ! AlreadyDialedTheNumberOnce){
  //do the dialing
AlreadyDialedTheNumberOnce = true;
}

Now if you have some other condition that can reset the whole shebang and let's you dial again, then all it needs to do is set that boolean back to false.

It seems that the state change detection example should have been looked at. When the receiver is picked up, the switch changes state. When the receiver is put down, the switch again changes state. One of those state changes is the one that you want to have trigger the dialing.

thanks so much for the replies guys!!

Still cant figure this out.
Delta_G That was so over my head.

can anyone give me a little example. Im thinking this needs a counter or the state change as Paul suggested.

Someone suggested that i define a val or integer and use an if statement to run the loop. At the end of the loop redefine the val to 0 or low. but this still isnt right, see below:

int Dail0 = 2; //sets the pin to the corresponding key pad number
int Switch = 12; // this is the switch, its an on off switch essentually
int val = 0;

void setup()
{
pinMode(Dail0, OUTPUT); // sets the pins as output
pinMode(Switch, INPUT); //this is my on off switch
}

void loop() {

val = digitalRead(Switch);

if (val == 1 ) {
digitalWrite(Dail0, HIGH); //dail number
delay(200);
digitalWrite(Dail0, LOW); //dail number
delay(200);
val = 0;
}

if (val == 0) {
digitalWrite(Dail0, LOW);
}

}

can anyone give me a little example.

There is an example provided with the Arduino IDE, called StateChangeDetection (on #2).

PaulS

Thanks, i looked over that example a few times, just went back to it now. i see how it could work to activate the loop but i dont get how it helps it just running once until the next state change. Wont it keep looping until the state changes? I feel like im missing something very logical here.

Wont it keep looping until the state changes? I feel like im missing something very logical here.

Yes, it will. The structure looks like this:

int oldState = LOW;
void loop()
{
    int newState = digitalRead(somePin);
    if(newState != oldState)
    {
        // the state has changed
        if(newState == LOW)
        {
           // the state changed to LOW. Do something if this is the state you are interested in
        }
        else
        {
           // the state changed to HIGH. Do something if this is the state you are interested in
        }
    }
    oldState = newState;
}

So, while loop will keep checking the current state, nothing happens until the current state is not the same as the previous state.

Even when the state HAS changed, you have a choice of dealing with the change, or not.

If you are counting switch presses, for instance, you don't care about switch releases, so the transition from released to pressed is interesting, but the transition from pressed to released is not.

Along with state change detection, you need some debouncing. The simplest way is:

void loop()
{
    int newState = digitalRead(12);
    if(newState != oldState)
    {
         if(newState == LOW)
        {
           digitalWrite(LED, HIGH);// the state changed to LOW. Do something if this is the state you are interested in
        }
        else
        {
           digitalWrite(LED, LOW);// the state changed to HIGH. Do something if this is the state you are interested in
        }

        delay(10); // wait for the switch to stop bouncing.
    }
    oldState = newState;
}

AMAZING. Awesome thank you Paul!!

Is there a way take it one step further. At the moment is dials on state change, and perfectly, and dials only once.

Is it easy to make it so it doesnt dial on every state change but only when the switch is either low or high?

Darn, just put it all together and ran some tests.

When the button is down the number keeps repeating and dials again and again,
when the button state changes .. it runs the code.
But the problem is because it keeps running when the button is down (the head set down) if you had to pick it up in mid dial it all goes wrong as the loop has to finish first..

So the code unfortunately doesn't just dial the numbers once for each change of state. :frowning:

void loop()
{
  int newState = digitalRead(12);
  if(newState != oldState)
  {
    // the state has changed
    if(newState == LOW)
    {
      digitalWrite(Dail0, LOW);
      digitalWrite(Dail1, LOW);
      digitalWrite(Dail2, LOW);
      digitalWrite(Dail3, LOW);
      digitalWrite(Dail4, LOW);
      digitalWrite(Dail5, LOW);
      digitalWrite(Dail8, LOW);
      digitalWrite(Dail9, LOW); 
    }
    else
    {
      delay (1000); //time to pick up handle

      digitalWrite(Dail1, HIGH);
      delay (200);
      digitalWrite(Dail1, LOW);
      delay (200);

      digitalWrite(Dail0, HIGH);
      delay (200);
      digitalWrite(Dail0, LOW);
      delay (200);

      digitalWrite(Dail2, HIGH);
      delay (200);
      digitalWrite(Dail2, LOW);
      delay (200);

      digitalWrite(Dail3, HIGH);
      delay (200);
      digitalWrite(Dail3, LOW);
      delay (200);



    }
    
    delay(10); // wait for the switch to stop bouncing.
  }
  oldState = newState;
}

i sorted this out by changing the newstate == HIGH as its the way my switch is wired.

I also swapped the code , so else sets everything to LOW.

I think thats it!! I hope this helps someone else out there. Paul a world of thank you!

void loop()
{
  int newState = digitalRead(12);
  if(newState != oldState)
  {
    // the state has changed
    if(newState == HIGH) //changed this due to switch configuration.
    {
      delay (1000); //time to pick up handle

      digitalWrite(Dail1, HIGH);
      delay (200);
      digitalWrite(Dail1, LOW);
      delay (200);

      digitalWrite(Dail0, HIGH);
      delay (200);
      digitalWrite(Dail0, LOW);
      delay (200);

      digitalWrite(Dail2, HIGH);
      delay (200);
      digitalWrite(Dail2, LOW);
      delay (200);

      digitalWrite(Dail3, HIGH);
      delay (200);
      digitalWrite(Dail3, LOW);
      delay (200);
    }
    else
    {


      digitalWrite(Dail0, LOW);
      digitalWrite(Dail1, LOW);
      digitalWrite(Dail2, LOW);
      digitalWrite(Dail3, LOW);
      digitalWrite(Dail4, LOW);
      digitalWrite(Dail5, LOW);
      digitalWrite(Dail8, LOW);
      digitalWrite(Dail9, LOW);

    }

    delay(10); // wait for the switch to stop bouncing.
  }
  oldState = newState;