#include LiquidCrystal lcd(5, 6, 7, 8, 9, 10); #define encoderPinA 2 #define encoderSwitch 3 #define encoderPinB 4 #define enablePin 13 #define stepPin 12 #define dirPin 11 #define runPin A0 #define stopPin A1 #define numberOfItems 4 #define setupToolMenuItem 0 #define setupGapMenuItem 1 #define setZeroMenuItem 2 #define cancelMenuItem 3 #define numberOfSubMenuItems 2 #define setItem 0 #define cancelItem 1 #define factor 1 volatile float encoderPos = 0; volatile int currentMenuItem = -1; volatile int currentSubMenuItem = -1; int tmpInt; boolean rotating = false; boolean menuClicked = false; boolean subMenuShowing = false; boolean menuShowing = false; float toolSize = 3.0; float gapSize = toolSize; long stepDelayInMicroS = 800; int stepsPrMM = 160; int analogInput; void setup() { lcd.begin(16, 2); pinMode(encoderPinA, INPUT); digitalWrite(encoderPinA, HIGH); pinMode(encoderPinB, INPUT); digitalWrite(encoderPinB, HIGH); attachInterrupt(0, rotEncoder, CHANGE); pinMode(encoderSwitch, INPUT); digitalWrite(encoderSwitch, HIGH); attachInterrupt(1, menuClick, RISING); pinMode(enablePin, OUTPUT); pinMode(stepPin, OUTPUT); pinMode(dirPin, OUTPUT); pinMode(runPin, INPUT); pinMode(stopPin, INPUT); resetLcd(); enableStepper(false); } void enableStepper(boolean on) { if (on) { digitalWrite(enablePin, LOW); } else { digitalWrite(enablePin, HIGH); } delay(2); } void setDirection(boolean clockWise) { if (clockWise) { digitalWrite(dirPin, LOW); } else { digitalWrite(dirPin, HIGH); } delay(2); } void moveSteps(int steps) { for(int i = 0; i < steps; i++) { digitalWrite(stepPin, LOW); delayMicroseconds(stepDelayInMicroS); digitalWrite(stepPin, HIGH); delayMicroseconds(stepDelayInMicroS); digitalWrite(stepPin, LOW); delayMicroseconds(stepDelayInMicroS); } } void returnToStartPos() { noInterrupts(); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print("Moving..."); analogInput = analogRead(stopPin); delay(2); setDirection(false); enableStepper(true); while (map(analogInput, 0, 1023, LOW, HIGH) == LOW) { moveSteps(stepsPrMM); analogInput = analogRead(stopPin); delay(2); } enableStepper(false); delay(1000); moveForward(1); subMenuShowing = false; currentSubMenuItem = -1; resetMenu(); drawMenu(); interrupts(); } void moveForward(float _mm) { int steps = _mm * factor * stepsPrMM; setDirection(true); enableStepper(true); moveSteps(steps); enableStepper(false); } void handleMoveForward() { int i, j; i = ceil(gapSize / toolSize); j = 0; delay(50); noInterrupts(); lcd.clear(); lcd.print("Moving..."); float tmp = max(gapSize, toolSize); while (tmp > 0) { j++; lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(j); lcd.print(" of "); lcd.print(i); moveForward(min(toolSize, tmp)); tmp -= toolSize; tmp = tmp < 0 ? 0 : tmp; analogInput = analogRead(runPin); delay(2); while (tmp > 0 && map(analogInput, 0, 1023, LOW, HIGH) == LOW) { analogInput = analogRead(runPin); delay(2); } } interrupts(); resetLcd(); } void loop() { while(rotating) { delay(2); if (digitalRead(encoderPinA) == digitalRead(encoderPinB)) { encoderPos += 0.25; } else { encoderPos -= 0.25; } if (encoderPos < 0) { encoderPos = encoderPos + numberOfItems; } if (encoderPos > numberOfItems) { encoderPos = encoderPos - numberOfItems; } tmpInt = floor(encoderPos); if (menuShowing) { if (subMenuShowing == false) { if (tmpInt % numberOfItems != currentMenuItem) { currentMenuItem = tmpInt % numberOfItems; } } else { currentSubMenuItem = tmpInt % numberOfSubMenuItems; } drawMenu(); } rotating = false; } while (menuClicked) { if (digitalRead(encoderSwitch) == HIGH) { handleMenuClicked(); } menuClicked = false; } analogInput = analogRead(runPin); delay(2); if (menuShowing == false && map(analogInput, 0, 1023, LOW, HIGH) == HIGH) { handleMoveForward(); } } void rotEncoder() { rotating = true; } void menuClick() { menuClicked = true; } void handleMenuClicked() { tmpInt = floor(encoderPos); if (menuShowing == false) { resetMenu(); menuShowing = true; currentMenuItem = tmpInt % numberOfItems; currentSubMenuItem = -1; drawMenu(); } else { if (subMenuShowing) { switch(currentSubMenuItem) { case setItem: switch(currentMenuItem) { case setupToolMenuItem: setupTool(); break; case setupGapMenuItem: setupGap(); break; case setZeroMenuItem: returnToStartPos(); break; } break; case cancelItem: currentSubMenuItem = -1; subMenuShowing = false; resetMenu(); drawMenu(); break; } } else { switch(currentMenuItem) { case setupToolMenuItem: currentSubMenuItem = 0; subMenuShowing = true; handleSetupToolMenu(); drawMenu(); break; case setupGapMenuItem: currentSubMenuItem = 0; subMenuShowing = true; handleSetupGapMenu(); drawMenu(); break; case setZeroMenuItem: currentSubMenuItem = 0; subMenuShowing = true; handleSetZeroMenu(); drawMenu(); break; case cancelMenuItem: resetLcd(); currentMenuItem = -1; currentSubMenuItem = -1; encoderPos = 0; menuShowing = false; subMenuShowing = false; break; } } } } void setupTool() { float tmpPos, tmpPos2; lcd.setCursor(0,1); lcd.print(" "); menuClicked = false; tmpPos = 0; tmpPos2 = 0; while (menuClicked == false) { while(rotating) { delay(2); if (digitalRead(encoderPinA) == digitalRead(encoderPinB)) { tmpPos += 0.005; } else { tmpPos -= 0.005; } rotating = false; } if (tmpPos != tmpPos2) { toolSize += tmpPos - tmpPos2; toolSize = toolSize < 0 ? 0 : toolSize; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Size: "); lcd.print(toolSize); lcd.print(" mm"); tmpPos2 = tmpPos; } } int t = round(toolSize * 100); toolSize = (float)t / 100; gapSize = gapSize < toolSize ? toolSize : gapSize; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Size: "); lcd.print(toolSize); lcd.print(" mm"); menuClicked = false; drawMenu(); } void setupGap() { float tmpPos, tmpPos2; int pinA, pinB; lcd.setCursor(0,1); lcd.print(" "); menuClicked = false; tmpPos = 0; tmpPos2 = 0; while (menuClicked == false) { while(rotating) { delay(2); if (digitalRead(encoderPinA) == digitalRead(encoderPinB)) { tmpPos += 0.005; } else { tmpPos -= 0.005; } rotating = false; } if (tmpPos != tmpPos2) { gapSize += tmpPos - tmpPos2; gapSize = gapSize < toolSize ? toolSize : gapSize; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Gap: "); lcd.print(gapSize); lcd.print(" mm"); tmpPos2 = tmpPos; } } int t = round(gapSize * 100); gapSize = (float)t / 100; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Gap: "); lcd.print(gapSize); lcd.print(" mm"); menuClicked = false; drawMenu(); } void handleSetupToolMenu() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Size: "); lcd.print(toolSize); lcd.print(" mm"); } void handleSetupGapMenu() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Gap: "); lcd.print(gapSize); lcd.print(" mm"); } void handleSetZeroMenu() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Got to zero?"); } void resetLcd() { lcd.clear(); lcd.print("Ready..."); lcd.setCursor(0, 1); } void resetMenu() { lcd.clear(); lcd.print("Menu:"); lcd.setCursor(0, 1); } void drawMenu() { lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); if (menuShowing) { if (subMenuShowing) { switch(currentSubMenuItem) { case setItem: lcd.print("Set"); break; case cancelItem: lcd.print("Exit"); break; } } else { switch(currentMenuItem) { case setupToolMenuItem: lcd.print("Setup tool"); break; case setupGapMenuItem: lcd.print("Setup gap"); break; case setZeroMenuItem: lcd.print("Goto zero"); break; case cancelMenuItem: lcd.print("Exit"); break; } } } }