11. Open Source Hardware - From Fibers to Fabric
→ Inspirations
- 1 Studio Jibbe / woven translations
- 2 Studio Jibbe / Endless etching
- 3 Soft Connection Lab
- 4 Nodus Project7
- 5 Amandine David
- 6 Laend / Chevalier Masson x Diane Steverlynck
→ Websites - https://en.wikipedia.org/wiki/List_of_Traditional_Crafts_of_Japan - https://kirikomade.com/pages/kasuri?srsltid=AfmBOoo4xkGlYqsxLi0X4GqLt6J_JA6lLzrXiGiUh_zpOyz3ambpFphC - https://english.inagakikiryou.com/s_egasuri.html - https://kurumekasuri.jp/en/about/
Kasuri / Ikat machine !
"Kasuri (絣) is the Japanese term for fabric that has been woven with fibers dyed specifically to create patterns and images in the fabric, typically referring to fabrics produced within Japan using this technique. It is a form of ikat dyeing, traditionally resulting in patterns characterized by their blurred or brushed appearance." → Wikipédia
more about ikat technique → here
kasuris picked frome this website
Ikat techniques, such as Kasuri, are traditional crafts that have not been translated into industrial processes. I did not find a machine that could accelerate the process. So, with Sophia and Stephanie, we tried to develop a machine that can print directly onto the yarn, a pattern that we can then knit afterward.
Steps
There are 4 main parts to creating this machine
-
1 Understanding the knit, length of each stitch / each row & what affects the stitch lenght, e.g., first row vs other rows, side stitches vs middle stitches, tension, etc.
-
2 Considering the dyeing device We chose to use a permanent marker because thats what we had and we didn't have the time to consider our own dyes or shop for something else
-
3 Passing the fiber through the dyeing device Again we used what we had, a yarn winder, for the next step I think it would be great to build our own winder to improve the precision of the speed
-
4 Moving the dyer For this we used a 3D printer and python code generated from an image
1 Understanding the knit
/Normally, the Kasuri technique is developed for weaving, but the fact is that if we do it the traditional way, it won't work for knitting because the loop of a stitch directly modifies the shape of the pattern./
→ Knit a blank sample of jersey [40needles/40 rows - 5 stitch lenght] :
• Mark with a pen the first stitch of the cast on
• I did a double e wrap cast on
• Mark the last row before the cast off
→ Re-knit your sample with a pattern on it
• Draw a simple form pattern on your knitting and try to inked both sides
• Unravel it and make a new bobine
• start a new knitting and be carefull to ensure that the first stitch on your cast on is on your previous mark
As you can see the pattern moved a lot, I'm thinking about making a new one but marking the first loop after the cast on. ↓↓↓
I put two marks on each side of the machine bed, to be able to stop the carrier at a same position for every rows.
Then, as I marked the last stitch of my previous cast on, I had to do a reverse cast on, that starts from the stitched marked.
By starting after de cast on, I could be able to see the first pattern but it seems that it's off by 20 stitchs.
2 Considering the Dye
Currently we are using a big felt tip permanent marker because this is what we have and it dyes the fiber quite well. However' we noticed that it only dyed one side of the fiber (the part that it touches)
Upsides:
- Permanent Marking
- Doesn't drip like other dye might drip
- Dye doesn't dry out on pen
- Easily available
Downsides:
- Only marks one side of the fabric
- Doesn't dry fast (and thus marks the white fiber when wound)
We would like to improve on this by using a different type of marker or dyeing device and we would like to make it double sided like below in order to mark both sides of the fiber
3 Passing the Fiber Through the Dyer
To add more detail
Moving the Dyeing Device
For this we decided to use our Prusa 3D printer because it already has the functionality of reading code and moving in the Z direction quickly and with accuracy.
For now we added the marker (dyeing device) to the 3D printer using tape, but for the next iteration after we choose the ideal dyeing device, it would be great to 3D print a holder.
To communicate with the 3D printer we wrote a GCode using Python.
4 G Code
Python Code OutPut = GCode
Prusa has a great overview of G-Code here
Important functions in GCode:
- G0 = initialize position
- G1 = movement
- G2, G3 = arc movements
- G4 = pause machine (Dwell)
- Pause the machine for a period of time.
- G4 [ P | S ]
- Parameters
- P:Time to wait, in milliseconds
- S: Time to wait, in seconds
- G10 - Retract G10: Retract
- G20 / G21 = unit selection (21 = mm, 20 = inches)
- G91 - Switch on relative mode i.e., Relative Positioning
- All coordinates from now on are relative to the last position. E axis is left intact. -e.g., Z10 means move up 10 not move to coordinate Z10
- G90 - Switch off relative mode G90: Set to Absolute Positioning
- e.g., Z10 means move to coordinate Z10, this could be move 0 if already at 10
- Parameter F (for G code) = The feedrate per minute of the move between the starting point and ending point (if supplied)
We started with this code to test
G21 F100 ; This says set units to mm and sets the speed/feedrate to 100 mm/minute
G90 ; absolute mode in case we want to test
G91 ; relative mode.
G1 X0 Y0 Z-10 ; move down 10mm (towards plate)
G4 S2 ; wait 2 seconds
G1 X0 Y0 Z10 ; move back up 10mm
G4 S2 ; wait 2 seconds
G1 X0 Y0 Z-5 ; move down 5mm (towards plate)
G4 S5 ; wait 5 seconds
G1 X0 Y0 Z5 ; go back up 5mm
G4 S5 ; wait 5 seconds
Python Code
Inputs
- Number of Stitches per Row
- Distance to move in Z Direction: We chose between 2 at first, but may want to experiment with 3 or 4
- Number of milliseconds per stitch in other rows (measured by testing the yarn winder with a specified amount of yarn)
- Number of milliseconds per stitch in first chain row (can multiply after testing the length difference between chain row and other rows)
- Image Info
For the Image Info we have two options:
Photo Option 1
- Input an Image into and RGB converter
Another next step is to use the pillow library to do this directly in Python, but for now we're using this website
This takes this image, a 10 x 10 pixel test image I made, and turns into this data. A list of each pixel as a list of RGB information
[[0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0]]
If using
After we have the image info and all the inputs above we need to convert it into a more easily understandable format. We did this in 2 steps.
Convert into BW Data
We convert the list above into a table with the dimensions number of stitches by number of rows and convert the rgb data into a value of 1 or 0. Currently I'm doing this by just taking the first value of the RGB data and if it higher than 255/2 it is 1 and if it is lower than 255/2 it is 0. 1 will be white and 0 will be black. I'm doing this this way because it's a black and white image so the values above are always either (0,0,0)(black) or (255, 255, 255)(white).
So by using the following code:
bwArray=[] #bW array returns 0 for black, 1 for white, in an array of x rows with each row containing y stitches
n=0
while n < len(imageArray):
i=0
stitchArray=[]
while i < numStitches:
if(n>=len(imageArray)):
i=numStitches # to break the loop if there is an uneven number of pixels for some reason
elif int(imageArray[n][0]) <= blackMax: #should change this later to average of all so I can convert rgb to grayscale, for now just going to use bw images
stitchArray.append(0) # 0 = black bc 000
else:
stitchArray.append(1)
i+=1
n+=1
bwArray.append(stitchArray)
print("Array of BW points, row x stitch")
print(bwArray)
We get the following output:
Array of BW points, row x stitch
[[0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 1, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 1, 1, 0, 0], [1, 1, 0, 0, 1, 1, 0, 0, 1, 1], [1, 1, 0, 0, 1, 1, 0, 0, 1, 1], [0, 0, 1, 1, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 1, 1, 0, 0]]
You can see that if its reformatted like below it will ressemble the initial photo:
[[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
[1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
[1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
[0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0, 1, 1, 0, 0]]
Snake list around like yarn
Then I changed the table again to a list (it's been a long time since I coded, so maybe this can be made more efficient) that snakes around like the yarn will snake around
For example, if we have a list like this:
[[1,2,3], [4,5,6], [7,8,9], [10,11,12]]
We want it to snake around like this (because thats what the yarn will do):
[1, 2, 3, 6, 5, 4, 7, 8, 9, 12, 11, 10]
So in the code we do this like this:
#Turn array into list
l=0
index=0
bwListLoop=[] #bW list loop takes bwArray and turns it into a single list that snakes around so that we can easily reference the previous stitch
while l< len(bwArray):
if l % 2 ==0: # even rows go front to back
for i in range(0, len(bwArray[0]), 1):
bwListLoop.append(bwArray[l][i])
else: # odd rows go back to front
for i in range((len(bwArray[0])-1), -1, -1):
bwListLoop.append(bwArray[l][i])
l+=1
print("List of points in snake pattern")
print(bwListLoop)
Which changes the table into this:
List of points in snake pattern
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]
Note that the stitches are no longer grouped by rows. This now indicates just the pattern that will be shown on the yarn.
Photo Option 2
- Create a "drawing" using code:
For example, for our test, we wanted to do one row of stitches with color and the next without color for a simple test to see how its restitched.
This can be done like this:
bwListLoop=[]
row0=0
stitch0=0
while row0 < 10: #manually input how many rows
stitch0=0
while stitch0< numStitches:
if row0 % 2 ==0:
bwListLoop.append(1) #white = 1
else:
bwListLoop.append(0) #black = 0
stitch0+=1
row0+=1
print(bwListLoop)
Output
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Now we can move onto the G-Code!
We start with the initial settings
gCode='G21 F100\nG91 ; relative mode\n'
Then we run through the list of stitch colors.
We initialize for the first stitch, moving down if black or staying still if white.
Then for every stitch thereafter: - if the stitch is the same color as the previous stitch: we add time to the rest time - if the stitch is a different color, we finalize the rest time and add it to the code and we add a movement to the G code, up if white, down if black
So we write the GCode with the following code:
# Change to G Code!
#Add G Code inputs here
t=0 #totaltime
moveZblack='G1 X0 Y0 Z-'+str(zDistance)+'\n' #can define now because zDistance doesnt change
moveZwhite='G1 X0 Y0 Z'+str(zDistance)+'\n'
row=0
stitch=0
t=numSecondsFirstRow #time per move
#initialize --> if black go down, else stay up
if bwListLoop[0] == 0:
gCode+=moveZblack
stitch=1 #we already initialized [0][1]
while stitch < len(bwListLoop):
if stitch < numStitches: #i.e., in first row
timePerStitch=numSecondsFirstRow
else:
timePerStitch=numSecondsOtherRow #add side stitch time later if its different
if (stitch+1) % numStitches ==0: # i.e., if side stitch
timePerStitch+=addSecondsSideStitch
if bwListLoop[stitch] == bwListLoop[stitch-1]: # stitch = same color as last stitch, no movement, add time
t+=timePerStitch
else: # stitch color changes, finalize time for last section of colors, reset time and add a move
gCode+='G4 P'+str(t)+'\n' #adds time in milliseconds
t=timePerStitch #reset time to time of 1 stitch
if bwListLoop[stitch]==0: #change this once i look at photo data
gCode+=moveZblack
else:
gCode+=moveZwhite
stitch+=1
print(gCode)
Python Code Output
And the output (for the picture converted in the RGB converter) is
G21 F100
G91 ; relative mode
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P71
G1 X0 Y0 Z4
G4 P71
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P284
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P284
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P284
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
G4 P142
G1 X0 Y0 Z4
G4 P142
G1 X0 Y0 Z-4
Now we can copy this into a window, save as gcode and run it.
You can find all the Python code compiled (including inputs) below.
Current Python Code Limitations
Currently the image and the numStitches input need to match. If not, it will result in an error. Next step would be to make the code be able to change the image to the correct number of stitches. For example, if we have a 10 x 10 pixel image, it's necessary to input 10 stitches per row, but ideally if we input 40 stitches, it should be able to extrapolate the image to be 40 x 40 stitches with 1 pixel of information repeated for each 4x4 square
Python Code Complete
#Other Considerations: should white time be different than black time because of time for movement of 3D printer?
# add indication before we start - this should be done by hand? to indicate knot / starting point & to indicate end of first row?
#INPUTS
#numStitches = 10 #input stitch number
numStitches = int(input("Enter number of stitches per row: "))
print(numStitches)
#Definitions RGB --> BW
#<=127 = black, >=128 = white
blackMax=127
whiteMin=128
#Gcode inputs
zDistance = 2 #absolute z distance up / down
#Time below is calculated by testing the roller and seeing how long the roller pulls one row length of yarn.
# E.g., 1 row for us was 47.5 cm, we measured that the roller wound 47.5 cm on average every 2.84 seconds, so we convert 2.84 seconds to milliseconds and divide by 40
# the follow are number of seconds per STITCH not per row, but changes depending on if its first row or other row
numSecondsFirstRow = 71 #actually milliseconds but not changing name
numSecondsOtherRow = 71
addSecondsSideStitch = 0 #additional seconds added for side stitch
#numStitches already defined
gCode='G21 F100\nG91 ; relative mode\n'
#Copy image string from https://onlinepngtools.com/convert-png-to-rgb-values
#INPUT IMAGE
imageArray=[[0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [255, 255, 255], [0, 0, 0], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0], [255, 255, 255], [255, 255, 255], [0, 0, 0], [0, 0, 0]]
bwArray=[] #bW array returns 0 for black, 1 for white, in an array of x rows with each row containing y stitches
n=0
while n < len(imageArray):
i=0
stitchArray=[]
while i < numStitches:
if(n>=len(imageArray)):
i=numStitches # to break the loop if there is an uneven number of pixels for some reason
elif int(imageArray[n][0]) <= blackMax: #should change this later to average of all so I can convert rgb to grayscale, for now just going to use bw images
stitchArray.append(0) # 0 = black bc 000
else:
stitchArray.append(1)
i+=1
n+=1
bwArray.append(stitchArray)
print("Array of BW points, row x stitch")
print(bwArray)
#Turn array into list
l=0
index=0
bwListLoop=[] #bW list loop takes bwArray and turns it into a single list that snakes around so that we can easily reference the previous stitch
while l< len(bwArray):
if l % 2 ==0: #even rows go front to back
for i in range(0, len(bwArray[0]), 1):
bwListLoop.append(bwArray[l][i])
else: #odd rows go back to front
for i in range((len(bwArray[0])-1), -1, -1):
bwListLoop.append(bwArray[l][i])
l+=1
print("List of points in snake pattern")
print(bwListLoop)
# Change to G Code!
#Add G Code inputs here
t=0 #totaltime
moveZblack='G1 X0 Y0 Z-'+str(zDistance)+'\n' #can define now because zDistance doesnt change
moveZwhite='G1 X0 Y0 Z'+str(zDistance)+'\n'
row=0
stitch=0
t=numSecondsFirstRow #time per move
#initialize --> if black go down, else stay up
if bwListLoop[0] == 0:
gCode+=moveZblack
stitch=1 #we already initialized [0][1]
while stitch < len(bwListLoop):
if stitch < numStitches: #i.e., in first row
timePerStitch=numSecondsFirstRow
else:
timePerStitch=numSecondsOtherRow #add side stitch time later if its different
if (stitch+1) % numStitches ==0: # i.e., if side stitch
timePerStitch+=addSecondsSideStitch
if bwListLoop[stitch] == bwListLoop[stitch-1]: # stitch = same color as last stitch, no movement, add time
t+=timePerStitch
else: # stitch color changes, finalize time for last section of colors, reset time and add a move
gCode+='G4 P'+str(t)+'\n' #adds time in milliseconds
t=timePerStitch #reset time to time of 1 stitch
if bwListLoop[stitch]==0: #change this once i look at photo data
gCode+=moveZblack
else:
gCode+=moveZwhite
stitch+=1
print(gCode)