# K-Tape Cutter

## 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

### Demo Video
[
](https://www.youtube.com/watch?v=M4aRxDg3Xf8)
## Component

### 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://www.python.org/downloads/release/python-3717/ |
| | 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

### Circuit Diagram

## 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 ###

### **STEP2** Use [@BotFather](https://t.me/BotFather) to create new bot ###

### **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 ###

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 ###

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 ###

:::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