Closed mkeyno closed 7 years ago
@mkeyno It is highly unlikely you will get a feed rate for 10000 on an Arduino 328 for grayscale image engraving. Especially not at 20 pixels per mm. On an Arduino Uno, I have achieve about 5000 max at 10 pixels per mm. I tried smoothie but it was even worse at about 3800. The winning combo was GRBL-LPC https://github.com/gnea/grbl-LPC running on a 120MHz Smoothieboard. Running at 10 pixels per mm, I've hit 13000 on greyscales and dithering, and 20000 on lineart.
@mkeyno you are trying to push 3333 pixels per second down a 12000 bytes per second pipe line. Each gcode line you have is about 20 characters long, so at best without optimising your gcode further, you might hit 600 pixels per second, or a feed of 2000 at best.
thanks @mayhem2408 , honestly I have no idea about how calculate the optimized engraving speed and really appreciated to let me know how to do it but before using GRBL , I used the revised version of Marlin for CNC laser , and it had very fast engraving speed , I wasn't sure it came by firmware itself of the engrave Gcode convertor plugin , however I was hopping to reach the fastest possible speed with GRBL
@mayhem2408 do you know why movement in GRBL engraving is not look like the fast reciprocating movement similar to other CNC engraving machine
@mkeyno GRBL on the Arduino with a 328 just runs out of steam with. On the Arduino Mega, with it's larger buffers seems to be a little better, but GRBL-LPC just kicks everything else out of the park. Even Marlin on a Mega2560 and it's base64 method seems to run out of processing power at around feed rates of 7000. If speed is keep, GRBL-LPC is the way to go. I have also found for what ever reason, GRBL-LPC receives data much faster than the 115200 baud selected.
So on an Arduino Uno running a 328, you have a maximum serial bandwidth of 115200 (By default, can be recompiled with a higher settings) that give you 12800 characters per second. Because of the ping pong mature of GRBL, lets just say 10000. So from the you need to look at the gcode file and estimate how many characters per line there are. Your screenshot shows lines line 'G1 X0 Y0.05 F40000 S0' which is 21 characters. Add 2 for a carriage return and you have 23. Let say 20 is the average. So 10000 / 20 = 500. With each line being 1 pixel, you have 500 pixels per second. With your resolution set to 20 pixels per millimeter, your have 500 / 20 = 25mm per second, or 1500mm per minute. Optimising the gcode can increase this.
I am experimenting with gcode where 1 pixel looks like 'X12.4S465' which is only 11 characters per line. So there we have about 1000 lines per second. I Greyscale engrave at 10 pixels per mm, so that's 100mm per second or 6000mm per minute. GRBL-LPC is doing over double this rate.
Hi @mkeyno and thanks @mayhem2408 for your precious comments and computation
In developing LaserGRBL I always had in mind hobby use of hardware with limited power and speed, specially DIY engraver up to 10W laser diode. Faster and powerfull hardware usually have a dedicated software optimized for controller board.
However, as already mentioned, there are speed limits due to some reasons.
First reason is arduino's working frequency and grbl code speed that fix a limit of about 30kHz as step frequency. With your $100=126 this is equivalent to 30000/126 = 238mm/s = 14'285mm/min so this is not the limit. https://github.com/grbl/grbl/issues/41 (this is not the bottleneck in your case)
Second reasone is the speed of communication in relation to the G-Code data stream. Sending a bitmap/raster image in G-Code syntax (which is designed for vector instructions) is a terrible waste of bytes. As much as code generation can be optimized, it always requires S(POWER) X(DISTANCE) commands to be sent. I.e To send four pixels 200-212-212-209 (4 bytes) with a 10lines/mm resolution (0.1mm step) this code is generated: "S200 X0.1 newline S212 X0.2 newline S209 X0.1" These are a total of 33 bytes. This data stream is able to quickly saturate the communication line and grbl buffer (which is only 127 bytes)
These are not Limits of LaserGRBL but are intrinsic to the use of G-Code/grbl. An efficient system requires a protocol that transfers the image as a bytes sequence, and a hardware card that can print images natively.
LaserGRBL could optimize a little the generated G-Code (i.e. trimming whitespaces, joining subsequential pixels of the same colour) but it will never be efficient just because the G-Code is not made to transfer/encode raster images.
@arkypita I understand that DIY hobby is the focus of many of these CNC projects, but you may have heard of the China made K40 laser cutters. Very cheap, very powerful with an optical output of 40W, but terrible software and controller. I picked mine up for $400. The Maximum feedrate of this machine is 30000mm per minute (F30000). Way over the limits of the GRBL Arduino solution which at 80 steps per mm, limits at about F22000 . Smoothieboards do not have such a low limit, but for some reason it processes gcode slower than GRBL. Now come GRBL-LPC which runs on smoothieboards is absolutely by far the fastest I have come across. Just yesterday I pushed a lineart logo at an impressive 30000mm per minute, Which is pushing the gantry and steppers to the limit.
As for the buffers, GRBL is pretty small, but that's a hardware limit. GRBL-LPC on smoothie is massive. 249 planner buffer and 8192 serial buffer. No problems with buffer underruns. Between the two buffers, it usually holds over 800 lines of gcode in its buffers. I know gcode isn't made to transfer bitmap images, but the GRBL-LPC and smoothieboard combo sure goes a long way to making it work.
The Marlin method of sending raster data in base64 encoded lines works well and in theory allows about 50 pixels to be sent in a 75 byte line, which could allow 7000+ pixels per second or a Feed of F40000+, but the Mega2560 runs out of steam processing the data that quickly and usually stutters at about F7000, not because of serial underruns.
It's a really tough one to get a solid solution for because that is no defined standard for raster data in gcode, so it's trying to make it work within the standard, like GRBL, or making something new, like Marlin. Both and Pros and Cons.
Thanks @arkypita & @mayhem2408 for useful information , I've tried to use your suggestion to improve the speed however as @arkypita truly stated "Sending a bitmap/raster image in G-Code syntax (which is designed for vector instructions) is a terrible waste of bytes", and I thinks this is bottleneck of engraving low speed, also as mentioned before I used modified version of Marlin for engraving , I checked the code again and noticed the G7
code merely developed for such purpose and with python extension in inkscape can reach very madly speed of engraving , I'm gonna open ticket for such feature request in GRBL communities
python function to create raster code
def generate_raster_gcode(self, curve, laserPower, altfeed=None):
...
code for G7 interpreter
#ifdef LASER_RASTER
case 7: //G7 Execute raster line
if (code_seen('L')) laser.raster_raw_length = int(code_value());
if (code_seen('$')) {
laser.raster_direction = (bool)code_value();
destination[Y_AXIS] = current_position[Y_AXIS] + (laser.raster_mm_per_pulse * laser.raster_aspect_ratio); // increment Y axis
}
if (code_seen('D')) laser.raster_num_pixels = base64_decode(laser.raster_data, &cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], laser.raster_raw_length);
if (!laser.raster_direction) {
destination[X_AXIS] = current_position[X_AXIS] - (laser.raster_mm_per_pulse * laser.raster_num_pixels);
if (laser.diagnostics) {
SERIAL_ECHO_START;
SERIAL_ECHOLN("Negative Raster Line");
}
} else {
destination[X_AXIS] = current_position[X_AXIS] + (laser.raster_mm_per_pulse * laser.raster_num_pixels);
if (laser.diagnostics) {
SERIAL_ECHO_START;
SERIAL_ECHOLN("Positive Raster Line");
}
}
laser.ppm = 1 / laser.raster_mm_per_pulse; //number of pulses per millimetre
laser.duration = (1000000 / ( feedrate / 60)) / laser.ppm; // (1 second in microseconds / (time to move 1mm in microseconds)) / (pulses per mm) = Duration of pulse, taking into account feedrate as speed and ppm
laser.mode = RASTER;
laser.status = LASER_ON;
laser.fired = RASTER;
prepare_move();
break;
#endif // LASER_RASTER
sample raster code by inkscape
`; Raster data will always precede vector data
; Default Cut Feedrate 300 mm per minute
; Default Move Feedrate 2000 mm per minute
; Default Laser Intensity 10 percent
G28 XY; home X and Y
M5 ;turn the laser off
;(_)
;(** Layer: 10 [ppm=30,feed=2500] ****)
;(** Laser Power: 10 ****)
;(** Feed Rate: 2500.0 ****)
;(** Pulse Rate: 30.0 ****)
;(_********)
;(MSG,Starting layer '10 [ppm=30,feed=2500]')
;Beginning of Raster Image image4556 pixel size: 753x750
M649 S10 B2 D0 R0.09406
G0 X11.518 Y15.927 F2500
G7 $1 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAMHCiA3Tl9xg42XoqOlp6CZkoZ5bFpINSQTAQEAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAhMkNUda
G7 L28 DbHmGkpmgp6WjopiNg3FfTjchCwcD
G7 $0 L68 DBQoQMVN1kKvG1eT09vn78efcybajiGxQNx0DAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQIDHTdRbIikt8rd59H89fb05NXGq5B2
G7 L56 DUzEQCgUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
G7 $1 L68 DAQMFFCQ0MzEwIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACRIcMERYcImitMbY4u339fv8
G7 L68 D9u9o287Br5yKdV9KOSkYEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAACBAYKTpKX3SJnK9Bztvn7vX899n37ePYxrSiiXFYRDAcEgkAAAAAAAAA
G7 L36 DAAAAAAAAAAAAAAAAAAAAECAwMjM0JRUFAwE=
G7 $0 L68 DAwcMK0tqZ2ViQSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEiU5W39iscHQ2eLr8fb79P39
G7 L68 D9vbz7ebg183EtKOTc1IyIRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAECExUnOTo7TEzdfg5u3z99r99fz79vDr4tnQwbGif1s5JRIAAAAAAAAA
G7 L36 DAAAAAAAAAAAAAAAAAAAAIUJiZGdqSioLBwM=
G7 $1 L68 DBQsRP29gnJiUYzIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDlWh7rt8vj9999999999999
G7 L68 D99999999999989fcrHtLMhkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
G7 L68 DAAAAAAAAAAAAGDJLe6zb6PP99999999999999999999999999PLsuodWORwAAAAAAAAA
G7 L36 DAAAAAAAAAAAAAAAAAAAAMWOTmJyfcUESCwUA
`
When I compare this to the included g-code for, say the wolf.gcode, I see something much more reasonable:
`G28 ; home all
M5
;(_)
;(** LAYER: 10 ****)
;(_**)
;(MSG,Starting layer '10')
G00 X3.299782 Y118.552030
T01 (select tool)
M6 (tool change)
M5
G00 X3.299782 Y118.552030 F1400
M3
G02 S10.00 X3.548178 Y118.501119 I0.000000 J-0.631423 F1400
G02 S10.00 X3.676074 Y118.391017 I-0.110031 J-0.257148 F1400
G03 S10.00 X3.805945 Y118.305855 I0.156134 J0.096495 F1400
G03 S10.00 X4.136655 Y118.324427 I0.119469 J0.826362 F1400
G03 S10.00 X4.290573 Y118.498593 I-0.052748 J0.201711 F1400
G03 S10.00 X4.208141 Y118.860798 I-0.527850 J0.070353 F1400
G02 S10.00 X3.894311 Y120.088890 I1.636677 J1.072386 F1400
G02 S10.00 X4.381019 Y121.026364 I1.354478 J-0.108126 F1400
G03 S10.00 X4.518115 Y121.254128 I-0.257294 J0.310012 F1400
G03 S10.00 X4.521857 Y121.701707 I-1.117987 J0.233151 F1400
G01 S10.00 X4.429717 Y122.183697 F1400
G01 S10.00 X4.895852 Y121.878273 F1400
G03 S10.00 X5.715594 Y121.570679 I1.094221 J1.670000 F1400
G03 S10.00 X5.907575 Y121.737854 I0.023203 J0.167175 F1400
G02 S10.00 X5.950319 Y121.885151 I0.275167 J0.000000 F1400
@mkeyno The G7 code used in the Marlin format is very effecent, but my experience with it has shown it is much more computationally intensive. The maximum feed I can get out of Marlin using G7s base64 is around F7000 before it starts to stutter, and it's not because of bandwidth. G7s base64 should be able to transfer just over 7000 pixels per second, which at 10 pixels per mm, can in theory hit a feed of over F40000. The other problem as far as GRBL is concerned, there is no room left in the Arduino Unos memory to add such a massive feature. It is something that may be added to the GRBL-Mega version as it has more room. I am currently looking at GRBL-LPC for smoothieboards to see if I can add a similar feature to it. For speed though, nothing beats GRBL-LPC. It has the speed and processing power to handle standard Gcodes at much higher feeds without having to implement G7. I just did a test using standard G1 code and set the resolution to 20 pixels per mm and dithered. Overkill for the size of the laser dot, but still managed to pull a smooth F10000.
Test 1: Dithered Output Resolution: 20 pixels per mm Maximum smooth Feed: F10000
Test 2: Dithered Output Resolution: 10 pixels per mm Maximum smooth Feed: F18000
Test 3: 256 Greyscale Output Resolution: 10 pixels per mm Maximum smooth Feed: F13000
Test 4: 64 Greyscale Output Resolution: 10 pixels per mm Maximum smooth Feed: F16000
Test 5: Lineart B&W Output Resolution: 20 pixels per mm Maximum smooth Feed: F30000 (Machines mechanical limit)
These tests clearly show that G1 style rastering is not the bottleneck and even G7 has it's limits on the microcontrollers. G7 on GRBL-LPC should be able to sustain smooth F30000 across the board. I know the community in general is not willing to go down the G7 path as it is not a standard, but I do like it and have been using it for years and even customised the firmware for Horizontal, vertical and 45 Degree Base64 engraving and personally want to see if I can get something similar in GRBL-LPC.
If grbl will implement a sort of raster command, same as merlin G7 or in a different syntax I will be the first who will implement in its GUI.
However I know that grbl on arduino UNO is pushed to the limit of available resources, so any implementation of new code/functions is a big deal.
I set the GRBL 1.1f and software 2.6.6 configuration as per following images , however engraving speed is not what I expected , I saw many CNC machine use high rate of reciprocating movement during the engraving job , but I haven't seen such movement for any of engraving attempt , any hint really appreciated