Shop OBEX P1 Docs P2 Docs Learn Events
How do run a loop until a condition exist — Parallax Forums

How do run a loop until a condition exist

I am working on making a counter for when a condition exists using the external encoders found in the Activity Bot kit. Currently a while(1) loop is used to monitor the condition of the encoder and adds a +1 while the encoder state is at 1, however this loop continues during the entire 1 state. Anyone run across a function or a concept that will only add 1 to a variable inside an endless loop during a transition from 1 to 0?

Comments

  • This is a common problem where you have two states and want to do something only when the state changes. You need another variable "oldState". This gets initialized to the encoder state just before the loop is started. In the loop, you read the encoder state into another variable "newState", then make decisions based on oldState and newState. At the end of the loop, you copy newState into oldState. During the loop you might have:

    if (newState == 1) variableA += 1;

    or:

    if (newState == 0 and oldState == 1) variableB += 1;
  • Took me awhile but I got the code to work. So far i have tested 128, 256, and 512 "ticks" in the drive_goto call which resulted in 64, 128, and 256.

    print("%c p26 LED Cnt = %d\n p26state LED Cnt = %d%c", HOME, encoderCount, pinState26new, CLREOL);
    set_output(26, input(14));
    set_output(27, input(15));
    pinState26new = get_state(14);
    {
    if ( pinState26new == 1 && pinState26 ==0 )
    {
    encoderCount += 1;
    }
    pinState26 = get_state(14);


    - Thanks!
  • Remember that you have to initialize pinState26 going into the loop
  • I would change the last line to pinState26 = pinState26new,
    Your input might change between the first reading of it and the second.
  • Mike Green wrote: »
    Remember that you have to initialize pinState26 going into the loop

    I'm new to programming so I may not understand the difference between initializing pinState26 first, the way the code is written currently the loop starts at the transition (to my understanding) of 1 from the encoder and asses the loop, when i tried both pin states before the loop the events of the transition from 1 to 0 was not recognized in the if statement, but I will play around with the code again.
    rbehm wrote: »
    I would change the last line to pinState26 = pinState26new,
    Your input might change between the first reading of it and the second.

    Thanks for the input, I will try pinState26 = pinState26new, although I didn't have any problems with the posted code I also didn't run tests using longer durations.
  • 3snke wrote: »
    Mike Green wrote: »
    Remember that you have to initialize pinState26 going into the loop

    I'm new to programming so I may not understand the difference between initializing pinState26 first, the way the code is written currently the loop starts at the transition (to my understanding) of 1 from the encoder and asses the loop, when i tried both pin states before the loop the events of the transition from 1 to 0 was not recognized in the if statement, but I will play around with the code again.
    There's no loop structure or calling code shown, so I assume this is the content of your loop.
    Each time through the loop you compare the 'new' (current) value with an old value. The first time through you don't have that old value, so you need to either compare with a default state, or by reading the pin once before you enter the loop.

    As pinState26 and pinState26new seem to be derived from the state of pin 14 you might want to reconsider your variable names. Better than naming them for a pin (which might change for a number of reasons) I would suggest a functional name, perhaps 'encoder'.

    Then before entering the loop you either read the current pin state or set it to a default.
    In the loop you read the current state, you perform your comparison and conditional action, update the storage variable, and then repeat.
    Something like:
    encoder = get_state(14);   // initialise state variable
    // loop starts here
    while (1) {
     print("%c p26 LED Cnt = %d\n p26state LED Cnt = %d%c", HOME, encoderCount, encoder, CLREOL);
     set_output(26, encoder);
     set_output(27, input(15));
     encodernew = get_state(14);
     {
     if ( encodernew == 1 && encoder ==0 )
     {
     encoderCount += 1;
     }
     encoder = encodernew;
    }
    

    This loop doesn't appear to do much more than provide human readable output while passing some state from one pair of pins to another. I assume that at some point you'll want this count to be reported to other code?

    Of course, on the Prop each Cog has two counter modules that can perform this logic for you. The POSEDGE detector mode with FRQx set to 1 would perform all the logic in this loop automatically, but you'd lose the pin state transfer (14 to 26, and 15 to 27) and the printing of state, which while helpful is quite time consuming, meaning some edges could be missed if the pulses are short enough.

    With the counter set up, you could simply read the PHSx register inside the code that currently calls the loop, rather than tying up a Cog with this while loop and having to pass the results to another Cog.
    3snke wrote: »
    rbehm wrote: »
    I would change the last line to pinState26 = pinState26new,
    Your input might change between the first reading of it and the second.

    Thanks for the input, I will try pinState26 = pinState26new, although I didn't have any problems with the posted code I also didn't run tests using longer durations.

    An issue would occur if the pin changed state between any of the three separate times that you read pin 14 in the loop:
    print("%c p26 LED Cnt = %d\n p26state LED Cnt = %d%c", HOME, encoderCount, pinState26new, CLREOL);
     set_output(26, input(14));      // <---- once; not so critical
     set_output(27, input(15));
     pinState26new = get_state(14);  // <----- twice; critical
     {
     if ( pinState26new == 1 && pinState26 ==0 )
     {
     encoderCount += 1;
     }
     pinState26 = get_state(14);     // <---- thrice; critical
    
    

Sign In or Register to comment.