Help needed, color change macros
Hello, as far as i could understand (im new to python) the folloing code is where the color change comands go
elif command == COLOR_CHANGE: write_string_utf8(f, "M00\n")
now, if y want to add color change support for a modified muty needle machine, and i need to execute ceratain code for each one of the 9 needles available, how could i get the color we are changeing to ?
any help is greatly apreciated
Ed
Vpype has a solid solution to this a bit, since you can correctly define the routines. Here you might be better off editing the data directly. There is some work with regards to making a profile based corrected branch for gcode writing. Part of the issue here is that gcode especially hobbyist gcode can vary greatly from version to version. The gcode built in is based on one original hobbyist whose code didn't have color changes but rather paused the machine for them and rather than stitching per normal was hooked up to sew with the rotation of the wheel. Basically it was a hacked sewing machine with an XY plotter, and used the sewing machine wheel to drive the needle up and down. The result was that color changes would be done with M00 and stitches done with movement along the Z axis.
A few years after writing that I figured out the much better method of doing that. Specifically because there are so many more gcode users among plotting community and I had some of my work adapted there to help with vpype. Namely you can define a profile for the gcode and then using that profile define the different parts of the different commands.
The branch to do this generic-writer wasn't fully finished but I can check what my progress was since it seems like the easiest way forward for your project here. I opened pr #143 to go over it and evaluate what was done. I'll check, I think it was really close at the time. And it's the only way to properly capture all the different things in gcode that you might need or want to adjust.
Okay, I pushed the generic writer forward and fixed some of the other stuff. So now you can quickly make a duplicate pure code version of the gcode writer.
gcode_writer_dict = {
"scale": (-0.1, -0.1),
"pattern_start": "(STITCH_COUNT: {stitch_total})\n"
"(THREAD_COUNT: {color_change_count})\n"
"(EXTENTS_LEFT: {extents_left:.3f})\n"
"(EXTENTS_TOP: {extends_top:.3f})\n"
"(EXTENTS_RIGHT: {extends_right:.3f})\n"
"(EXTENTS_BOTTOM: {extends_bottom:.3f})\n"
"(EXTENTS_WIDTH: {extends_width:.3f})\n"
"(EXTENTS_HEIGHT: {extends_height:.3f})\n"
"(COMMAND_STITCH: {stitch_count})\n"
"(COMMAND_COLOR_CHANGE: {color_change_count})\n"
"(COMMAND_TRIM: {trim_count})\n"
"(COMMAND_STOP: {stop_count})\n"
"(COMMAND_END: {end_count})\n",
"metadata_entry": "({metadata_key}: {metadata_value})\n",
"thread_entry": "(Thread{thread_index}: {thread_color} {thread_description} {thread_brand} {thread_catalog_number})\n",
"stitch": "G00 X{x:.3f} Y{y:.3f}\nG00 Z{z:.1f}\n",
"color_change": "M00\n",
"stop": "M00\n",
"end": "M30\n",
}
EmbPattern.write_embroidery(
GenericWriter,
pattern,
"myfile.gcode",
gcode_writer_dict,
)
This doesn't go into details with all the features but if you need to change color change which is M00\n there you can do that and it'll write that out. This formatting scheme has been used to create all manner of gcode, and formats as distinct as svg to json and various rare ascii-like formats.
I focused on purely getting it to work so if you have need for some more specifics with the gcode I could certainly help with that. The "stitch" format uses G00 which is isn't typical but it was doing the sewing with the Z value. If you need that to be G01, or any other conversions that's fairly easily doable. There's hooks for jump as well which would properly go G01.
It's new and there's basically no documentation, yet, so if you have some additional questions kindly do ask.
The core part works like another project I did that sort of used the same scheme: https://github.com/plottertools/vpype-gcode/
Parameters that it accepts are:
self.metadata_entry = settings.get("metadata_entry", None)
self.thread_entry = settings.get("thread_entry", None)
self.pattern_start = settings.get("pattern_start", None)
self.pattern_end = settings.get("pattern_end", None)
self.document_start = settings.get("document_start", None)
self.document_end = settings.get("document_end", None)
self.color_start = settings.get("color_start", None)
self.color_end = settings.get("color_end", None)
self.color_join = settings.get("color_join", None)
self.block_start = settings.get("block_start", None)
self.block_end = settings.get("block_end", None)
self.block_join = settings.get("block_join", None)
self.segment_start = settings.get("segment_start", None)
self.segment = settings.get("segment", None)
self.segment_end = settings.get("segment_end", None)
self.segment_join = settings.get("segment_join", None)
self.stitch_first = settings.get("stitch_first", None)
self.stitch_last = settings.get("stitch_last", None)
self.stitch = settings.get("stitch", None)
self.stop = settings.get("stop", None)
self.jump = settings.get("jump", None)
self.trim = settings.get("trim", None)
self.needle_set = settings.get("needle_set", None)
self.color_change = settings.get("color_change", None)
self.sequin = settings.get("sequin", None)
self.sequin_mode = settings.get("sequin_mode", None)
self.slow = settings.get("slow", None)
self.fast = settings.get("fast", None)
self.end = settings.get("end", None)
The main blocks are pattern, document, color, block. These all have start, end, and join values. Segments refer to all stitches regardless of types. Stitch are specific to stitches, stop, jump, trim, needle_set, color_change, sequin, sequin_mode, slow, fast, and end commands all also exist and are specific to just those commands.
Pattern refers to the entire pattern. Document is just from the first stitch entry to the next end value. Color refers to color change'd blocks of commands. Block refers to clumps of uninterrupted stitches. The formatting here gives some examples of different properties but there's a lot of other values that aren't referenced but could be. For example thread entries will notably allow you to output all the thread metadata index color description brand catalog_number chart details weight all of these are prefixed with thread_ so if you wanted to just list the thread description and color. "thread_entry": "{thread_description}, {thread_color}" would let you format that output.
Relevant to your original question. If you have this setup and you want to say issue an M6 toolchange you would replace the color_change code with: "color_change": "M06 T{cmd_needle}\n", this gives the M06 command and the command's needle value which isn't common issued through other means. As I assume whatever needle device you have will use and reuse these needles with whatever sort of gcode head you have for it.
Do note I just updated pyembroidery to bring this functionality to you, so you'll need to do pip install -U pyembroidery to use that.
@tatarize First of all i want to thank you for the quick response to my request, being new to python, im in the process of digesting all this new information,
regarding: Relevant to your original question. If you have this setup and you want to say issue an M6 toolchange you would replace the color_change code with: "color_change": "M06 T{cmd_needle}\n", this gives the M06 command and the command's needle value which isn't common issued through other means. As I assume whatever needle device you have will use and reuse these needles with whatever sort of gcode head you have for it.
i could use:
if {cmd_needle]=1: "G0 A100 \n" elseif {cmd_needle}=2: "G0 A200 \n"
and so on for the 9 needles available ?
the "G0 AXX" command is to position the acive needle using axis "A"
am i correct ?
Thanks Ed
hello
also according to:
Rapid Overrides
Immediately alters the rapid override value. An active rapid motion is altered within tens of milliseconds. Only effects rapid motions, which include G0, G28, and G30. If rapid override value does not change, the command is ignored. Rapid override set values may be changed in config.h. The commands are: 0x95 : Set to 100% full rapid rate. 0x96 : Set to 50% of rapid rate. 0x97 : Set to 25% of rapid rate.
we could use the set to 100% for stitch fast, and set to 25% for stitch slow this woudl mimic the original machines
Ed
@tatarize BTW what country/timezone are you from? im living in Guadalajara Mx, central time
GMT-8. About the same time zone but weird sleep schedule.
You'd want your color change command to reference the cmd_needle value:
"color_change": "G0 A{cmd_needle}00\n",
So altogether we'd be looking at code like:
gcode_writer_dict = {
"scale": (-0.1, -0.1),
"stitch": "G00 X{x:.3f} Y{y:.3f}\nG00 Z{z:.1f}\n",
"color_change": "G0 A{cmd_needle}00\n",
"slow": "S500\n"
"fast": "S1500\n"
"stop": "M00\n",
"end": "M30\n",
}
EmbPattern.write_embroidery(
GenericWriter,
pattern,
"myfile.gcode",
gcode_writer_dict,
)
As an example. Assuming the stitch code was right. I added in commands for slow and fast these commands are in the pyembroidery standard as standard commands but most files will not possess them. But, if we're writing gcode then it's entirely possible and plausible to add in those commands, these are standard for .u01 type files on a Barudan machine but if you're using gcode you can actually directly set the speed at which things move. Assuming you have some kind of stitching mechanism it should work fine for that.
The code here should be able to write whatever you need. The A100 for needle 1 and A200 for needle doesn't quite let needle 2 be called needle 200 but you can just add the 00 after the {cmd_needle} there. Also, this setup assumes you begin with needle 1. If that's not the case and you have a different config and you need it to give the needle command at the start of the file which is entirely possible. You'd need to switch away from color_change operations and use needle_set operations.
You'd do this with an extra setting being sent to the writer for thread_change_command=NEEDLE_SET the difference here is that needle sets (though rarer than color change). Occur before a color block to indicate the set needle. In theory most machines start at the correct needle and tend to just stop or sometimes have preset needle code values to go to the next element. The exception to this is again .u01 format by Barudan which sets gives the needle to set as part of the file itself.
Most of this stuff depends on how the gcode controller is controlling the embroidery machine. Which is actually why it needs something like generic writer. The main reason is that there can be any arrangement of hobbyist machines and to cover them all requires something so general and generic that it can write out most different formats.
For example the following code:
pattern = EmbPattern()
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
pattern.add_command(SLOW)
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "blue")
pattern.add_command(FAST)
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
gcode_writer_dict = {
"scale": (0.1, -0.1),
"thread_change_command": NEEDLE_SET,
"write_speeds": True,
"pattern_start": "G21 G90 F6000 (mm units, absolute positioning, speed)\n",
"thread_entry": "(Thread{thread_index}: {thread_color} {thread_description} {thread_brand} {thread_catalog_number})\n",
"block_start": "G00 X{x:.3f} Y{y:.3f} (Starting new location)\n",
"stitch": "G01 X{x:.3f} Y{y:.3f}\n",
"slow": "F1000\n",
"fast": "F6000\n",
"needle_set": "G00 A{cmd_needle}00 (Changing to color: {cmd_thread})\n",
"end": "M30\n",
}
file = "file-generic.gcode"
EmbPattern.write_embroidery(
GenericWriter,
pattern,
file,
gcode_writer_dict,
)
Produces this gcode:
G21 G90 F6000 (mm units, absolute positioning, speed)
(Thread0: #ff0000 None None None)
(Thread1: #0000ff None None None)
(Thread2: #008000 None None None)
G00 A100 (Changing to color: 0)
G00 X0.000 Y0.000 (Starting new location)
G01 X0.000 Y0.000
G01 X0.000 Y-10.000
G01 X10.000 Y-10.000
G01 X10.000 Y0.000
G01 X0.000 Y0.000
G00 A200 (Changing to color: 1)
F1000
G01 X0.000 Y0.000
G01 X0.000 Y-10.000
G01 X10.000 Y-10.000
G01 X10.000 Y0.000
G01 X0.000 Y0.000
G00 A300 (Changing to color: 2)
F6000
G01 X0.000 Y0.000
G01 X0.000 Y-10.000
G01 X10.000 Y-10.000
G01 X10.000 Y0.000
G01 X0.000 Y0.000
M30
Basically if you need it to write the gcode for you that's quite able to be sorted out. You just need to know the exact sort of things you specifically need in the gcode. If you tell me what that might be, I could likely tell you if it requires something that the program can't do (I would then likely update it). But generally whatever sort of thing you need it should be able to to do that.
You could send the rapid speed change commands and they would, in theory work, but I think those are for GRBL and they tend to be realtime commands. Which means regardless when you sent them they take effect immediately. You might more correctly and properly want F commands which should set the feed rate which is the speed in some setups.
Once you pin down the formatting right, I could certainly advise you on how to make the system output that format. But, it sounds like what you're doing is replacing a busted and not-easy-to-replace (or costs as much as a house) controller card for a particular embroidery machine, and it might be easier to get an off the shelf GRBL device and a raspberry pi, then you could just and send the embroidery files having them convert to grbl and control the device. It might be hard to do things like thread break detection, since I don't know how that works etc (but there are a couple triggers for emergency stop on many gcode controller cards), but it all sounds doable.
I'm quite happy to make sure you can convert whatever format into whatever form of gcode you end up with. Since that's well within the scope of this project. Though stuff like remi (python remote interface) and pyserial (send data to across the serial for the grbl directly) would be nice for such a project might be beyond the scope there. But, I'll make sure you can do the conversion to your format of gcode from typical embroidery formats.
hello,
regarding the gcode output: G21 G90 F6000 (mm units, absolute positioning, speed) (Thread0: #ff0000 None None None) (Thread1: #0000ff None None None) (Thread2: #008000 None None None) G00 A100 (Changing to color: 0) G00 X0.000 Y0.000 (Starting new location) G01 X0.000 Y0.000 G01 X0.000 Y-10.000 G01 X10.000 Y-10.000 G01 X10.000 Y0.000 G01 X0.000 Y0.000
G00 A200 (Changing to color: 1) HERE THE 1 BEFORE THE 00 IS THE NEEDLE NUMBER
the problem is i need to insert certain commands depending on the nedle number like for needle 0 i could send: G0A51 //move needle positioner to needle 0 coordenates G0B8 //engage neddle clutch M25 0x0 turn on needle 0 light
or can any other block of code
i need to be able to define different code blocks for each needle
as per the real time feed overrides this is ok since im using GRBL this would mimick the slowdown of the machine
Thanks for the help
Ed
would it be possible to insert code blocks based on the needle number we are changeing to?
this would alow to: make this universal for any gcode controlled machine turn on light or buzzer to alert use a color change is needed disengage needle clutch if needed set needle changer position engage neddle clutch if needed resume stitching
i king of thing of this genericwriter as a cnc post procesor file i will be more than happy to provide the needed explanation on how a cnc postprocesor works and what parameters an embroidery postprocessor would ever need, it will be lots more than what i ever need but it will be universal for anyone building a machine to be able to get a custom gcode output
as i will be using stepper axis to control needle change, but someone might be using a servo or other means
this way it will be more like a universalgcodewriter, or a emb.gcode.postprocessor
i would be more than happy to help finishing a fully featured postprocessor :)
Ed
Hello something happen, now im not getting any output on mi gcod file ed
@tatarize can you please help me get my otput back :(
Thanks
Any indication of what was done differently. There's likely a minor error and I'd need to see the code to diagnose it.
Specific code sections based on the needle selected isn't properly achievable you could write or use a gcode post-processor. And while that is out of the realm of the project all you're doing is basically writing anything you want for the needle switch and then changing the needle based on that. So if you set the needle code to write Needle2\n you'd just line by line check the resulting gcode and do a match and replace within the text. It's not that difficult, but there's not context specific gcode switching based on the specific needle number. There might, however, be an easy enough way to do that in the code.
https://www.delftstack.com/howto/python/python-replace-line-in-file/ for example covers that sort of basic scripting process.
Sorry for the delay on the reply. I'll look into giving you methods of specific needle sets values to gcode. That sounds like a reasonable enough request.
I added 1.4.35. It's now possible to rewrite some segment code like that:
def test_generic_write_gcode_multi(self):
pattern = EmbPattern()
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
pattern.add_command(SLOW)
pattern.add_block([(5, 5), (0, 100), (100, 100), (100, 0), (5, 5)], "blue")
pattern.add_command(FAST)
pattern.add_block([(10, 10), (0, 100), (100, 100), (100, 0), (10, 10)], "green")
gcode_writer_dict = {
"scale": (0.1, -0.1),
"thread_change_command": NEEDLE_SET,
"write_speeds": True,
"pattern_start": "G21 G90 F6000 (mm units, absolute positioning, speed)\n",
"thread_entry": "(Thread{thread_index}: {thread_color} {thread_description} {thread_brand} {thread_catalog_number})\n",
"color_start": "G00 X{x:.3f} Y{y:.3f} (Starting new location)\n",
"stitch": "G01 X{x:.3f} Y{y:.3f}\n",
"slow": "F1000\n",
"fast": "F6000\n",
"needle_set": {None: ("{cmd_needle}", "default value {cmd_needle}\n"), "1": "G0A51\n", "2": "G0B8\n"},
"end": "M30\n",
}
file = "file-generic.gcode"
EmbPattern.write_embroidery(
GenericWriter,
pattern,
file,
gcode_writer_dict,
)
The needle_set command shows the general format. Basically the None value of the dict is to be a tuple of key, and default. The rest of the dictionary calls the main dictionary entries which either exist or get replaced with the dictionary. For example running that code results in:
G21 G90 F6000 (mm units, absolute positioning, speed)
(Thread0: #ff0000 None None None)
(Thread1: #0000ff None None None)
(Thread2: #008000 None None None)
G00 X0.000 Y0.000 (Starting new location)
G0A51
G01 X0.000 Y0.000
G01 X0.000 Y-10.000
G01 X10.000 Y-10.000
G01 X10.000 Y0.000
G01 X0.000 Y0.000
G0B8
F1000
G01 X0.500 Y-0.500
G01 X0.000 Y-10.000
G01 X10.000 Y-10.000
G01 X10.000 Y0.000
G01 X0.500 Y-0.500
default value 3
F6000
G01 X1.000 Y-1.000
G01 X0.000 Y-10.000
G01 X10.000 Y-10.000
G01 X10.000 Y0.000
G01 X1.000 Y-1.000
M30
Any indication of what was done differently. There's likely a minor error and I'd need to see the code to diagnose it.
im running same code as wen i started
import pyembroidery import sys infile=str(sys.argv[1])+".DST" outfile=str(sys.argv[2])+".gcode" pyembroidery.convert (infile, outfile)
i do get a file output but no code just like
STITCH_COUNT: 1) (THREAD_COUNT: 0) (EXTENTS_LEFT: 0.000) (EXTENTS_TOP: 0.000) (EXTENTS_RIGHT: 0.000) (EXTENTS_BOTTOM: 0.000) (EXTENTS_WIDTH: 0.000) (EXTENTS_HEIGHT: 0.000) (COMMAND_END: 1) M30
thanks
You need to put it in the backticks to keep the tabs. In Python the tabbing is quite essential to the the code.
The output there says there is no code. That the extends go only to 0 and the only command in the pattern you gave it was "END".
The issue isn't the code it's apparently the DST. If you zip it up and include it here I could test it directly but I think you might have deleted the dst contents at some point.
You need to put it in the backticks to keep the tabs. In Python the tabbing is quite essential to the the code.
The output there says there is no code. That the extends go only to 0 and the only command in the pattern you gave it was "END".
The issue isn't the code it's apparently the DST. If you zip it up and include it here I could test it directly but I think you might have deleted the dst contents at some point. files.zip
attached the files im testing with and the output i get
Thanks
Worked fine.
python DST2GC.py comis myoutput
You might be adding the dst of the filename into the script code which is causing it to not find the file and thus an empty file.
Try this script:
import pyembroidery
import sys
pyembroidery.convert(sys.argv[1], f"{sys.argv[1]}.gcode")
It's a bit more simplistic but it'll be pretty easy. You call it on any file or even drag and drop a file on it as a script and it'll do the conversion pretty easy for you. It just appends .gcode to the output file which isn't an issue to do .dst.gcode and it makes it really clear what file that started with.
Using the latest version. Note I just pushed a newer version to make sure this would work correctly.
from pyembroidery import *
import sys
gcode_writer_dict = {
# This is the scaling from 1/10MM to MM which is gcode standard. Flipping Y-axis.
"scale": (0.1, -0.1),
# We are using the needle change rather than color change command.
"thread_change_command": NEEDLE_SET,
# This tells it to write speed changes rather than strip them this is typically only a
# Thing within U01 file formats but gcodes can write speed changes with the F command.
"write_speeds": True,
# Default commands at the start of the pattern.
"pattern_start": "G21 G90 F6000 (mm units, absolute positioning, speed)\n",
# This writes thread info, using () brackets to make them GCODE comments.
"thread_entry": "(Thread{thread_index}: {thread_color} {thread_description} {thread_brand} {thread_catalog_number})\n",
# This occurs when a new color is started. block_start could also be use for intercolor location changes
"color_start": "G00 X{x:.3f} Y{y:.3f} (Starting new location)\n",
# Default stitch command.
"stitch": "G01 X{x:.3f} Y{y:.3f}\n",
# Example of slow command sets the feed rate to 1000
"slow": "F1000\n",
# Example for fast command this is 6x the slow speed. Note this is an example batch of code
"fast": "F6000\n",
# Needle set with optional dynamic values.
"needle_set": {
# None, given a tuple of key creation value and a default value (if no key matches)
None: ("{cmd_needle}", "default value {cmd_needle}\n"),
# Overrides cmd_needle==1 value.
"1": "G0A51\n",
# Overrides cmd_needle==2 value.
"2": "G0B8\n",
},
# Called at the end of the gcode.
"end": "M30\n",
}
# This section performs the actual writing with the above dictionary.
EmbPattern.write_embroidery(
GenericWriter,
EmbPattern(sys.argv[1]),
f"{sys.argv[1]}.gcode",
gcode_writer_dict,
)
I added a bunch of python comments to explain each section and what it was doing to make it more adaptable.
Here's tog.py as a script (to-g as in gcode) .
python tog.py comis.DST works.
I formatted everything out nicely and tried to make sure it had comments and explained what it should be doing.
Your job is likely not messing with the python that much but getting all the regular parts to work well with grbl code.
EXCELENT!!!!!!!!!! will go play with it now, ill let you know how it went
Thanks Edward
@tatarize , from command line i still get blank output, but dropping a dst on the py file works great!!!! just one litle thing to add we are missing the z value in mm to complete 1 stitch and the actual z output to do the stitching
if it isnt much to ask, can you please add also the tread cut commnads section so i can energize the tread cut solenoids (since im converting a tajima machine to gcode controller
thanks
Edward
Hello, i have tryed this line
# Default stitch command.
"stitch": "G01 X{x:.3f} Y{y:.3f} Z{Z%.1f}\n",
but did not work
Ed
"stitch": "G01 X{x:.3f} Y{y:.3f} Z{z:.1f}\n",
Note the {} brackets are formatting strings values so you need z which is lower rather than upper case and you need the color : the section there is Z{z:.1f} which is Z as a string value then in the formatting brackets it does the variable z (note case matters) and the formatting which is .1f which means float point with one value of decimal. It seems like the 3 issues (case, lack of color and extraneous %) could have been copy and pasted.
The Z value depends on the type of system you have setup. In some hobby setups it does the wheel turning since it's hooked to a sewing machine wheel. In your case I do not know what you use to trigger the needle down, and I did not assume.
The Z value depends on the type of system you have setup. In some hobby setups it does the wheel turning since it's hooked to a sewing machine wheel. In your case I do not know what you use to trigger the needle down, and I did not assume.
Hello, thanks again, im still trying to understand phyton,
yes, th z value is the number of mm needed to advance z axis to turn the wheel 1 full turn,
if we could have a setting within the tog.py like :
use Z for stitch= YES, NO Stitch Z Value=12
if use Z for stitch =NO then: stitch commands=" whatever code needed"
else: do not output Z values or stitch commands
please note we would need the Z axis or stitch commands to be on a separate line from the XY moves this to guarant that the move has been completed before we stitch
Thanks again Ed
So would movement commands have Z0 and stitch commands use Z12? I'm thinking Z is needle position so you want to indicate position and say Z12 to change needle position down and Z0 to get it back up again before moving?
You'd do your stitches:
"stitch": "G01 X{x:.3f} Y{y:.3f}\nZ12\nZ0\n",
That's three lines go to position, needle down, needle up. Writing it is easy if the right commands are sorted out. There are some formats where the order matters, but I think default is "move then stitch" but some commands in some formats mean "stitch then move", but I think this should be correctly sorted for you in pyembroidery.
In this case each stitch you are adjusting then counter adjusting the z level.
Great, this works for incremental seretings
"stitch": "G01 X{x:.3f} Y{y:.3f}\nG91\nZ150\nG90\n",
this is my output: G01 X-36.800 Y-32.100 G91 Z150 G90 G01 X-36.500 Y-32.500 G91 Z150 G90 G01 X-36.200 Y-33.000 how about for users requiring absolute coordinates (and avoid some communication overhead)
is there a way to have Z increment a set value for each stitch like in the original file where:
if command == STITCH: write_string_utf8(f, "G00 X%.3f Y%.3f\nG00 Z%.1f\n" % (x, y, z)) z += increment_value
mabe leave a option to alow both cases for diferent setups ?
thanks
Ed