Problems tracking pin state with Switch statement

I have a dial attached to pin 8. Rotating the dial sends out pulses which are measured through digitalread. Once the dial finishes rotating the number of pulses is put into an array. The problem is if I have it as part of a switch statement the measurements don't seem to happen properly.

loop()
{
dial();

}

Seems to work fine. However if I do something like

loop()
{


switch (vcs.CallStatus())
  {
    case X: //casex is met by default
    dial(); 
    break;

    case Y:  
    break;

    case Z: 
    break;
  }
}

It seems to be unable to properly detect the dialing, especially with smaller number of pulses. I think it might have to do with the pin not being measured quickly enough as the arduino is looping through the code so pulses are lost as they occur between measurements. The problem is I want to keep track of both callstatus and whether dialing is occurring at the same time or at least have them measured quickly enough that it does not matter and would rather not choose one or the other.

Dialing a value that allows the dial to rotate longer makes it more likely that a value (not necessarily the right one) is entered.

Here is the dialing code

//variables to read in dial pulses
int needToPrint = 0;
int count; //dial pulse counts
int lastState = LOW;
int trueState = LOW;
long lastStateChangeTime = 0;

// constants
int dialHasFinishedRotatingAfterMs = 100;
int debounceDelay = 10;

//phone number variables
int numquota = 0;//keeps track of how many digits of the phone number we have entered
char callednum[20];//number to call



int dial() //code for recognizing and reading in dial pulses
{
    int reading = digitalRead(dialPin);//set pin to read dial pulses


    if ((millis() - lastStateChangeTime) > dialHasFinishedRotatingAfterMs) {
        // the dial isn't being dialed, or has just finished being dialed.
        if (needToPrint) {
            // if it's only just finished being dialed, we need to send the number 
            // and reset the count. 
            transferredchar = dialarray[count-1];
            callednum[numquota]= transferredchar;
            callednum[numquota+1]= '\0';
            Serial.println("detecting dialing");
            Serial.println(callednum);
            needToPrint = 0;
            count = 0;
            numquota++;//increment till phone number length reached
        }
    }

    if (reading != lastState) {
        lastStateChangeTime = millis();
    }
    if ((millis() - lastStateChangeTime) > debounceDelay) {
        // debounce - this happens once it's stablized
        if (reading != trueState) {
            // this means that the switch has either just gone from closed->open or vice versa.
            trueState = reading;
            if (trueState == HIGH) {
                // increment the count of pulses if it's gone high.

                count++;
                needToPrint = 1; // we'll need to print this number (once the dial has finished rotating)
            }
        }
    }

    lastState = reading;

    //rotary addition

    if (numquota == 11 ) {//once the last digit has been reached send the number
        Serial.println("SENDING");
        gsm.call(callednum, 100);//send number to call
        while(1);
        Serial.println("NUMBER SENT");
        numquota = 0;//resets phone number digit count
        callednum[0] = '\0';
    }

}

First auto format your code before YOU try to debug it.

Second look in the playground for button/switch debounce.

Mark

holmes4: First auto format your code before YOU try to debug it.

Second look in the playground for button/switch debounce.

Mark

Hi, I don't think its a problem of reading too many pulses since there is already a debounce for reading in individual pulses thru debounceDelay and for adding a value after the dial has finished rotating thru dialHasFinishedRotatingAfterMs. I (think) the problem might be simply that the program might be missing pulses as it loops through the rest of the program. An entire pulse might happen between measurements and not be counted. I think this because rotating the dial longer makes it more likely to be measured and simply putting dial in a loop by itself fixes the problem. unfortunately I'd like to measure callstatus and detect dialing at the same time. or quickly enough that a change in either won't be missed.

The failing code calls vcs.CallStatus() each time around loop().

What does that method do, and how long does it take to execute?

PeterH:
The failing code calls vcs.CallStatus() each time around loop().

What does that method do, and how long does it take to execute?

Its a library function that checks the status of the line. Busy, Receiving call, etc

I’m not sure how long it takes but I’ll check when I can get back to the arduino.

Also, can you estimate the duration of the shortest encoder pulse that you want to be able to detect i.e. based on the speed you'll be turning the dial at, and the encoder resolution?

PeterH: Also, can you estimate the duration of the shortest encoder pulse that you want to be able to detect i.e. based on the speed you'll be turning the dial at, and the encoder resolution?

It seems it may be the speed of the loop after all. Measured the speed of the default loop with switch statement through millis() 25487 26006 26521 27036

so each cycle of the program in its default state takes around 500ms.

the dial() only loop is much faster 27092 27111 27129 27148

Measuring the time dial() detects a pulse when its by itself in loop() 51267 51363 51457 51554

so around 100 ms or less between pulses.

when I measure callStatus by itself in the loop.

90011 90526 91044 91560

So I need to figure out some way to both measure callstatus and dialing accounting for these speeds. The default gsm library for the regular gsm shield contains a delay of 1000ms for each cycle

http://arduino.cc/en/Tutorial/GSMExamplesReceiveVoiceCall

I feel I should probably add this in but it'd make the problem even worse. I don't see how the shield would be able to detect even button presses with all the delays these libraries seem to have built in.

I guess I should simply work around it then? Since the ‘easiest’ direct solution I can think of is multithreading.