Станок для нарезки кабеля на базе Arduino


Похоже, Edward Carlson устал отмерять и нарезать кабель и он решил сделать автоматизированный станок для нарезки кабеля.
Для этого, ему понадобились:
— контроллер Arduino Mega,
— LCD-шилд с кнопками — для организации меню,
— шаговый двигатель — для перемещения кабеля между роликами на нужную длину,
— мощная сервомашинка — для приведения в действие ручные кусачки.

Скетч для Arduino

#include <Servo.h>
#include <Stepper.h>
#include <LiquidCrystal.h>


//////////////////////////////////////
// LCD buttons
//////////////////////////////////////
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5

int pinSwitch = 52;
int pinServo = 53;

const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
const int stepsPerFoot = 1209; // steps per stepsPerFoot of cable

int calSteps;           // steps counted during calibration
unsigned long startTime;
unsigned long endTime;
unsigned long calTime;
int switchLastState;    // switch change state

int cutPos = 0;         // servo cutter closed position
int openPos = 180;        // servo cutter open position
int servoDelay = 1000;   // servo movement time
int baseDelay = 6100;   // time to measure one stepsPerFoot of cable
int speed1 = 150;        // stepper speed in RPMs
int cutDelay;           // how long it takes to measure entire length
int setLen;             // requested length
int setQty;             // requested quantity
int currQty = 0;        // current quantity
int totalSteps;         // how many steps we need to measure the requested length
int measureLen = 0;     // measured length (float for decimals!)
int measureInch;
int measureFeet;
int cutLen;             // Measured length during cutting operation


unsigned long lastDelayTime = 0;
unsigned long delayTime = 300;
unsigned long lastInteraction = 0;
unsigned long lastUpdate = 0;
//int buttonState = 0;

int cursorPos = 0;
int menuState = 0;        // Menu position, starts at Menu 0

Stepper myStepper(stepsPerRevolution, 22, 24, 26, 28);
Servo myservo;

// Set up lcd global variable
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

/////////////////////////////////////////////
// New way to read buttons
////////////////////////////////////////////
int read_LCD_buttons()
{
  adc_key_in = analogRead(0); // read the value from the buttons
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  if (adc_key_in < 50) return btnRIGHT;
  if (adc_key_in < 195) return btnUP;
  if (adc_key_in < 380) return btnDOWN;
  if (adc_key_in < 555) return btnLEFT;
  if (adc_key_in < 790) return btnSELECT;

  return btnNONE; // when all others fail, return this...
}

void setup() {
  Serial.begin(9600);
  Serial.println("======== Automated Cable Cutter Online =========");

  pinMode(10, OUTPUT);    // LCD backlight control
  digitalWrite(10, 255);
  pinMode(pinSwitch, INPUT_PULLUP);

  lcd.begin(16, 2);     // Begin 16 x 2 LCD
  myservo.attach(pinServo);
  myStepper.setSpeed(speed1);

  myservo.write(openPos); // make sure we start with cutter open

  showMenus();
}

void loop() {
  lcd_key = read_LCD_buttons(); // read the buttons
  processButtons();             // do the thing
  if (digitalRead(pinSwitch) != switchLastState) {
    showMenus();
    switchLastState = digitalRead(pinSwitch);   // checks to see if the wire sensor switch has changed
  }

}

void processButtons () { // Reads the buttons and exectues the proper actions based on the menu currently open

  if ((millis() - lastDelayTime) > delayTime) {                                 // Only read buttons every 0.3 second

    switch (menuState) {
      case 0:
        ///////////////////////////////////////////////////
        // Menu 0: Cut mode
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT: // Select
            if (digitalRead(pinSwitch) == HIGH) {  // if we haven't loaded a cable
              releaseStepper();
            }
            menuState = 1;
            cursorPos = 1;
            showMenus();
            break;
          case btnRIGHT: // Right
            if (digitalRead(pinSwitch) == HIGH) {  // if we haven't loaded a cable
              releaseStepper();
            }
            menuState = 1;
            cursorPos = 1;
            showMenus();
            break;
          case btnUP: //Up
            menuState = 7;
            showMenus();
            break;
          case btnDOWN: // Down
            menuState = 2;
            showMenus();
            break;
          case btnLEFT: // ESC
            menuState = 0;
            showMenus();
            break;
        }
        break;
      case 1:
        ///////////////////////////////////////////////////
        // Menu 0 Sub 1: Set cuts
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:   // Select
            if (setQty > 0) { // only if we've set Qty and if there's a cable loaded
              cutCables();
            }
            break;
          case btnRIGHT: // Right
            if (cursorPos == 1) {
              cursorPos = 2;
            } else if (cursorPos == 2) {
              cursorPos = 1;
            }
            showMenus();
            break;
          case btnUP: //Up
            if (cursorPos == 1) {
              setLen ++;
            } else if (cursorPos == 2) {
              setQty ++;
            }
            showMenus();
            break;
          case btnDOWN: // Down
            if (cursorPos == 1 && setLen > 0) {
              setLen --;
            } else if (cursorPos == 2 && setQty > 0) {
              setQty --;
            }
            showMenus();
            break;
          case btnLEFT: // Left
            menuState = 0;
            showMenus();
            break;
        }
        break;
      case 2:
        ///////////////////////////////////////////////////
        // Menu 1: Measure Mode
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:
            menuState = 5;    // measure menu
            showMenus();
            break;
          case btnRIGHT: // Right
            menuState = 5;    // measure menu
            showMenus();
            break;
          case btnUP: //Up
            menuState = 0;    // Go back to Top menu
            showMenus();
            break;
          case btnDOWN: // Down
            menuState = 7;    // Go to calibrate menu
            showMenus();
            break;
          case btnLEFT: // ESC

            break;
        }
        break;
      case 4:
        ///////////////////////////////////////////////////
        // Cut summary
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:
            menuState = 1;    // Go back to Cut menu
            showMenus();
            break;
          case btnRIGHT: // Right
            menuState = 1;    // Go back to Cut menu
            showMenus();
            break;
          case btnUP: //Up
            menuState = 1;    // Go back to Cut menu
            showMenus();
            break;
          case btnDOWN: // Down
            menuState = 1;    // Go back to Cut menu
            showMenus();
            break;
          case btnLEFT: // ESC
            menuState = 0;    // Go back to Top menu
            showMenus();
            break;
        }
        break;

      case 5:
        ///////////////////////////////////////////////////
        // Measurement mode
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:
            measureCable();
            break;
          case btnRIGHT: // Right
            // do nothing
            break;
          case btnUP: //Up
            // do nothing
            break;
          case btnDOWN: // Down
            // do nothing
            break;
          case btnLEFT: // ESC
            menuState = 2;    // Go back to Measure top menu
            showMenus();
            break;
        }
        break;
      case 6:
        ///////////////////////////////////////////////////
        // Cut summary
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:
            menuState = 5;    // Go back to Measure menu
            showMenus();
            break;
          case btnRIGHT: // Right
            menuState = 5;    // Go back to Measure menu
            showMenus();
            break;
          case btnUP: //Up
            menuState = 5;    // Go back to Measure menu
            showMenus();
            break;
          case btnDOWN: // Down
            menuState = 5;    // Go back to Measure menu
            showMenus();
            break;
          case btnLEFT: // ESC
            menuState = 5;    // Go back to Measure menu
            showMenus();
            break;
        }
        break;
      case 7:
        ///////////////////////////////////////////////////
        // Calibrate
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:
            menuState = 8;    // calibrate menu
            showMenus();
            releaseStepper();
            break;
          case btnRIGHT: // Right
            menuState = 0;    //
            showMenus();
            break;
          case btnUP: //Up
            menuState = 2;    //
            showMenus();
            break;
          case btnDOWN: // Down
            menuState = 0;    //
            showMenus();
            break;
          case btnLEFT: // ESC
            menuState = 0;    //
            showMenus();
            break;
        }
        break;
      case 8:
        ///////////////////////////////////////////////////
        // Calibrate
        ///////////////////////////////////////////////////
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:
            //menuState = 8;    //
            calibrate();
            showMenus();
            break;
          case btnRIGHT: // Right
            menuState = 0;    //
            showMenus();
            break;
          case btnUP: //Up
            menuState = 2;    //
            showMenus();
            break;
          case btnDOWN: // Down
            menuState = 0;    //
            showMenus();
            break;
          case btnLEFT: // ESC
            menuState = 0;    //
            showMenus();
            break;
        }
        break;

      default:
        switch (lcd_key) {
          case btnNONE: // No buttons
            // Do nothing
            break;
          case btnSELECT:
            menuState = 0;    //
            showMenus();
            break;
          case btnRIGHT: // Right
            menuState = 0;    //
            showMenus();
            break;
          case btnUP: //Up
            menuState = 0;    //
            showMenus();
            break;
          case btnDOWN: // Down
            menuState = 0;    //
            showMenus();
            break;
          case btnLEFT: // ESC
            menuState = 0;    //
            showMenus();
            break;
        }
        break;
    }
    lastDelayTime = millis();
  }
}



void showMenus() {
  // This function holds all the menu designs. Each case is a different menu/submenu. Cases are set by the Enter button incrementing the menuState variable.
  switch (menuState) {
    case 0:
      ///////////////////////////////////////////////////
      // Menu 0: Cut Mode
      ///////////////////////////////////////////////////

      lcd.noCursor(); // Don't show the cursor
      lcd.setCursor(0, 0);
      lcd.write("    Cut Mode    ");
      lcd.setCursor(0, 1);
      lcd.write("  Press Select  ");
      break;

    case 1:
      ///////////////////////////////////////////////////
      // Menu 0, Submenu 1: Cut Setup
      ///////////////////////////////////////////////////
      lcd.clear();
      lcd.cursor(); // Show the cursor
      lcd.setCursor(0, 0);
      lcd.write("Length (ft): ");
      lcd.setCursor(13, 0);
      lcd.print(setLen);
      lcd.setCursor(0, 1);
      lcd.write("Qty: ");
      lcd.print(setQty);
      if (digitalRead(pinSwitch) == HIGH) { // if we've not loaded a cable
        lcd.setCursor(10, 1);
        lcd.print("Load");
      } else {
        lcd.setCursor(10, 1);
        lcd.print("Ready");
      }

      if (cursorPos == 1) {
        lcd.setCursor(13, 0);
      } else if (cursorPos == 2) {
        lcd.setCursor(5, 1);
      }
      break;

    case 2:
      ///////////////////////////////////////////////////
      // Menu 1: Measure Mode
      ///////////////////////////////////////////////////
      lcd.noCursor(); // Don't show the cursor
      lcd.setCursor(0, 0);
      lcd.write("  Measure Mode  ");
      lcd.setCursor(0, 1);
      lcd.write("  Press Select  ");

      break;

    case 3:
      //////////////////////////////////////////////////
      // Cutting in Progress
      //////////////////////////////////////////////////
      lcd.clear();
      lcd.noCursor();
      lcd.setCursor(0, 1);
      lcd.print("Qty cut:");
      lcd.setCursor(8, 1);
      lcd.print(currQty);
      break;

    case 4:
      //////////////////////////////////////////////////
      // Cut summary
      //////////////////////////////////////////////////
      lcd.clear();
      lcd.noCursor();
      lcd.setCursor(0, 0);
      lcd.print("Complete");
      lcd.setCursor(0, 1);
      lcd.print("Cut ");
      lcd.setCursor(4, 1);
      lcd.print(currQty);
      lcd.print(" @ ");
      lcd.print(setLen);
      lcd.print(" ft.");
      break;
    case 5:
      //////////////////////////////////////////////////
      // Measure mode
      //////////////////////////////////////////////////
      lcd.clear();
      lcd.noCursor();
      lcd.setCursor(0, 0);
      if (digitalRead(pinSwitch) == HIGH) {
        lcd.print(" Load cable now ");
      } else {
        lcd.print("      Ready     ");
      }

      lcd.setCursor(0, 1);
      lcd.print("  Press Select  ");
      break;
    case 6:
      //////////////////////////////////////////////////
      // Measure summary
      //////////////////////////////////////////////////
      lcd.clear();
      lcd.noCursor();
      lcd.setCursor(0, 0);
      lcd.print("Measurement Done");
      lcd.setCursor(0, 1);
      lcd.print("Len: ");
      lcd.print(measureFeet);
      lcd.print("' ");
      lcd.print(measureInch);
      lcd.print("\"");
      break;

    case 7:
      //////////////////////////////////////////////////
      // Calibrate
      //////////////////////////////////////////////////
      lcd.clear();
      lcd.noCursor();
      lcd.setCursor(0, 0);
      lcd.print("Calibration Mode");
      lcd.setCursor(0, 1);
      lcd.print("  Press Select  ");
      break;

    case 8:
      //////////////////////////////////////////////////
      // Calibrate
      //////////////////////////////////////////////////
      lcd.clear();
      lcd.noCursor();
      lcd.setCursor(0, 0);
      lcd.print("Load exactly 1'");
      lcd.setCursor(0, 1);
      lcd.print("of cable.");
      break;

    case 9:
      //////////////////////////////////////////////////
      // Calibrate
      //////////////////////////////////////////////////
      lcd.clear();
      lcd.noCursor();
      lcd.setCursor(0, 0);
      lcd.print("Cal. Complete!");
      lcd.setCursor(0, 1);
      lcd.print(calSteps);
      lcd.print(" steps/ft");
      break;
  }
}

void calibrate() {
  calTime = 0;
  calSteps = 0;           // reset
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Calibrating...");


  while (digitalRead(pinSwitch) == LOW) {
    myStepper.step(1);
    calSteps ++;
    lcd.setCursor(0, 1);
    lcd.print(calSteps);
  }

  menuState = 9;        // Calibrate summary menu
  showMenus();
  releaseStepper();
}

void cutCables() {
  cutLen = 0;                     // reset measured length
  currQty = 0;                    // reset current quantity

  if (digitalRead(pinSwitch) == HIGH) {    // switch reads HIGH if we haven't loaded a wire
    lcd.setCursor(0, 0);
    lcd.print("Load Wire! ");
  } else {
    Serial.println("-_-_-_ Cutting subroutine activated _-_-_-");
    Serial.print("~ Cutting ");
    Serial.print(setQty);
    Serial.print(" pieces with length ");
    Serial.print(setLen);
    Serial.println(" feet.");
    Serial.print("~ Current quantity cut: ");
    Serial.println(currQty);

    //totalSteps = (setLen * stepsPerFoot);     // total steps per cut
    menuState = 3;                  // Cutting in progress menu
    showMenus();

    while (currQty < setQty) {
      myStepper.step(-20);
      delay(100);
      myStepper.step(20);             // unstick the wire from the cutter
      cutLen = 0;                     // reset measured length
      Serial.println("~~~ Measuring... ~~~");
      lcd.setCursor(0, 0);
      lcd.print("Measuring...    ");
      while (cutLen < setLen) {
        myStepper.step(stepsPerFoot);
        cutLen ++;
        lcd.setCursor(13, 0);
        lcd.print(cutLen);
      }
      Serial.println("~~~ Cutter Closed ~~~");
      lcd.setCursor(0, 0);
      lcd.print("Cutter closed   ");
      myservo.write(cutPos);
      delay(servoDelay);
      Serial.println("~~~ Cutter Open ~~~");
      lcd.setCursor(0, 0);
      lcd.print("Cutter open     ");
      myservo.write(openPos);
      delay(servoDelay);
      Serial.println("~~~ Cut made ~~~");
      currQty ++;
      showMenus();
    }

    menuState = 4;     // Cut summary
    showMenus();
  }
}

void measureCable() {
  int stepsPerInch = (stepsPerFoot / 12);
  measureLen = 0;

  lcd.clear();
  lcd.noCursor();
  lcd.setCursor(0, 0);
  lcd.print("  Measuring...  ");
  lcd.setCursor(0, 1);
  lcd.print("Len: ");
  lcd.print(measureLen);
  lcd.print(" in.");
  while (digitalRead(pinSwitch) == LOW) {
    myStepper.step(stepsPerInch);
    measureLen = measureLen + 1;
    lcd.setCursor(4, 1);
    lcd.print(measureLen);
  }

  //some math

  measureInch = measureLen % 12;
  measureFeet = measureLen / 12;

  menuState = 6;  // Summary menu
  showMenus();

  releaseStepper();
}

void releaseStepper() {
  digitalWrite(22, LOW);
  digitalWrite(24, LOW);
  digitalWrite(26, LOW);
  digitalWrite(28, LOW);
}


По теме
Автомат для нарезания провода
Робот-бендер для проволоки
RopeBot — робот для перерезания верёвки
Arduino-механизм для нарезки пенки
Простой ЧПУ под управлением Arduino

Arduino
Ардуино что это и зачем?
Arduino, термины, начало работы
КМБ для начинающих ардуинщиков
Состав стартера (точка входа для начинающих ардуинщиков)
  • 0
  • 15 января 2018, 10:20
  • admin

Комментарии (0)

RSS свернуть / развернуть

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.