---
# System prepended metadata

title: K-Tape Cutter

---

# K-Tape Cutter

![IMG_2100](https://hackmd.io/_uploads/rJMk1MYda.jpg)



## Overview
　　This is a **Laser Cutter Machine for Kinesiology Tape**.
  
　　Physical health is a big issue for every athlete, they have always to take care of their body. It is quite important to have a good connection with their trainers to protect themselves, especially during the competition period. Sometimes athletes have to apply kinesiology tapes before the game so that they can have better performance. 
  
　　However, the tape-cutting work is very time consumed may delay their preparation state. In addition, trainers would not be by their sides 24/7……  So if an athlete wants to apply the tape, they have to cut it by themselves (or the trainers) beforehand and bring the tape somewhere for application by trainers, the tape may be damaged while stored in a bag, which will reduce the effectiveness  :(
  
　　The Best helper for Athletes and Athletic Trainers! Using Telegram, we can communicate with the K-Tape Cutter Genie to ask for the ideal length and style of cutting Kinesiology Tape, after receiving the QR code generated by the K-Tape genie, athletes only have to scan the image by the K-Tape Cutter machine that can get the tape which they requested!!!


## What it is

### The Apperance

![S__3751944](https://hackmd.io/_uploads/BkBVTlFO6.jpg)




### Demo Video
[![video](https://hackmd.io/_uploads/S1IRTYK_a.png)
](https://www.youtube.com/watch?v=M4aRxDg3Xf8)



## Component

![S__180936712](https://hackmd.io/_uploads/r1Csled_T.jpg)



### Hardware

|Name |Quantity|
|-----|--------|
|Raspiberry Pi 4|1       |
|12V 2.5 W Laser Head |1      |
|28BYJ-48 5VDC stepper motor|3|
|ULN2003 stepper motor driver|3|
|360° Rotary Encoder|1||
|Logitech Webcam|1||
|Sliding tracks for 28BYJ-48 stepper motor|2||
|Power Supplier for Raspiberry Pi|1||
|1.5V AA battery|8||
|4x 1.5V AA batteries holder|2||
|Breadboard|1||
|GPIO pin extender|1||
|40 pins Rainbow GPIO cable|1||
|Jumper wires|many many||

### Software
| Icon                                                | Name                | Download here!                                             |
| --------------------------------------------------- | ------------------- | ---------------------------------------------------------- |
|![python](https://hackmd.io/_uploads/BkldGguOT.png) | Python              | https://www.python.org/downloads/release/python-3717/      |
|![bot](https://hackmd.io/_uploads/SyjbmxOOa.jpg)  | Python Telegram Bot | https://github.com/python-telegram-bot/python-telegram-bot |

### Others
|Name |Quantity| 
|-----|--------|
|Encoder Wheel|1       |
|Roller Tube|1      |
|cotton thread|1||
|15mm binder clip|1|
|Kinsiology Tape|1|
|Tape Holder|1|
|Wood Squares|10||
|Thick cardboard|2||
|Clipboard|1||
|Instant glue|1||


## Let's make it

### System Logic
![sysDiagram](https://hackmd.io/_uploads/H1GZrwFdp.jpg)



### Circuit Diagram
![Circuit](https://hackmd.io/_uploads/Hk4eWPFdT.jpg)


## Before Getting Start
### 1. Set up [Raspberry Pi OS](https://www.raspberrypi.com/software/) ###


### 2. Build the environment for this project ###

##### **Basic enviornments** #####
Go yor Raspberry Pi terminal and enter:
        
        sudo apt-get install libzbar0
        pip install RPi.GPIO
        pip install pyzbar
        pip install opencv-python
        



##### **OpenCV** #####
Follow below link to **Install CMake 3.14.4** and **Install OpenCV**:
(p.s. In this project, u don't need to install OpenVINO!!)
https://hackmd.io/HV6hQ2PHSiWlrRsfxC10SA

##### **Telegram bot** #####
Go to your local computer terminal and enter:

        pip install python-telegram-bot --upgrade
        pip install qrcode

### 3. 3D print to make Wheel & Tube ###
* My 3D print file: [tubeNwheels.gcode](https://github.com/Chienyuuu6/K-Tape-Cutter/blob/main/3D%20print/tubeNwheels.gcode)
* Or you can find lots of 3D models on [PrintTables](https://www.printables.com/)
* You can design your own 3D print file on [Tinkercad](https://www.tinkercad.com/)



##### Encoder & Wheel #####
The purpose of having a wheel is to calculate the actual length of the pulled-out tape. Since I use a 360 ° rotary encoder to obtain the goal, I need an encoder “wheel-like”  knob.

##### Motor & Tube #####
The tube is for collecting the pulled-out tape.
I’d like to roll out the tape by sticking the motor with the tape roll, but I found that the tape won’t roll out, it’s become loose… So I adapted plan B: set the motor away from the tape and use blind clips to pull it out.



## Build up your own Chatting Genie ##
I use **Python Telegram bot v20.7** to make my own chatting bot.

Follow the steps to get your own bot!

 ### **STEP1** [Download](https://desktop.telegram.org/) Telegram ###
![tele](https://hackmd.io/_uploads/r1EYPRdda.png)



### **STEP2** Use [@BotFather](https://t.me/BotFather) to create new bot  ###
![fa](https://hackmd.io/_uploads/SkfhD0O_6.png)


### **STEP3** Follow these link to learn how to setting your bot ###
* Build Bot: https://tcsky.cc/tips-01-telegram-chatbot/
* Instructions & Examples (v13): https://hackmd.io/@truckski/HkgaMUc24?type=view
* Offical document: https://docs.python-telegram-bot.org/en/v20.7/

### **STEP4** Edit your bot in python ###
* Import the libraraies

            from telegram.ext import (  
                ContextTypes,
                ApplicationBuilder,
                CommandHandler,
                MessageHandler,
                filters,
                ConversationHandler,
                CallbackQueryHandler,
            )
            from io import BytesIO
            import json
            import logging
            from telegram import Update,InlineKeyboardButton,InlineKeyboardMarkup
            import qrcode

* Setting token on the script "YOUR TOKEN HERE".

<font color=#930000>**Notice**: MUST keep your token private & safe.</font>

        application = ApplicationBuilder().token("YOUR TOKEN HERE").build()
        

* Examples for designing the bot
    * Reference code: https://github.com/Amir-AJ-PRO/Bot-projects-PythonTelegramBot-V20/blob/main/ChatBot.py
    *  Conversation bot example: https://docs.python-telegram-bot.org/en/v20.7/examples.conversationbot.html

* My KTapeGenieBot: [KTapeGenie.py](https://github.com/Chienyuuu6/K-Tape-Cutter/blob/main/telegramBot/KTapeGenieBot.py)


## Build up the K-Tape Cutter ##

* My Cutter: [cutter.py](https://github.com/Chienyuuu6/K-Tape-Cutter/blob/main/cutter.py)

### **STEP1** Motor ###
![S__3751942](https://hackmd.io/_uploads/r1i86ltOp.jpg)

I use 28BYJ-48 5vDC stepper motors as my XY axis and tape-roller controller.
You Need a ULN2003 stepper motor driver to drive each motor.

* Motor setup

1. For scripting the motor, you need these libraries:

        import RPi.GPIO as GPIO
        import time
        from threading import Thread


1. Set up the GPIO pins
Here I used **GPIO.setmode(GPIO.BCM)**
Replace the number of "pins" list as the pins you used for in1, in2, in3, and in4!
    
            
        # Define the GPIO pins for the stepper motor
        # pins = [in1, in2, in3, in4]
            
            GPIO.setmode(GPIO.BCM) 
            motor_pins = [18,23,24,25]
    
            for i in motor_pins:        
            GPIO.setup(i, GPIO.OUT)



* Make it Move!

Here is the moving sequence of the motor:

        # Define the sequence of steps for the stepper motor
                seq = [
                    [1, 0, 0, 1],
                    [1, 0, 0, 0],
                    [1, 1, 0, 0],
                    [0, 1, 0, 0],
                    [0, 1, 1, 0],
                    [0, 0, 1, 0],
                    [0, 0, 1, 1],
                    [0, 0, 0, 1]
                ]

    An Example to move the motor in two direction:
    
        # move one motor   
        # the arg "pins" is the "pins list" of your motor

        
        def move_single(pins, steps, speed, direction):
            # move forward
            if direction == 0:
                for _ in range(steps):
                    print(_)
                    for i in range(8):
                        for y in range(4):
                            GPIO.output(pins[y], seq[i][y])
                        time.sleep(speed)
                        
            # move backward
            else:
                for _ in range(steps):
                    print(_)
                    for i in range(8):
                        for y in range(4):
                            pin=abs(y-(3))
                            GPIO.output(pins[pin], seq[i][y])
                        time.sleep(speed)

* How it work: **28BYJ-48 stepper motor** (source: [ChatGPT](https://chat.openai.com/))
Accroding above example, here's sth you need to know:
    * The **seq** variable defines the sequence of steps for the stepper motor. Adjusting this sequence can change the motor direction and stepping behavior.
    * The **for _ in range(steps) loop** moves the stepper motor by a specified number of steps with a specified delay between steps.
    * The **for y in range(4) loop** sets the motor coils based on the current step.


* Move both motor in the same time
I defined motor_x and motor_y beforehand, and using **Thread** to make both motors move together!
 
        # move a slope
        def move_both( speed, direction_x, direction_y):
            thread_x = Thread(target=motor_x, args=(slope, speed, direction_x))
            thread_y = Thread(target=motor_y, args=(slope, speed, direction_y))

            thread_x.start()
            thread_y.start()

            thread_x.join()
            thread_y.join()


### **STEP2** Rotary Encoder ###
![S__3751940](https://hackmd.io/_uploads/B1sP6gtuT.jpg)

I use rotary encoder to calculate the actual length of the pulled-out tape.
* My Encoder: [encoder.py](https://github.com/Chienyuuu6/K-Tape-Cutter/blob/main/encoder.py)
* Encoder setup

        # Define GPIO pins for the rotary encoder
        CLK = 22  # Rotary encoder CLK pin
        DT = 27  # Rotary encoder DT pin
        SW = 17   # Rotary encoder SW (push button) pin

        # Setup GPIO mode and pins
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(CLK, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(DT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.setup(SW, GPIO.IN, pull_up_down=GPIO.PUD_UP)

* How it work: **Incremental Rotary Encoder** (source: [ChatGPT](https://chat.openai.com/))

    * Mechanical Structure: An incremental rotary encoder consists of a rotating disk with evenly spaced slots or markings, and a stationary sensor (optical or magnetic) that reads these markings as the disk rotates.
    * Working Principle: As the encoder shaft turns, the sensor detects changes in position by counting the number of slots that pass by or changes in the magnetic field. Each slot or marking represents a discrete "step" or "pulse."
    * Output: The output of an incremental encoder is a series of pulses. The direction of rotation can be determined by the order in which these pulses occur (increasing or decreasing). However, an incremental encoder does not provide information about the absolute position; it only indicates the relative change in position.

          # Initialize variables
            counter = 0
            clk_last_state = GPIO.input(CLK)
            dt_last_state = GPIO.input(DT)

          # Callback function for the rotary encoder
            def rotary_encoder_callback(channel):
                global counter, clk_last_state, dt_last_state

                clk_state = GPIO.input(CLK)
                dt_state = GPIO.input(DT)

                if clk_state != clk_last_state:
                    if dt_state != clk_state:
                        counter += 1
                    else:
                        counter -= 1

                clk_last_state = clk_state
                dt_last_state = dt_state

### **STEP3** Laser Head ###
![S__3751943](https://hackmd.io/_uploads/SJsdpgY_T.jpg)

:::danger
MUST be Carefully while testing the laser!!!
:::
The most important Role in this project: **Laser Head**.
For cutting the Kinesiology tape we'd lke!

* Laser setup
Use the pin with PWM control! 
        1. GPIO12 & GPIO18 (PWM0)
        2. GPIO13 & GPIO19 (PWM1)

            GPIO.setmode(GPIO.BCM)

            def laser(status):
                laser_pin = 12
                GPIO.setup(laser_pin, GPIO.OUT)
                GPIO.output(laser_pin, status)


* How it work: [**Laser Head**](https://www.ruten.com.tw/item/show?22330312878964&_gl=1*17h5nd8*_ga*MzE0NTMwNzU1LjE2OTg4NDUwMjY.*_ga_2VP4WXLL56*MTcwNDY4NTcyMi4yOC4xLjE3MDQ2ODU3MzUuNDcuMC4w)
Control the laser by these commands:

        laser(GPIO.LOW)  # close the laser
        laser(GPIO.HIGH) # open the laser

### **STEP4** Design the cutting Route ###
I found that every 660 steps, the motor move 5cm which is one grid of the Kinesiology tape.

Base on this, we can design the moving route by different x or y motors, steps, and direction.

Here's some example:
        
    # tape cutting format
    # move steps
        grid = 692
        half = 346
        halfhalf = 173

        slope = 60

        cut1 = 632
        cut2 = 590

        cutY = 226
        cutF = 53

    # speed
        laser_speed = 0.025
        move_speed = 0.001
    # onclose
        def onclose_u():
            laser(GPIO.LOW)
            motor_y(cut1, move_speed, 0)
            laser(GPIO.HIGH)
            move_both(laser_speed, 0,0)
            laser(GPIO.LOW)
            motor_x(cut2, move_speed, 0)
            laser(GPIO.HIGH)
            move_both(laser_speed, 0,1)
            laser(GPIO.LOW)
            motor_y(cut1, move_speed, 1)
            motor_x(grid, move_speed, 1)   


### **STEP5** Web cam & Decoding QRcode ###

By scaning the QR code generated from K-Tape Genie, the program can get the arguments it needs and start the laser cutting work!!

* My qrCode detector: [qrCode.py](https://github.com/Chienyuuu6/K-Tape-Cutter/blob/main/qrCode.py)

* OpenCV
Most importantly for this code to run is to     import OpenCV & the libraries we needed:
   
            import cv2
            import pyzbar.pyzbar as pyzbar
            import json

    * set up web cam
            
            # set up camera object called Cap which we will use to find OpenCV
            cap = cv2.VideoCapture(0)
            font = cv2.FONT_HERSHEY_PLAIN

* Decoding the img

    
        def run():
        try:
            while True:
                _, img = cap.read()
                decodedObjects = pyzbar.decode(img)
    
            # Check if any QR code is detected
                if decodedObjects:
                    for obj in decodedObjects:
                        try:
                            decoded_data = str(obj.data, 'utf-8')
                            print(decoded_data)

                            # Replace single quotes with double quotes
                            decoded_data = decoded_data.replace("'", "\"")


                            data = json.loads(decoded_data)
                            format = data['format']
                            length = data['length']
                            inner = data['inner']
                            print('json data detected in QR code:\n' + format + '\n' + str(length) + '\n' + str(inner) + '\n')
                            cv2.putText(img, str(obj.data), (50, 50), font, 2, (255, 0, 0), 3)
                            
                            cap.release()
                            cv2.destroyAllWindows()

                            return format, length, inner
                    

                        except json.JSONDecodeError as e:
                            print("Error decoding JSON:", e)    
                            continue
                        except Exception as e:
                            print("Error processing QR code data:", e)
                            continue

                cv2.imshow("code detector", img)
    
                if cv2.waitKey(1) == ord("q"):
                break
    
            cap.release()
            cv2.destroyAllWindows()

        except KeyboardInterrupt:
            key = cv2.waitKey(1)
            if key == 27:
                cap.release()
                cv2.destroyAllWindows()
                return

            
    
    **Look Deeper into the above code**
    
        for obj in decodedObjects:
            try:
                decoded_data = str(obj.data, 'utf-8')
                print(decoded_data)

                # Replace single quotes with double quotes
                decoded_data = decoded_data.replace("'", "\"")


                data = json.loads(decoded_data)
                format = data['format']
                length = data['length']
                inner = data['inner']
                print('json data detected in QR code:\n' + format + '\n' + str(length) + '\n' + str(inner) + '\n')
                cv2.putText(img, str(obj.data), (50, 50), font, 2, (255, 0, 0), 3)
                
                cap.release()
                cv2.destroyAllWindows()

                return format, length, inner
    
        
These scripts help us to get the important argments and retuen to the main program that make the cutter start running!!!


## Let's Coding ##
Here is my code for the whole project
Link here: https://github.com/Chienyuuu6/K-Tape-Cutter

## Reference

#### Laser Engraver
* Mini CNC plotter: https://www.hackster.io/embeddedlab786/mini-cnc-plotter-machine-at-home-6cddbf
* How to Make Powerfull Laser Engraver: https://www.hackster.io/diyprojectslab/how-to-make-powerfull-laser-engraver-d7b675


#### QR code detector
* How To Scan QR Codes With A Raspberry Pi + OpenCV + Python: https://www.youtube.com/watch?v=Qf55aUgfLfQ
* iot-bartender for **qrcode detecting**: https://github.com/chung-coder/Iot-bartender/blob/main/Iot-bartender/camera.py

#### Telegram bot
* iot-bartender for **telegram bot api**: https://github.com/chung-coder/Iot-bartender/

#### 3D print
* **Encoder wheels** that I modified from: https://www.printables.com/model/646906-encoder-wheel-for-seeder/files

* **Tape roller** tube that I modified from: https://www.printables.com/model/583211-50mm-tape-roller


#### Others
* Green house for **motor moving tracks**: https://hackmd.io/@fGmzd-CTSGSBPbmj6Sr-nw/BJ06WFw0P#Green-House


