Use flags from multiple sequences to poll serial data


txturbo

Recommended Posts

I have been updating some code in my application and want to understand if there is a downside to using a single serial loop and flags. 

 

As an example I have a stepper controller that uses serial coms. I have a  sequence that runs continuously getting status information, position, and home flags. Other sequences run programs that move the lift when called. On some pages I use quick sequences to move the stepper.  

As an example, most buttons have something like this:


   if (!device.step_1.LockPort())
      delay(0.5)
      continue
   endif
   device.step_1.Purge()

   try
      device.step_1.Write("+" + (v.lift_move(0)) + chr(13) + chr(10))
      device.step_1.UnlockPort()
   catch()
      device.step_1.UnlockPort()
      ? strLastError
      delay(0.5)
   endcatch
 

Sometimes when I used the buttons the UI can bog or flash the screen. I suspect this is due to the delay. 

 

I have decided to try a different approach using one main loop for the stepper and reading if flags have been set during the loop. Any buttons or sequences that need to interact with the stepper motor would set a variable and flag. 

 

Is there a downside to this approach? 

 

Example:
private count = 6

while(1)
   if (!device.step_1.LockPort())
      //throw("port in use!")
      delay(0.1)
      continue
   endif
   device.step_1.Purge()

   try
      device.step_1.Write("Z" + chr(13) + chr(10))  //read the lift position
      datain = device.step_1.ReadUntil(10)
      v.lift_pos.AddValue(right(datain,11))
      
      count -- // this is used to slow down any reads that are non critical
      if (count == 0)
         device.step_1.Write("] 1" + chr(13) + chr(10))  // read the home flag
         datain = device.step_1.ReadUntil(10)
         lift_home.AddValue(strtodouble(right(datain,6)))
         delay(.05)
         device.step_1.Write("] 0" + chr(13) + chr(10)) // read the limit flag
         datain = device.step_1.ReadUntil(10)
         lift_limits.AddValue(strtodouble(right(datain,3)))
         count = 6
      endif
      delay(0.07)
      
      
      if(lift_jog_plus_flag ==1)
         device.step_1.Write("+" + (v.lift_move[0]) + chr(13) + chr(10))  // used to jog the lift postiive
         lift_jog_plus_flag = 0
      endif
      
      if(lift_jog_negative_flag ==1)
         device.step_1.Write("-" + (v.lift_move[0]) + chr(13) + chr(10))  // used to jog the lift negative
         lift_jog_negative_flag = 0
      endif
      
      if(Lift_relative_flag ==1)
         device.step_1.Write("R" + (v.lift_rel[0]) + chr(13) + chr(10))  // used to move the lift relative 
         Lift_relative_flag = 0
      endif
      
      if(lift_move_flag ==1)
         if(v.panel_lift_move[0] > 0)
            device.step_1.Write (("+") + (v.panel_lift_move[0]) + chr(13) + chr(10))  // used from the main page to move the lift + with presets 
            else 
            device.step_1.Write (("-") + (v.panel_lift_move[0]) + chr(13) + chr(10))  // used from the main page to move the lift - with presets 
         endif
         lift_move_flag = 0
      endif
      
      if(lift_stop_flag == 1)
         device.step_1.Write(CHR(27) + chr(13) + chr(10))
         lift_stop_flag = 0
      endif
      
      if(lift_zero_flag == 1)
         device.step_1.Write("R" + (0) + chr(13) + chr(10))  // used to zero the lift
         lift_zero_flag = 0
      endif
      
      if(home_lift_flag == 1)
         device.step_1.Write("G" + chr(13))   // used to home the lift
         home_lift_flag = 0
      endif
      
      
      device.step_1.UnlockPort()
   catch()
      device.step_1.UnlockPort()
      ? strLastError
      delay(0.1)
      //throw()
   endcatch
   delay(0.1)
endwhile

 

 

 

 

 

 

 

Thanks!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

Link to comment
Share on other sites

No, the only downside is response time.  In your loop, it may take as long as 0.1 seconds (or more if its busy with other comms) between the time the flag is set, and the time the comms occurs for that flag.  Otherwise, I think you'll find that things actually run better using this technique.  Multithreading is great when the hardware can handle it, but in a lot of serial applications, it can't and by putting it in one thread you've eliminated potential issues.

You might consider using a message queue instead.  Then just create a sequence that monitors the queue to do the actual comms.  Move the timing of the reads out of that sequence and create two separate sequences to handle that.  The first, running at 0.1 seconds would add a request to the queue at that interval to read the position.  The second would run at 0.5 seconds and add a request to read the other items.  Other commands would add manually.  You could also create a separate function that adds to the queue uniquely, meaning, if the command is already in the queue it doesn't add it again.   

A messaging queue would be the cleanest solution and offer a lot more flexibility.  The way you have it now you are basically limited to a 0.1 second loop time because that's the interval you want to read the position.  But with a queue, you could have it loop and check the queue much faster, maybe 0.02 seconds.  Most of the time the queue is empty, but every 5 times it will get a read message.  And whenever you do a manual request, for example to home the lift, the response time will drop to 0.02 seconds.

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.