From b86ba60a250a498003a423cbf89c6165a0729b70 Mon Sep 17 00:00:00 2001 From: Sonny Jeon Date: Fri, 27 Jan 2012 19:48:46 -0700 Subject: [PATCH] Updated streaming scripts. Compiler compatibility for _delay_ms(). - Moved obsolete streaming scripts to folder for reference. - Added a more complex Python streaming script which uses the serial buffer as an additional streaming buffer. - Removed all references to a _delay_ms(variable) to allow for better porting across different compilers. --- motion_control.c | 2 +- nuts_bolts.c | 7 ++ nuts_bolts.h | 3 + script/{ => Obsolete}/console | 0 script/{ => Obsolete}/proxy | 0 script/{ => Obsolete}/stream | 0 script/{ => Obsolete}/stream.rb | 0 script/{ => Obsolete}/trapezoid_simulator.rb | 0 script/simple_stream.py | 9 ++ script/stream.py | 89 ++++++++++++++++++++ 10 files changed, 109 insertions(+), 1 deletion(-) rename script/{ => Obsolete}/console (100%) rename script/{ => Obsolete}/proxy (100%) rename script/{ => Obsolete}/stream (100%) rename script/{ => Obsolete}/stream.rb (100%) rename script/{ => Obsolete}/trapezoid_simulator.rb (100%) create mode 100755 script/stream.py diff --git a/motion_control.c b/motion_control.c index 06b7868..016b035 100644 --- a/motion_control.c +++ b/motion_control.c @@ -35,7 +35,7 @@ void mc_dwell(double seconds) { uint16_t i = floor(seconds); st_synchronize(); - _delay_ms(floor(1000*(seconds-i))); // Delay millisecond remainder + delay_ms(floor(1000*(seconds-i))); // Delay millisecond remainder while (i > 0) { _delay_ms(1000); // Delay one second i--; diff --git a/nuts_bolts.c b/nuts_bolts.c index 8a6960c..3c699c3 100644 --- a/nuts_bolts.c +++ b/nuts_bolts.c @@ -21,6 +21,7 @@ #include "nuts_bolts.h" #include #include +#include int read_double(char *line, uint8_t *char_counter, double *double_ptr) { @@ -36,3 +37,9 @@ int read_double(char *line, uint8_t *char_counter, double *double_ptr) return(true); } +// Delays variable defined milliseconds. Compiler compatibility fix for _delay_ms(), +// which only accepts constants in future compiler releases. +void delay_ms(uint16_t ms) +{ + while ( ms-- ) { _delay_ms(1); } +} diff --git a/nuts_bolts.h b/nuts_bolts.h index 54b3cb8..ae71773 100644 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -42,4 +42,7 @@ // a pointer to the result variable. Returns true when it succeeds int read_double(char *line, uint8_t *char_counter, double *double_ptr); +// Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms(). +void delay_ms(uint16_t ms); + #endif diff --git a/script/console b/script/Obsolete/console similarity index 100% rename from script/console rename to script/Obsolete/console diff --git a/script/proxy b/script/Obsolete/proxy similarity index 100% rename from script/proxy rename to script/Obsolete/proxy diff --git a/script/stream b/script/Obsolete/stream similarity index 100% rename from script/stream rename to script/Obsolete/stream diff --git a/script/stream.rb b/script/Obsolete/stream.rb similarity index 100% rename from script/stream.rb rename to script/Obsolete/stream.rb diff --git a/script/trapezoid_simulator.rb b/script/Obsolete/trapezoid_simulator.rb similarity index 100% rename from script/trapezoid_simulator.rb rename to script/Obsolete/trapezoid_simulator.rb diff --git a/script/simple_stream.py b/script/simple_stream.py index 8bd4b3b..5119db4 100755 --- a/script/simple_stream.py +++ b/script/simple_stream.py @@ -1,6 +1,15 @@ #!/usr/bin/env python """\ Simple g-code streaming script for grbl + +Provided as an illustration of the basic communication interface +for grbl. When grbl has finished parsing the g-code block, it will +return an 'ok' or 'error' response. When the planner buffer is full, +grbl will not send a response until the planner buffer clears space. + +G02/03 arcs are special exceptions, where they inject short line +segments directly into the planner. So there may not be a response +from grbl for the duration of the arc. """ import serial diff --git a/script/stream.py b/script/stream.py new file mode 100755 index 0000000..5b82c94 --- /dev/null +++ b/script/stream.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +"""\ +Stream g-code to grbl controller + +This script differs from the simple_stream.py script by +tracking the number of characters in grbl's serial read +buffer. This allows grbl to fetch the next line directly +from the serial buffer and does not have to wait for a +response from the computer. This effectively adds another +buffer layer to prevent buffer starvation. + +TODO: - Add runtime command capabilities + +Version: SKJ.20120110 +""" + +import serial +import re +import time +import sys +import argparse +# import threading + +RX_BUFFER_SIZE = 128 + +# Define command line argument interface +parser = argparse.ArgumentParser(description='Stream g-code file to grbl. (pySerial and argparse libraries required)') +parser.add_argument('gcode_file', type=argparse.FileType('r'), + help='g-code filename to be streamed') +parser.add_argument('device_file', + help='serial device path') +parser.add_argument('-q','--quiet',action='store_true', default=False, + help='suppress output text') +args = parser.parse_args() + +# Periodic timer to query for status reports +# TODO: Need to track down why this doesn't restart consistently before a release. +# def periodic(): +# s.write('?') +# t = threading.Timer(0.1, periodic) # In seconds +# t.start() + +# Initialize +s = serial.Serial(args.device_file,9600) +f = args.gcode_file +verbose = True +if args.quiet : verbose = False + +# Wake up grbl +print "Initializing grbl..." +s.write("\r\n\r\n") + +# Wait for grbl to initialize and flush startup text in serial input +time.sleep(2) +s.flushInput() + +# Stream g-code to grbl +print "Streaming ", args.gcode_file.name, " to ", args.device_file +l_count = 0 +g_count = 0 +c_line = [] +# periodic() # Start status report periodic timer +for line in f: + l_count += 1 # Iterate line counter +# l_block = re.sub('\s|\(.*?\)','',line).upper() # Strip comments/spaces/new line and capitalize + l_block = line.strip() + c_line.append(len(l_block)+1) # Track number of characters in grbl serial read buffer + grbl_out = '' + while sum(c_line) >= RX_BUFFER_SIZE-1 | s.inWaiting() : + out_temp = s.readline().strip() # Wait for grbl response + if out_temp.find('ok') < 0 and out_temp.find('error') < 0 : + print " Debug: ",out_temp # Debug response + else : + grbl_out += out_temp; + g_count += 1 # Iterate g-code counter + grbl_out += str(g_count); # Add line finished indicator + del c_line[0] + if verbose: print "SND: " + str(l_count) + " : " + l_block, + s.write(l_block + '\n') # Send block to grbl + if verbose : print "BUF:",str(sum(c_line)),"REC:",grbl_out + +# Wait for user input after streaming is completed +print "G-code streaming finished!\n" +print "WARNING: Wait until grbl completes buffered g-code blocks before exiting." +raw_input(" Press to exit and disable grbl.") + +# Close file and serial port +f.close() +s.close() \ No newline at end of file