// IoT Blynk notification
#define BLYNK_TEMPLATE_ID "TMPL6QtOn927d"
#define BLYNK_TEMPLATE_NAME "Cable Cutter Automatic Notification"
#define BLYNK_AUTH_TOKEN "8oSUsCEJg-GCSQDLo2_mpyKY1T0vA0V8"
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <ESP32Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// LCD configuration
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Pin definitions (matches your schematic)
#define OK_BUTTON 14
#define UP_BUTTON 13
#define DOWN_BUTTON 12
#define STATUS_LED 2
#define READY_LED 4
#define BUZZER 15
#define CUTTER_SERVO_PIN 25
#define SHEATH_SERVO_PIN 26
#define TINNING_SERVO_PIN 27
#define FEED_STEP_PIN 32
#define FEED_DIR_PIN 33
#define CUT_STEP_PIN 26
#define CUT_DIR_PIN 27
// Motor constants
const float FEED_STEPS_PER_MM = 105.0; // Steps per millimeter for feed stepper
const int CUT_STEPS = 3200; // Steps for one full cut
const int SERVO_OPEN = 0; // Servo open position (degrees)
const int SERVO_CLOSE = 90; // Servo closed position (degrees)
// Blynk credentials
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Global variables
int menuState = 0; // Current menu state (0-4)
int length_cm = 0; // Length in cm (1-100)
int quantity = 0; // Quantity (1-100)
int remainingCuts = 0; // Remaining cuts during operation
const int DEBOUNCE_DELAY = 200; // Button debounce delay (ms)
Servo cutterServo;
Servo sheathServo;
Servo tinningServo;
void setup() {
// Initialize pins
pinMode(OK_BUTTON, INPUT_PULLUP);
pinMode(UP_BUTTON, INPUT_PULLUP);
pinMode(DOWN_BUTTON, INPUT_PULLUP);
pinMode(FEED_STEP_PIN, OUTPUT);
pinMode(FEED_DIR_PIN, OUTPUT);
pinMode(CUT_STEP_PIN, OUTPUT);
pinMode(CUT_DIR_PIN, OUTPUT);
pinMode(STATUS_LED, OUTPUT);
pinMode(READY_LED, OUTPUT);
pinMode(BUZZER, OUTPUT);
// Initialize serial communication
Serial.begin(115200);
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.clear();
// Initialize Blynk
Blynk.begin(auth, ssid, pass, "blynk.cloud", 8080);
// Attach servos
cutterServo.attach(CUTTER_SERVO_PIN, 500, 2400);
sheathServo.attach(SHEATH_SERVO_PIN, 500, 2400);
tinningServo.attach(TINNING_SERVO_PIN, 500, 2400);
// Start with all servos open
cutterServo.write(SERVO_OPEN);
sheathServo.write(SERVO_OPEN);
tinningServo.write(SERVO_OPEN);
// Set initial LED states
digitalWrite(STATUS_LED, LOW);
digitalWrite(READY_LED, HIGH);
}
void loop() {
Blynk.run();
handleButtons();
updateDisplay();
}
void handleButtons() {
static unsigned long lastButtonPress = 0;
if (millis() - lastButtonPress < DEBOUNCE_DELAY) return;
// OK button - navigate through menu states
if (!digitalRead(OK_BUTTON)) {
menuState = (menuState + 1) % 5;
lastButtonPress = millis();
lcd.clear();
// If starting cutting process
if (menuState == 4) {
if (length_cm > 0 && quantity > 0) {
remainingCuts = quantity;
startCuttingProcess();
} else {
menuState = 0; // Return to home if invalid parameters
showError("INVALID PARAMS!");
}
}
return;
}
// UP/DOWN buttons - adjust values in appropriate states
if (menuState == 1 && !digitalRead(UP_BUTTON)) { // Length increase
length_cm = constrain(length_cm + 1, 1, 100);
lastButtonPress = millis();
lcd.clear();
}
else if (menuState == 1 && !digitalRead(DOWN_BUTTON)) { // Length decrease
length_cm = constrain(length_cm - 1, 1, 100);
lastButtonPress = millis();
lcd.clear();
}
else if (menuState == 2 && !digitalRead(UP_BUTTON)) { // Quantity increase
quantity = constrain(quantity + 1, 1, 100);
lastButtonPress = millis();
lcd.clear();
}
else if (menuState == 2 && !digitalRead(DOWN_BUTTON)) { // Quantity decrease
quantity = constrain(quantity - 1, 1, 100);
lastButtonPress = millis();
lcd.clear();
}
}
void updateDisplay() {
switch (menuState) {
case 0: // Home screen
lcd.setCursor(0, 0);
lcd.print("CABLE PROCESSING");
lcd.setCursor(0, 1);
lcd.print("CUT-SHEATH-TIN");
lcd.setCursor(11, 1);
lcd.print("NEXT>");
break;
case 1: // Set length
lcd.setCursor(0, 0);
lcd.print("SET LENGTH:");
lcd.setCursor(0, 1);
lcd.print(length_cm);
lcd.print(" cm");
lcd.setCursor(11, 1);
lcd.print("NEXT>");
break;
case 2: // Set quantity
lcd.setCursor(0, 0);
lcd.print("SET QUANTITY:");
lcd.setCursor(0, 1);
lcd.print(quantity);
lcd.print(quantity == 1 ? " piece" : " pieces");
lcd.setCursor(11, 1);
lcd.print("NEXT>");
break;
case 3: // Confirmation
lcd.setCursor(0, 0);
lcd.print("LENGTH: ");
lcd.print(length_cm);
lcd.print(" cm");
lcd.setCursor(0, 1);
lcd.print("QTY: ");
lcd.print(quantity);
lcd.print(quantity == 1 ? " piece" : " pieces");
lcd.setCursor(0, 2);
lcd.print("PROCESS: CUT-SHEATH-TIN");
lcd.setCursor(11, 1);
lcd.print("START?>");
break;
case 4: // Cutting in progress (handled separately)
break;
}
}
void startCuttingProcess() {
digitalWrite(READY_LED, LOW);
int feedSteps = length_cm * FEED_STEPS_PER_MM * 10; // Convert cm to steps
for (int i = 0; i < quantity; i++) {
updateCuttingDisplay(i + 1);
// Feed the wire
digitalWrite(FEED_DIR_PIN, HIGH); // Assuming HIGH is forward
for (int step = 0; step < feedSteps; step++) {
digitalWrite(FEED_STEP_PIN, HIGH);
delayMicroseconds(500);
digitalWrite(FEED_STEP_PIN, LOW);
delayMicroseconds(500);
}
// Process sequence
// 1. Cut the wire
cutterServo.write(SERVO_CLOSE);
delay(300);
cutterServo.write(SERVO_OPEN);
delay(300);
// 2. Remove sheath
sheathServo.write(SERVO_CLOSE);
delay(300);
sheathServo.write(SERVO_OPEN);
delay(300);
// 3. Strip and tin
tinningServo.write(SERVO_CLOSE);
delay(300);
tinningServo.write(SERVO_OPEN);
delay(300);
// Visual feedback
digitalWrite(STATUS_LED, !digitalRead(STATUS_LED));
Blynk.virtualWrite(V0, quantity - i - 1); // Update Blynk with remaining cuts
}
finishCutting();
}
void updateCuttingDisplay(int currentCut) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("PROCESSING ");
lcd.print(currentCut);
lcd.print("/");
lcd.print(quantity);
lcd.setCursor(0, 1);
lcd.print("REMAINING: ");
lcd.print(quantity - currentCut);
lcd.setCursor(0, 2);
lcd.print("STEPS: CUT-SHEATH-TIN");
}
void showError(const char* message) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("ERROR:");
lcd.setCursor(0, 1);
lcd.print(message);
digitalWrite(BUZZER, HIGH);
delay(1000);
digitalWrite(BUZZER, LOW);
delay(1000);
}
void finishCutting() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("PROCESS COMPLETE!");
lcd.setCursor(0, 1);
lcd.print(quantity);
lcd.print(" pieces processed");
lcd.setCursor(0, 2);
lcd.print("CUT-SHEATH-TIN DONE");
digitalWrite(STATUS_LED, HIGH);
digitalWrite(READY_LED, HIGH);
digitalWrite(BUZZER, HIGH);
delay(1000);
digitalWrite(BUZZER, LOW);
Blynk.logEvent("cable_process_finish", String("Processed ") + quantity + " pieces");
// Reset for next operation
menuState = 0;
length_cm = 0;
quantity = 0;
delay(2000);
lcd.clear();
}
Cable feeder
Cable Cutter
Leds and Buzzer
Down - Up - Choose
Sheath Removal
Stripping & Tinning