6767 raise Exception ("Unsupported platform '%s'" % platform )
6868
6969
70+ class SpeedInteger (int ):
71+ pass
72+
73+
74+ class SpeedRPS (SpeedInteger ):
75+ """
76+ Speed in rotations-per-second
77+ """
78+
79+ def __str__ (self ):
80+ return ("%d rps" % self )
81+
82+ def get_speed_pct (self , motor ):
83+ """
84+ Return the motor speed percentage to achieve desired rotations-per-second
85+ """
86+ assert self <= motor .max_rps , "%s max RPS is %s, %s was requested" % (motor , motor .max_rps , self )
87+ return (self / motor .max_rps ) * 100
88+
89+
90+ class SpeedRPM (SpeedInteger ):
91+ """
92+ Speed in rotations-per-minute
93+ """
94+
95+ def __str__ (self ):
96+ return ("%d rpm" % self )
97+
98+ def get_speed_pct (self , motor ):
99+ """
100+ Return the motor speed percentage to achieve desired rotations-per-minute
101+ """
102+ assert self <= motor .max_rpm , "%s max RPM is %s, %s was requested" % (motor , motor .max_rpm , self )
103+ return (self / motor .max_rpm ) * 100
104+
105+
106+ class SpeedDPS (SpeedInteger ):
107+ """
108+ Speed in degrees-per-second
109+ """
110+
111+ def __str__ (self ):
112+ return ("%d dps" % self )
113+
114+ def get_speed_pct (self , motor ):
115+ """
116+ Return the motor speed percentage to achieve desired degrees-per-second
117+ """
118+ assert self <= motor .max_dps , "%s max DPS is %s, %s was requested" % (motor , motor .max_dps , self )
119+ return (self / motor .max_dps ) * 100
120+
121+
122+ class SpeedDPM (SpeedInteger ):
123+ """
124+ Speed in degrees-per-minute
125+ """
126+
127+ def __str__ (self ):
128+ return ("%d dpm" % self )
129+
130+ def get_speed_pct (self , motor ):
131+ """
132+ Return the motor speed percentage to achieve desired degrees-per-minute
133+ """
134+ assert self <= motor .max_dps , "%s max DPM is %s, %s was requested" % (motor , motor .max_dpm , self )
135+ return (self / motor .max_dpm ) * 100
136+
137+
70138class Motor (Device ):
71139
72140 """
@@ -113,6 +181,10 @@ class Motor(Device):
113181 '_stop_actions' ,
114182 '_time_sp' ,
115183 '_poll' ,
184+ 'max_rps' ,
185+ 'max_rpm' ,
186+ 'max_dps' ,
187+ 'max_dpm' ,
116188 ]
117189
118190 #: Run the motor until another command is sent.
@@ -222,6 +294,10 @@ def __init__(self, address=None, name_pattern=SYSTEM_DEVICE_NAME_CONVENTION, nam
222294 self ._stop_actions = None
223295 self ._time_sp = None
224296 self ._poll = None
297+ self .max_rps = float (self .max_speed / self .count_per_rot )
298+ self .max_rpm = self .max_rps * 60
299+ self .max_dps = self .max_rps * 360
300+ self .max_dpm = self .max_rpm * 360
225301
226302 @property
227303 def address (self ):
@@ -732,6 +808,18 @@ def wait_while(self, s, timeout=None):
732808 """
733809 return self .wait (lambda state : s not in state , timeout )
734810
811+ def _speed_pct (self , speed_pct ):
812+
813+ # If speed_pct is SpeedInteger object we must convert
814+ # SpeedRPS, etc to an actual speed percentage
815+ if isinstance (speed_pct , SpeedInteger ):
816+ speed_pct = speed_pct .get_speed_pct (self )
817+
818+ assert - 100 <= speed_pct <= 100 ,\
819+ "%s is an invalid speed_pct, must be between -100 and 100 (inclusive)" % speed_pct
820+
821+ return speed_pct
822+
735823 def _set_position_rotations (self , speed_pct , rotations ):
736824
737825 # +/- speed is used to control direction, rotations must be positive
@@ -760,10 +848,18 @@ def _set_brake(self, brake):
760848
761849 def on_for_rotations (self , speed_pct , rotations , brake = True , block = True ):
762850 """
763- Rotate the motor at 'speed' for 'rotations'
851+ Rotate the motor at 'speed_pct' for 'rotations'
852+
853+ 'speed_pct' can be an integer or a SpeedInteger object which will be
854+ converted to an actual speed percentage in _speed_pct()
764855 """
765- assert speed_pct >= - 100 and speed_pct <= 100 ,\
766- "%s is an invalid speed_pct, must be between -100 and 100 (inclusive)" % speed_pct
856+ speed_pct = self ._speed_pct (speed_pct )
857+
858+ if not speed_pct or not rotations :
859+ log .warning ("%s speed_pct is %s but rotations is %s, motor will not move" % (self , speed_pct , rotations ))
860+ self ._set_brake (brake )
861+ return
862+
767863 self .speed_sp = int ((speed_pct * self .max_speed ) / 100 )
768864 self ._set_position_rotations (speed_pct , rotations )
769865 self ._set_brake (brake )
@@ -775,10 +871,18 @@ def on_for_rotations(self, speed_pct, rotations, brake=True, block=True):
775871
776872 def on_for_degrees (self , speed_pct , degrees , brake = True , block = True ):
777873 """
778- Rotate the motor at 'speed' for 'degrees'
874+ Rotate the motor at 'speed_pct' for 'degrees'
875+
876+ 'speed_pct' can be an integer or a SpeedInteger object which will be
877+ converted to an actual speed percentage in _speed_pct()
779878 """
780- assert speed_pct >= - 100 and speed_pct <= 100 ,\
781- "%s is an invalid speed_pct, must be between -100 and 100 (inclusive)" % speed_pct
879+ speed_pct = self ._speed_pct (speed_pct )
880+
881+ if not speed_pct or not degrees :
882+ log .warning ("%s speed_pct is %s but degrees is %s, motor will not move" % (self , speed_pct , degrees ))
883+ self ._set_brake (brake )
884+ return
885+
782886 self .speed_sp = int ((speed_pct * self .max_speed ) / 100 )
783887 self ._set_position_degrees (speed_pct , degrees )
784888 self ._set_brake (brake )
@@ -788,12 +892,43 @@ def on_for_degrees(self, speed_pct, degrees, brake=True, block=True):
788892 self .wait_until ('running' , timeout = WAIT_RUNNING_TIMEOUT )
789893 self .wait_until_not_moving ()
790894
895+ def on_to_position (self , speed_pct , position , brake = True , block = True ):
896+ """
897+ Rotate the motor at 'speed_pct' to 'position'
898+
899+ 'speed_pct' can be an integer or a SpeedInteger object which will be
900+ converted to an actual speed percentage in _speed_pct()
901+ """
902+ speed_pct = self ._speed_pct (speed_pct )
903+
904+ if not speed_pct :
905+ log .warning ("%s speed_pct is %s, motor will not move" % (self , speed_pct ))
906+ self ._set_brake (brake )
907+ return
908+
909+ self .speed_sp = int ((speed_pct * self .max_speed ) / 100 )
910+ self .position_sp = position
911+ self ._set_brake (brake )
912+ self .run_to_abs_pos ()
913+
914+ if block :
915+ self .wait_until ('running' , timeout = WAIT_RUNNING_TIMEOUT )
916+ self .wait_until_not_moving ()
917+
791918 def on_for_seconds (self , speed_pct , seconds , brake = True , block = True ):
792919 """
793- Rotate the motor at 'speed' for 'seconds'
920+ Rotate the motor at 'speed_pct' for 'seconds'
921+
922+ 'speed_pct' can be an integer or a SpeedInteger object which will be
923+ converted to an actual speed percentage in _speed_pct()
794924 """
795- assert speed_pct >= - 100 and speed_pct <= 100 ,\
796- "%s is an invalid speed_pct, must be between -100 and 100 (inclusive)" % speed_pct
925+ speed_pct = self ._speed_pct (speed_pct )
926+
927+ if not speed_pct or not seconds :
928+ log .warning ("%s speed_pct is %s but seconds is %s, motor will not move" % (self , speed_pct , seconds ))
929+ self ._set_brake (brake )
930+ return
931+
797932 self .speed_sp = int ((speed_pct * self .max_speed ) / 100 )
798933 self .time_sp = int (seconds * 1000 )
799934 self ._set_brake (brake )
@@ -803,15 +938,31 @@ def on_for_seconds(self, speed_pct, seconds, brake=True, block=True):
803938 self .wait_until ('running' , timeout = WAIT_RUNNING_TIMEOUT )
804939 self .wait_until_not_moving ()
805940
806- def on (self , speed_pct ):
941+ def on (self , speed_pct , brake = True , block = False ):
807942 """
808- Rotate the motor at 'speed' for forever
943+ Rotate the motor at 'speed_pct' for forever
944+
945+ 'speed_pct' can be an integer or a SpeedInteger object which will be
946+ converted to an actual speed percentage in _speed_pct()
947+
948+ Note that `block` is False by default, this is different from the
949+ other `on_for_XYZ` methods
809950 """
810- assert speed_pct >= - 100 and speed_pct <= 100 ,\
811- "%s is an invalid speed_pct, must be between -100 and 100 (inclusive)" % speed_pct
951+ speed_pct = self ._speed_pct (speed_pct )
952+
953+ if not speed_pct :
954+ log .warning ("%s speed_pct is %s, motor will not move" % (self , speed_pct ))
955+ self ._set_brake (brake )
956+ return
957+
812958 self .speed_sp = int ((speed_pct * self .max_speed ) / 100 )
959+ self ._set_brake (brake )
813960 self .run_forever ()
814961
962+ if block :
963+ self .wait_until ('running' , timeout = WAIT_RUNNING_TIMEOUT )
964+ self .wait_until_not_moving ()
965+
815966 def off (self , brake = True ):
816967 self ._set_brake (brake )
817968 self .stop ()
0 commit comments