This is not something everyone needs, but it is something that is fun and cool to build. Maybe not the exact same thing, but some variation thereof… This is a heat shrink cutter. It uses a stepper motors to move the heat shrink through the feeder made of 3D printed wheels. The heat shrink is cut with a pair of scissors that are violently actuated via a pneumatic cylinder. The heat shrink fall down a tube and is collected in a cup carousel that is rotated by a stepper motor once the set amount of heat shrink is cut. Its all powered by a Arduino Mega (the code is at the bottom of the page). This project took about two weeks to build (primarily built after-hours while watching TV and enjoying a beverage or three). No fingers were lost in the making this product!
We set this up so we could make heat shrink to any length for ourselves. We use a lot of heat shrink. Don’t use electrical tape, its just amateur and it will usually come undone, looks like sh*t, etc. We are probably going to make different cutters so we can cut wire to set lengths too, etc. The program is set up to cut in inches or feet and can cut from a 1/4″ to 120′ lengths. The stepper motors deliver very precise lengths, then the scissors cut the heat shrink. All the settings can be changed when the program starts using the LCD and buttons and knobs via the menu. Then when its all confirmed the machine will run. The fruits of our labor are available online for those who don’t want to build their own machine and buy 500 foot rolls of heat shrink.
- 0.125 x 0.75 inch long heat shrink tubing, pack of 12
- 0.188 x 1 inch long heat shrink tubing, pack of 12
- 0.25 x 1 inch long heat shrink tubing, pack of 12
Below is the video showing the setup of the machine and then it running for a couple cycles. Below the video is code that was used in the Arduino.
/* Project: Heat Shrink and Wire Cutter Author: SuperDroid Robots Inc. Date: April 27, 2016 Notice: Copyright (c) 2016 SuperDroid Robots. All Rights Reserved Arduino: Arduino Mega Scope: Project is written to use stepper motors to feed heat strink or wire a precise distance and cut it. The cut piece falles down a shoot, then is collected in a cup on a rotary tray. The tray holds 12 cups The cut is actuated by a pair of cutters on a pneumatic cylinder. http://www.SuperDroidRobots.com */ #include// I2C Library #include // LCD I2C Library LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address //Global constants and variables int i = 0; // counting variable int j = 0; // counting variable int k = 0; // counting variable int sw_val = 0; // variable to store the read value int an_val = 0; // varialbe to store analog read value long an_average; // Calculated variable used for analog reading byte SW_STAT = 0; // variable for switch status byte Feed_Units = 0; // units 0 = inches, 1 = feet byte Feed_Range = 0; // cut range. 0 = 0-12.00, 1 = 0-120.0 long Feed_Length = 0; // divide by 100 float val_float; //floating value for display long Step_per_Cut; // Calculated variable for steps wheels feed per cut byte Feed_Speed1 = 0; // 0-slow, 1=medium, 2=fast byte Number_of_Cuts = 10; // number of times the cutter cycles per cycle byte Number_of_Cycles = 1; // number of cycles the catcher turtable will make int Catcher_Count = 0; // counter for number of steps the catcher turntable has taken int Feed_Speed = 500; // delay between step pulses for cutting speed - bit banging (uSec) int Turntable_Step_Speed = 5000; //usec delay - delay between step pulses int Cut_Delay_Start = 200; //delay msec - delay befor triggering coil to cut int Cut_Delay_High = 1000; //delay msec - delay after tiggering cut int Cut_Delay_Low = 200; //delay msec - delay after triggering cut #define Bottom_wheel_stp 53 // stepper step IO Pin #define Bottom_wheel_dir 51 // stepper dir IO Pin #define Bottom_wheel_en 49 // stepper enable IO Pin #define Top_wheel_stp 47 // stepper step IO Pin #define Top_wheel_dir 45 // stepper dir IO Pin #define Top_wheel_en 43 // stepper enable IO Pin #define Catcher_Stp 38 // stepper step IO Pin #define Catcher_Dir 36 // stepper dir IO Pin #define Catcher_en 34 // stepper enable IO Pin #define Cutter_Trigger 41 // IO that triggers scissors #define SW1 31 #define SW2 29 #define SW3 27 #define SW4A 37 #define SW4B 39 #define SW5A 35 #define SW5B 33 #define Catcher_Limit 32 int analogPin = 1; // potentiometer wiper (middle terminal) connected to analog ///////////////////////////////////////////////////////////////////////////////////// // SETUP ////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// void setup(void) { Serial.begin(115200); pinMode(Bottom_wheel_stp, OUTPUT); pinMode(Bottom_wheel_dir, OUTPUT); pinMode(Bottom_wheel_en, OUTPUT); pinMode(Top_wheel_stp, OUTPUT); pinMode(Top_wheel_dir, OUTPUT); pinMode(Top_wheel_en, OUTPUT); pinMode(Cutter_Trigger, OUTPUT); pinMode(SW1, INPUT); pinMode(SW2, INPUT); pinMode(SW3, INPUT); pinMode(SW4A, INPUT); pinMode(SW4B, INPUT); pinMode(SW5A, INPUT); pinMode(SW5B, INPUT); pinMode(Catcher_Stp, OUTPUT); pinMode(Catcher_Dir, OUTPUT); pinMode(Catcher_en, OUTPUT); pinMode(Catcher_Limit, INPUT); digitalWrite(Bottom_wheel_en, HIGH); //enable stepper drivers digitalWrite(Top_wheel_en, HIGH); digitalWrite(Catcher_en, HIGH); digitalWrite(Bottom_wheel_dir, LOW); //Set direction of stepper drivers digitalWrite(Top_wheel_dir, HIGH); digitalWrite(Catcher_Dir, HIGH); digitalWrite(Cutter_Trigger, LOW); delay(800); //let LCD warm up lcd.begin(20,4); // Initialize the lcd for 20 chars 4 lines, turn on backlight lcd.backlight(); // finish with backlight on lcd.clear(); lcd.setCursor(0,0); lcd.print("SuperDroid Robots"); lcd.setCursor(0,1); lcd.print("Parts Cutter"); lcd.setCursor(0,2); lcd.print("Version 1.0"); delay(1000); //Display startup } ///////////////////////////////////////////////////////////////////////////////////// // MAIN LOOP ////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// void loop(void) { //test_inputs(); //used to check IO, not needed once all set up restart: lcd.clear(); // Start turntable and rotate until hits a limit - there is a limit for each cup/tray /////////// lcd.setCursor(0,0); lcd.print("Setting Turntable..."); digitalWrite(Catcher_Dir, LOW); // set direction while (digitalRead(Catcher_Limit) == LOW) { //limit_reached = digitalRead(Catcher_Limit) digitalWrite(Catcher_Stp, HIGH); delayMicroseconds(Feed_Speed); digitalWrite(Catcher_Stp, LOW); delayMicroseconds(Feed_Speed); } // User Select Speed /////////////////////////////////////// lcd.setCursor(0,0); lcd.print("1:CHANGE 3:ENTER "); lcd.setCursor(0,2); lcd.print("FEEDING SPEED: "); delay(300); //debounce Feed_Speed1 = 3; SW_STAT = 0; while (SW_STAT == 0){ sw_val = digitalRead(SW3); if (sw_val) SW_STAT = 3; sw_val = digitalRead(SW1); if (sw_val) { Feed_Speed1++; delay(200); //LCD refresh delay and debounce... } if (Feed_Speed1 == 1) { lcd.setCursor(14,2); lcd.print("SLOW "); Feed_Speed = 1500; } else if (Feed_Speed1 == 2) { lcd.setCursor(14,2); lcd.print("MEDIUM"); Feed_Speed=1000; } else { Feed_Speed1 = 0; lcd.setCursor(14,2); lcd.print("FAST "); Feed_Speed = 500; } } // User Select Units /////////////////////////////////////// lcd.setCursor(0,0); lcd.print("1:CHANGE 3:ENTER "); lcd.setCursor(0,2); lcd.print("CUT UNITS: "); delay(300); //debounce Feed_Units = 0; SW_STAT = 0; while (SW_STAT == 0){ sw_val = digitalRead(SW3); if (sw_val) SW_STAT = 3; sw_val = digitalRead(SW1); if (sw_val) { Feed_Units++; delay(200); //LCD refresh delay and debounce... } if (Feed_Units == 1) { lcd.setCursor(10,2); lcd.print("Feet "); } else { Feed_Units = 0; lcd.setCursor(10,2); lcd.print("Inches"); } } // User Select Range /////////////////////////////////////// lcd.setCursor(0,0); lcd.print("1:CHANGE 3:ENTER "); lcd.setCursor(0,2); lcd.print("RANGE: "); delay(300); //debounce Feed_Range = 0; SW_STAT = 0; while (SW_STAT == 0){ sw_val = digitalRead(SW3); if (sw_val) SW_STAT = 3; sw_val = digitalRead(SW1); if (sw_val) { Feed_Range++; delay(200); //LCD refresh delay and debounce... } if (Feed_Range == 1) { lcd.setCursor(6,2); lcd.print("0 to 120.0"); } else { Feed_Range = 0; lcd.setCursor(6,2); lcd.print("0 to 12.00"); } } // User Select Length of cut /////////////////////////////////////// lcd.setCursor(0,0); lcd.print("1:RESTART 3:ENTER "); lcd.setCursor(0,1); lcd.print("TURN POTENTIOMETER "); lcd.setCursor(0,2); lcd.print("CUT LENGTH: "); delay(300); //debounce if (Feed_Units==1) { lcd.setCursor(17,2); lcd.print("ft"); } else { lcd.setCursor(17,2); lcd.print("in"); } lcd.setCursor(0,3); lcd.print("AN:"); lcd.setCursor(8,3); lcd.print("STEPS:"); SW_STAT = 0; while (SW_STAT == 0){ sw_val = digitalRead(SW1); if (sw_val) SW_STAT = 1; sw_val = digitalRead(SW3); if (sw_val) SW_STAT = 3; an_average=0; for(i=0; i< 10; i++){ an_val = 1024 - analogRead(analogPin); // read the input pin an_average = an_average + an_val; delay(25); } an_average = an_average/(i+1); lcd.setCursor(3,3); lcd.print(" "); lcd.setCursor(3,3); lcd.print(an_average); Feed_Length = 12*an_average/10.24; //have to mulitiply by 12 again for feet Step_per_Cut = 1600; // leght in inches cuts: 1600/(3*3.14): 3" wheel, 9.42478 inches per rev, 1600 pulses per rev Step_per_Cut = 1600/9.42478; if (Feed_Range==0) Step_per_Cut = Step_per_Cut * Feed_Length/100; if (Feed_Range==1) Step_per_Cut = Step_per_Cut * Feed_Length/10; if (Feed_Units==1) Step_per_Cut = Step_per_Cut*12; lcd.setCursor(14,3); lcd.print(" "); lcd.setCursor(14,3); lcd.print(Step_per_Cut); lcd.setCursor(12,2); lcd.print(" "); if (Feed_Range==0) val_float = float(Feed_Length)/100.00; if (Feed_Range==1) val_float = float(Feed_Length)/10.0; lcd.setCursor(11,2); lcd.print(val_float); } if (SW_STAT == 1) goto restart; // User Select Number of Cuts /////////////////////////////////////// lcd.setCursor(0,0); lcd.print("1:RESTART 3:ENTER "); lcd.setCursor(0,1); lcd.print("4:INC 1 5:INC 10"); lcd.setCursor(0,2); lcd.print("# OF CUTS: "); lcd.setCursor(0,3); lcd.print(" "); delay(300); //debounce Number_of_Cuts = 10; SW_STAT = 0; while (SW_STAT == 0){ sw_val = digitalRead(SW1); if (sw_val) SW_STAT = 1; sw_val = digitalRead(SW3); if (sw_val) SW_STAT = 3; if (digitalRead(SW4A)) { Number_of_Cuts++; } else if (digitalRead(SW4B)) { Number_of_Cuts--; } else if (digitalRead(SW5A)) { Number_of_Cuts = Number_of_Cuts + 10; } else if (digitalRead(SW5B)) { Number_of_Cuts = Number_of_Cuts - 10; } delay(200); //LCD refresh delay and debounce... if (Number_of_Cuts >= 99) Number_of_Cuts = 99; if (Number_of_Cuts <= 1) Number_of_Cuts = 1; lcd.setCursor(10,2); lcd.print(" "); lcd.setCursor(10,2); lcd.print(Number_of_Cuts); } delay(250);//debouce if (SW_STAT == 1) goto restart; // User Select Number of Cycles /////////////////////////////////////// lcd.setCursor(0,0); lcd.print("1:RESTART 3:ENTER "); lcd.setCursor(0,1); lcd.print("4:INC 1 "); lcd.setCursor(0,2); lcd.print("# OF CYCLES: "); delay(300); //debounce Number_of_Cycles = 1; SW_STAT = 0; while (SW_STAT == 0){ sw_val = digitalRead(SW1); if (sw_val) SW_STAT = 1; sw_val = digitalRead(SW3); if (sw_val) SW_STAT = 3; if (digitalRead(SW4A)) { Number_of_Cycles++; } else if (digitalRead(SW4B)) { Number_of_Cycles--; } delay(200); //LCD refresh delay and debounce... if (Number_of_Cycles >= 12) Number_of_Cycles = 12; if (Number_of_Cycles <= 1) Number_of_Cycles = 1; lcd.setCursor(12,2); lcd.print(" "); lcd.setCursor(12,2); lcd.print(Number_of_Cycles); } delay(250);//debouce if (SW_STAT == 1) goto restart; repeat_cut: ///////////////////////////////////////////////////////////////////////////////////// // READY TO RUN. THIS STARTS THE CUTTING!!! /////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// lcd.clear(); lcd.setCursor(0,0); lcd.print("1:RESTART 2:RUN "); lcd.setCursor(0,1); lcd.print("READY TO RUN! "); lcd.setCursor(0,2); lcd.print("CUT LENGTH: "); if (Feed_Units==1) { lcd.setCursor(17,2); lcd.print("ft"); } else { lcd.setCursor(17,2); lcd.print("in"); } if (Feed_Range==0) val_float = float(Feed_Length)/100.00; if (Feed_Range==1) val_float = float(Feed_Length)/10.0; lcd.setCursor(11,2); lcd.print(val_float); lcd.setCursor(0,3); lcd.print("# CUTS:"); lcd.setCursor(7,3); lcd.print(Number_of_Cuts); lcd.setCursor(10,3); lcd.print("CYCLES:"); lcd.setCursor(17,3); lcd.print(Number_of_Cycles); delay(300); //debounce SW_STAT=0; while (SW_STAT == 0){ sw_val = digitalRead(SW1); if (sw_val) SW_STAT = 1; sw_val = digitalRead(SW2); if (sw_val) SW_STAT = 2; delay(250);//debouce } if (SW_STAT == 1) goto restart; lcd.clear(); delay(1000); for(k = 0; k < Number_of_Cycles; k++){ lcd.clear(); lcd.setCursor(0,0); lcd.print("Running!!!"); lcd.setCursor(0,0); lcd.print("2: (HOLD) TO PAUSE"); lcd.setCursor(0,1); lcd.print("Cut"); lcd.setCursor(4,1); lcd.print("0 "); lcd.setCursor(7,1); lcd.print("of "); lcd.setCursor(10,1); lcd.print(Number_of_Cuts); //lcd.setCursor(13,1); lcd.print("cuts"); lcd.setCursor(0,2); lcd.print("Cycle"); lcd.setCursor(7,2); lcd.print(k+1); lcd.setCursor(10,2); lcd.print("of "); lcd.setCursor(13,2); lcd.print(Number_of_Cycles); for(j = 0; j < Number_of_Cuts; j++){ pause_cut: if (digitalRead(SW2)) goto pause_cut; lcd.setCursor(4,1); lcd.print(j+1); lcd.setCursor(0,3); lcd.print("Feeding..."); for(i=0; i < Step_per_Cut; i++){ digitalWrite(Bottom_wheel_stp, HIGH); digitalWrite(Top_wheel_stp, HIGH); delayMicroseconds(Feed_Speed); digitalWrite(Bottom_wheel_stp, LOW); digitalWrite(Top_wheel_stp, LOW); delayMicroseconds(Feed_Speed); } lcd.setCursor(0,3); lcd.print("Cutting..."); delay(Cut_Delay_Start); digitalWrite(Cutter_Trigger, HIGH); delay(Cut_Delay_High); digitalWrite(Cutter_Trigger, LOW); delay(Cut_Delay_Low); } lcd.setCursor(0,3); lcd.print("Finished Cycle! "); delay(1000); // CYCLE TRAY !!! /////////////////////////////////////// digitalWrite(Catcher_Dir, LOW); // set direction Catcher_Count=0; //reset counter Catcher_Count++; for(Catcher_Count = 0; Catcher_Count < 200; Catcher_Count++){ //get it off the limit switch digitalWrite(Catcher_Stp, HIGH); delayMicroseconds(Feed_Speed); digitalWrite(Catcher_Stp, LOW); delayMicroseconds(Feed_Speed); } while (digitalRead(Catcher_Limit) == LOW) { //loop until it hits the limit digitalWrite(Catcher_Stp, HIGH); delayMicroseconds(Feed_Speed); digitalWrite(Catcher_Stp, LOW); delayMicroseconds(Feed_Speed); } } delay(2000); // debounce/pause lcd.clear(); lcd.setCursor(0,0); lcd.print("1:RESTART 2:REPEAT "); lcd.setCursor(0,1); lcd.print("READY TO RUN! "); SW_STAT=0; while (SW_STAT == 0){ sw_val = digitalRead(SW1); if (sw_val) SW_STAT = 1; sw_val = digitalRead(SW2); if (sw_val) SW_STAT = 2; delay(250);//debouce } if (SW_STAT == 1) goto restart; goto repeat_cut; } ////////////////////////// THE END OF MAIN LOOP ///////////////////////////////////////// void test_inputs(void) { //used to check IO, not needed once all set up lcd.clear(); // Test Inputs while(1) { lcd.setCursor(1,0); lcd.print("SW1"); sw_val = digitalRead(SW1); lcd.setCursor(5,0); lcd.print(sw_val); lcd.setCursor(9,0); lcd.print("SW2"); sw_val = digitalRead(SW2); lcd.setCursor(14,0); lcd.print(sw_val); lcd.setCursor(1,1); lcd.print("SW3"); sw_val = digitalRead(SW3); lcd.setCursor(5,1); lcd.print(sw_val); lcd.setCursor(9,1); lcd.print("A2"); an_val = 1024 - analogRead(analogPin); // read the input pin lcd.setCursor(14,1); lcd.print(" "); lcd.setCursor(14,1); lcd.print(an_val); lcd.setCursor(0,2); lcd.print("SW4A"); sw_val = digitalRead(SW4A); lcd.setCursor(5,2); lcd.print(sw_val); lcd.setCursor(9,2); lcd.print("SW4B"); sw_val = digitalRead(SW4B); lcd.setCursor(14,2); lcd.print(sw_val); lcd.setCursor(0,3); lcd.print("SW5A"); sw_val = digitalRead(SW5A); lcd.setCursor(5,3); lcd.print(sw_val); lcd.setCursor(9,3); lcd.print("SW5B"); sw_val = digitalRead(SW5B); lcd.setCursor(14,3); lcd.print(sw_val); } }