Announcement

Collapse
No announcement yet.

Exiting a while loop while in the Genie Event Handler?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Exiting a while loop while in the Genie Event Handler?

    Hello,

    I am banging myhead against the wall trying to figure out how I can exit a while loop based that is inside the Genie Event handler, it seems so easy. I am not stuck to a while loop but it is the only thing I can think of.

    Basically I have a button on the display setup as both. When the button is pressed (storeButton1 = 1) long enough (KEYDOWN) the value is stored in a location and the corresponding LED shows it is stored. If the button is released before KEYDOWN it just goes to the previously stored location. I cannot figure out how I can get out of the while loop to read the button event.

    I am stuck as to how I can read an event change while stuck inside a while loop. I have used two if loops, one to start the timer, and the other to read it, but that does not show when the vaule is stored, i.e., KEYDOWN time is exceeded and LED is turned on. So I do not know if the time I held the button down was long enough to store the value until I release it.

    Here is the code inside the genie event handler:


    Code:
    if (Event.reportObject.index == 7)
    {
      storeButton1 = genie.GetEventData(&Event);
      unsigned long finalTime = 0; // Reset final time
      if (storeButton1 == 1) // Key is pressed
      {
        keyTime = millis(); // Base time is set
      }
    
      while (storeButton = 1)
      {
        finalTime = millis() - keyTime; // Final time is calculated
        if (KEYDOWN < finalTime) // If final time is greater then the Keytime
        {
          location1 = counts; // Store counts in location1
          genie.WriteObject(GENIE_OBJ_LED, 1 , 1); // Set Location1's LED
        }
        gotoLocation(location1); // If final time is less than Keytime goto location
      }
    }

    Thanks for any help.
    -Erik
    Last edited by Vince_4D; 2nd April 2018, 05:00 PM. Reason: I edited the format of your code for better readability - Vince

  • #2
    to exit the while loop without exiting the handler, issue a “break;” when needed, you also cant poll within the same callback, do the capture on next callback

    Comment


    • #3
      Hello Erik,

      With regards to your code, it is not recommended to use long loops inside the event handler.
      Instead, you could just trigger some flags through genie event handling then check and process those flags in the main loop.

      Below is another way of implementing the process you wanted (based on what i understand).

      I hope this will help.

      Vince

      Code:
      /*
         This program stores new data after pressing the Button  for 2 sec or more
         and retains data otherwise
      */
      
      #include <genieArduino.h>
      #include <SoftwareSerial.h>
      #define RESETLINE 4
      
      Genie genie;
      SoftwareSerial serial(5, 6);
      
      static long timePress;
      static long PRESS_TIME =  2000; //prolong pressing time
      
      bool buttonPress = false;
      
      void setup()
      {
        Serial.begin(9600);
        serial.begin(9600);
        genie.Begin(serial);
      
        genie.AttachEventHandler(myGenieEventHandler);
      
        pinMode(RESETLINE, OUTPUT);
        digitalWrite(RESETLINE, 1);
        delay(100);
        digitalWrite(RESETLINE, 0);
        delay (3500);
        Serial.println("START!");
      
      }
      
      void loop()
      {
      
        genie.DoEvents();
      
        if (buttonPress == true) {
          if (millis() - timePress > 2000) {
            genie.WriteObject(GENIE_OBJ_LED, 0 , 1);
      
            /*
              store new location function
            */
          } else {
       
            /*
              store current location function
            */
          }
        }
      
      }
      
      void myGenieEventHandler(void)
      {
        genieFrame Event;
        genie.DequeueEvent(&Event);
      
        if (Event.reportObject.cmd == GENIE_REPORT_EVENT)
        {
          if (Event.reportObject.object == GENIE_OBJ_WINBUTTON)    //Reported Message from winbutton
          {
            if (Event.reportObject.index == 0)  {                   // Receive the data from the Button0 (press/released)
      
              int state = genie.GetEventData(&Event);
              if (state == 1) {              // button pressed
                timePress = millis();
                buttonPress = true;
              } else if (state == 0) {       // button released
                buttonPress = false;
              }
            }
          }
        }
      }
      Vince_4D

      Comment


      • #4
        Thanks for the reply! "break" does not work for me since it will always break when I press the button and thus will always store the location and turn on the LED.

        What I am after is if the button is pressed less then KEYDOWN time it would run the function gotoLocation(), but if I press the button more than KEYDOWN it would store the location and turn on the LED next to the button.

        I am interested in the idea of capturing the next callback, since I have not done anything with callback, as a matter of fact I had to readup on it after your post. Even though, I cannot figure out how it would work for a callback to get me the status change of storeButton1 while in a while loop. I would be appreciative for any guidence.

        Currently I have this code which works, except that the LED will not light until I release the button, so I am not sure if I held the button long enough to store the value.

        if (Event.reportObject.index == 7) //
        { //
        storeButton1 = genie.GetEventData(&Event);
        unsigned long finalTime = 0; // Reset final time
        if (storeButton1 == 1) // Key is pressed

        keyTime = millis(); // Base time is set
        }

        if (storeButton1 == 0) // Key is released
        {
        finalTime = millis()-keyTime; // Final time is calculated
        if (KEYDOWN < finalTime) // If final time is greater then the Keytime
        {
        location1 = counts; // Store counts in location1
        genie.WriteObject(GENIE_OBJ_LED, 1 , 1); // Set Location1's LED
        }
        gotoLocation(location1); // If final time is less than Keytime goto location
        }

        }


        Thanks

        Comment


        • #5
          please change the button to “both” instead of default action in workshop (momentary)

          reason is, when its set to both, it changes things with arduino

          there is 2 callbacks

          one when you press (and never release)
          and
          one when you let go

          i use this method for a push button and count the seconds until the release callback is sent

          this way you can count the time in the loop after the button is pressed up until its released, and turn your led on, no while loop necessary

          EDIT, with momentary it only tells you the button was pressed only when you let go, with “both”, as soon as you touch arduino gets a callback, letting go gets another
          Last edited by tonton81; 2nd April 2018, 06:09 PM.

          Comment


          • #6
            Hello Vince,

            I really appreciate the quick reply, with this kind of support you are forcing me to keep buying 4D displays ;-)

            I really like the structure it is nice and simple, however it is partially working.

            What seems to be happening is that when I push the button to store the location (counts), the first run through if (millis() - timePress > 2000) is false so it runs gotoLocation(location1);which seems to clear the location entered in via the 4d keypad.

            What should be happening when the button is pressed less than 2sec is that gotoLocation(location1);should execute when button is released and if (millis() - timePress > 2000) is not true, so the motor goes to the location.

            If I want to store the current motor location then gotoLocation(location1); should never execute and if (millis() - timePress > 2000) becomes true and stores the location (location1 = counts).

            What I tried is this. (irrelevant sections of code removed):

            Code:
            void loop()
            {
              genie.DoEvents();
              if (buttonPress == true)
              {
                if (millis() - timePress > 2000)
                {
                  genie.WriteObject(GENIE_OBJ_LED, 1 , 1);
                  location1 = counts; //store counts (4D keypad specified location) in location1
                }
                else
                {
                  gotoLocation(location1); // Run motor until it reaches the location
                }
            
              }
              ////////////////////////////////////////////////////////////////////////////////////////////////////////////
              void myGenieEventHandler(void)
              {
                genieFrame Event;
                genie.DequeueEvent(&Event);
            
                if (Event.reportObject.cmd == GENIE_REPORT_EVENT)
                {
                  if (Event.reportObject.object == GENIE_OBJ_4DBUTTON) // Reported Message from button
                  {
                    if (Event.reportObject.index == 7) // Receive the data from the Button7 (press/released)
                    {
                      int state = genie.GetEventData(&Event);
                      if (state == 1) // button pressed
                      {
                        timePress = millis();
                        buttonPress = true;
                      }
                      else if (state == 0) // button released
                      {
                        buttonPress = false;
            
                      }
            
                    }
            
                  }
                }
              }



            I am sure there is just a little massaging to get it to work, which I will try in the morning since I am on the USA pacific coast.

            Thanks again!
            -Erik
            Last edited by Vince_4D; 3rd April 2018, 10:50 AM. Reason: I edited the format of your code for better readability - Vince

            Comment


            • #7
              Greetings Erik,

              Thank you for clarifying what you intended to do.

              Below is the modified code based to the process you want to implement.

              Hope this works.

              Code:
              /* Modified Code */
              
              #include <genieArduino.h>
              #include <SoftwareSerial.h>
              #define RESETLINE 4
              
              Genie genie;
              SoftwareSerial serial(5, 6);
              
              static long timePress;
              static long KEYDOWN_TIME =  2000; //prolong pressing time
              
              bool buttonPress = false;
              
              void setup()
              {
                Serial.begin(9600);
                serial.begin(9600);
                genie.Begin(serial);
              
                genie.AttachEventHandler(myGenieEventHandler);
              
                pinMode(RESETLINE, OUTPUT);
                digitalWrite(RESETLINE, 1);
                delay(100);
                digitalWrite(RESETLINE, 0);
                delay (3500);
                Serial.println("START!");
              
              }
              
              void loop()
              {
              
                genie.DoEvents();
              
                if (buttonPress == true) {
                  if (millis() - timePress >= KEYDOWN_TIME) {
                    genie.WriteObject(GENIE_OBJ_LED, 1, 1);       // led on  
                    storeLocation();                              //store new location function
                  } 
                }
              
              }
              
              void myGenieEventHandler(void)
              {
                genieFrame Event;
                genie.DequeueEvent(&Event);
              
                if (Event.reportObject.cmd == GENIE_REPORT_EVENT)
                {
                  if (Event.reportObject.object == GENIE_OBJ_4DBUTTON)      //Reported Message from 4DButton
                  {
                    if (Event.reportObject.index == 7)  {                   // Receive the data from the 4DButton (pressed/released)
              
                      int state = genie.GetEventData(&Event);
                      if (state == 1) {              // button pressed
                        timePress = millis();
                        buttonPress = true;
                      } else if (state == 0) {       // button released
                        buttonPress = false;
                        if (millis() - timePress < KEYDOWN_TIME) {
                          gotoLocation();                             //go to location if pressed < 2 sec
                        }
                      }
                    }
                  }
                }
              }
              
              void gotoLocation() {
                // do something
              }
              
              void storeLocation() {
                // do something
              
                // maybe turn off LED when done
                genie.WriteObject(GENIE_OBJ_LED, 1, 0);       // led off
              }
              Best regards

              Vince


              Vince_4D

              Comment


              • #8
                Bingo, that was it! Really appreciate this Vince. I made this so much more difficult then it needed to be.

                -Erik

                Comment

                Working...
                X