grbl.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #!/usr/bin/python
  2. #
  3. # some common functions I use in GRBL
  4. # grbl.setup() - setup connection. can specify device, defaults to '/dev/ttyUSB0'
  5. # can specify baud, defaults to 8600
  6. # grbl.teardown() - explicitely closes the serial connection
  7. # grbl.send_command( cmd ) - send cmd to GRBL
  8. # grbl.get_position() - return (x, y, z) position
  9. # grbl.get_var_position( v ) - get variable 'v' position, where v is 'x', 'y' or 'z'
  10. # grbl.wait_for_var_position( v, pos ) - wait for axis 'v' to get within epsilon distance of 'pos'.
  11. # This call blocks until position is reached, sleeping for 'sleepy'
  12. # seconds at a time (sleepy can be subsecond).
  13. #
  14. import serial
  15. import re
  16. import math
  17. import time
  18. import sys
  19. # default values
  20. #
  21. device = "/dev/ttyUSB0"
  22. baud = 115200
  23. grbl_serial = None
  24. sleepy = 0.05
  25. var_epsilon = 0.005
  26. infn = None
  27. #verbose = False
  28. verbose = True
  29. def setup( dev = device, b = baud ):
  30. global device
  31. global baud
  32. global grbl_serial
  33. device = dev
  34. baud = b
  35. grbl_serial = serial.Serial( device, baud )
  36. def teardown():
  37. global grbl_serial
  38. if grbl_serial:
  39. if verbose:
  40. print "tearing down connection"
  41. grbl_serial.close()
  42. def send_initial_command( cmd ) :
  43. global grbl_serial
  44. global verbose
  45. if verbose:
  46. print "# sending initial command '" + cmd + "'"
  47. grbl_serial.write(cmd + "\n")
  48. grbl_out = grbl_serial.readline()
  49. ans = grbl_out
  50. if verbose:
  51. print "# got :", grbl_out.strip(), ":"
  52. if ( re.search("^error:", grbl_out) ):
  53. return ans
  54. if ( re.search("^Grbl", grbl_out) or re.search("^\s*$", grbl_out) ):
  55. grbl_out = grbl_serial.readline()
  56. ans = grbl_out
  57. if verbose:
  58. print "# got :", grbl_out.strip()
  59. if ( re.search("^\['", grbl_out) or re.search("^\s*$", grbl_out) ):
  60. grbl_out = grbl_serial.readline()
  61. ans = grbl_out
  62. if verbose:
  63. print "# got :", grbl_out.strip()
  64. if verbose:
  65. print "#", grbl_out
  66. return ans
  67. def send_command( cmd ) :
  68. global grbl_serial
  69. global verbose
  70. if verbose:
  71. print "# sending '" + cmd + "'"
  72. grbl_serial.write(cmd + "\n")
  73. grbl_out = grbl_serial.readline()
  74. ans = grbl_out
  75. if verbose:
  76. print "# got :", grbl_out.strip(), ":"
  77. if ( re.search("^error:", grbl_out) ):
  78. return ans
  79. if ( re.search("^Grbl", grbl_out) or re.search("^\s*$", grbl_out) ):
  80. grbl_out = grbl_serial.readline()
  81. ans = grbl_out
  82. if verbose:
  83. print "# got :", grbl_out.strip()
  84. if ( re.search("^\['", grbl_out) or re.search("^\s*$", grbl_out) ):
  85. grbl_out = grbl_serial.readline()
  86. ans = grbl_out
  87. if verbose:
  88. print "# got :", grbl_out.strip()
  89. while ( not re.search("ok", grbl_out) ):
  90. grbl_out = grbl_serial.readline()
  91. if verbose:
  92. print "# got:", grbl_out.strip()
  93. ans += grbl_out
  94. if ( re.search("^error:", grbl_out) ):
  95. return ans
  96. if verbose:
  97. print "#", grbl_out
  98. return ans
  99. def get_position():
  100. global grbl_serial
  101. global verbose
  102. grbl_serial.write("?")
  103. grbl_out = grbl_serial.readline()
  104. m = re.search( "^<([^,]*),MPos:([^,]*),([^,]*),([^,]*),", grbl_out)
  105. if ( m ):
  106. if verbose:
  107. print "# matched", m.group(0)
  108. state = m.group(1)
  109. x = float(m.group(2))
  110. y = float(m.group(3))
  111. z = float(m.group(4))
  112. return x, y, z
  113. return None, None, None
  114. def get_var_position( var_name ):
  115. global grbl_serial
  116. global verbose
  117. var_seen = 0
  118. var_pos = 0.0
  119. #grbl_serial.write("$?\n")
  120. grbl_serial.write("?")
  121. grbl_out = grbl_serial.readline()
  122. if verbose:
  123. print "# get_var_position(", var_name, "): got :", grbl_out.strip()
  124. m = re.search( "^<([^,]*),MPos:([^,]*),([^,]*),([^,]*),", grbl_out)
  125. if ( m ):
  126. if verbose:
  127. print "# matched", m.group(0)
  128. state = m.group(1)
  129. x = float(m.group(2))
  130. y = float(m.group(3))
  131. z = float(m.group(4))
  132. if ( var_name == 'x') or ( var_name == 'X'):
  133. return x
  134. if ( var_name == 'y') or ( var_name == 'Y'):
  135. return y
  136. if ( var_name == 'z') or ( var_name == 'Z'):
  137. return z
  138. def wait_for_var_position( var_name, var_val ):
  139. global grbl_serial
  140. global verbose
  141. global sleepy
  142. global var_epsilon
  143. cur_val = get_var_position( var_name )
  144. if verbose:
  145. print "#", str(var_val), " var_epsilon", str(var_epsilon), "cur_x", str(cur_val)
  146. while (math.fabs(var_val - cur_val) > var_epsilon):
  147. if verbose:
  148. print "# cur_val", str(cur_val), ", waiting for ", var_name, str(var_val)
  149. time.sleep(sleepy)
  150. cur_val = get_var_position( var_name )
  151. return cur_val
  152. if __name__ == "__main__":
  153. import argparse
  154. parser = argparse.ArgumentParser(description='Send GRBL commands.')
  155. parser.add_argument("-B", "--baud", help="Set baud rate (default 9600)", nargs = 1, default=[baud], type=int)
  156. parser.add_argument("-D", "--device", help="Set device (default /dev/ttyUSB0)", nargs = 1, default=[device] )
  157. parser.add_argument("-v", "--verbose", help="Set verbose mode", default=verbose, action='store_true')
  158. parser.add_argument("-f", "--file", help="input file", nargs=1, type=str)
  159. parser.add_argument("command", help="Command to send GRBL", nargs="*" )
  160. args = parser.parse_args()
  161. if hasattr(args, 'baud'):
  162. baud = args.baud[0]
  163. if hasattr(args, 'device'):
  164. device = args.device[0]
  165. if hasattr(args, 'verbose'):
  166. verbose = args.verbose
  167. if hasattr(args, 'file'):
  168. infn = args.file[0]
  169. if infn is None and len(args.command)==0:
  170. print ""
  171. parser.print_help()
  172. print ""
  173. sys.exit(-1)
  174. if verbose:
  175. print "baud:", baud
  176. print "device:", device
  177. setup(device, baud)
  178. #print "setup done..."
  179. v = send_initial_command("")
  180. #print "got", v
  181. if infn is not None:
  182. with open(infn, "r") as fp:
  183. for line in fp:
  184. line = line.strip()
  185. if verbose:
  186. print "sending command", line
  187. send_command(line)
  188. else:
  189. for cmd in args.command:
  190. if verbose:
  191. print "sending command", cmd
  192. print send_command(cmd)
  193. if verbose:
  194. print "tearing down..."
  195. teardown()