txturbo Posted September 22, 2017 Share Posted September 22, 2017 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 More sharing options...
AzeoTech Posted September 25, 2017 Share Posted September 25, 2017 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 More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.