Sign In

Remember Me

Tech Thursday #039: An Automated Heat Shrink Cutter!

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!

SuperDroid Robots Heat Shrink Cutter

SuperDroid Robots Heat Shrink Cutter

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.



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); 
  }

}  

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Skip to toolbar