#include #include #define maxItemSize 10 #define pump011 6 #define pump012 7 #define pump021 4 #define pump022 5 #define pump031 0 #define pump032 1 #define stpXdir 12 #define stpXstp 11 #define stpMdir 10 #define stpMstp 9 #define limitX A0 #define limitM A1 #define motor1 A2 #define motor2 A3 const int stepsPerRevolution = 200; LiquidCrystal_I2C lcd(0x27, 16, 2); static int pinA = 2; // Our first hardware interrupt pin is digital pin 2 static int pinB = 3; // Our second hardware interrupt pin is digital pin 3 static int enSW = 8; volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set) volatile uint16_t encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255 volatile uint16_t oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor) volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent const int itemsPerScreen = 2; //Declare the Menus you need. char menu[][maxItemSize] = {"Juice", "Mix ", " "}; // Only 2 sub-menus are shown. You can add as many as you wish. char subMenu0[][maxItemSize] = {"Orange", "Lemon ", "Mango ", "BACK "}; char subMenu1[][maxItemSize] = {"Mokheto", "Mix2 ", "Mix3 ", "BACK "}; int cnt = 0; int itemSelected, subMenuSelected; int itemsToDisplay = 0; void PinA() { cli(); //stop interrupts happening before we read pin values reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge encoderPos --; //decrement the encoder's position count bFlag = 0; //reset flags for the next turn aFlag = 0; //reset flags for the next turn } else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation sei(); //restart interrupts } void PinB() { cli(); //stop interrupts happening before we read pin values reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge encoderPos ++; //increment the encoder's position count bFlag = 0; //reset flags for the next turn aFlag = 0; //reset flags for the next turn } else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation sei(); //restart interrupts } void setup() { // display.begin(); pinMode(enSW, INPUT_PULLUP); pinMode(PinA, INPUT_PULLUP); pinMode(PinB, INPUT_PULLUP); pinMode(limitX, INPUT_PULLUP); pinMode(limitM, INPUT_PULLUP); pinMode(stpXdir, OUTPUT); pinMode(stpXstp, OUTPUT); pinMode(stpMdir, OUTPUT); pinMode(stpMstp, OUTPUT); pinMode(motor1, OUTPUT); pinMode(motor2, OUTPUT); pinMode(pump011, OUTPUT); pinMode(pump012, OUTPUT); pinMode(pump021, OUTPUT); pinMode(pump022, OUTPUT); pinMode(pump031, OUTPUT); pinMode(pump032, OUTPUT); attachInterrupt(0, PinA, RISING); attachInterrupt(1, PinB, RISING); Serial.begin(115200); lcd.init(); // initialize the lcd // Print a message to the LCD. lcd.backlight(); lcd.setCursor(1, 0); lcd.print("Hello, Welcome!"); lcd.setCursor(0, 1); lcd.print("To MOAO Cocktail"); homing(); } void loop() { // Enter the settings menu if select Switch is pressed if (digitalRead(enSW) == 0) { while (digitalRead(enSW) == 0); //wait till switch is released. lcd.clear(); itemSelected = displayMenu(menu, sizeof(menu) / maxItemSize); switch (itemSelected) { case 0: // juice is choosen Serial.print("calling submenu"); subMenuSelected = displayMenu(subMenu0, sizeof(subMenu0) / maxItemSize); switch (itemSelected) { case 0: // Mango pump1(); break; case 1: pump2(); break; case 2: pump3(); break; } break; case 1: // Mix is choosen subMenuSelected = displayMenu(subMenu1, sizeof(subMenu1) / maxItemSize); switch (itemSelected) { case 0: mix1(); break; case 1: // mix2(); break; case 2: //mix3(); break; } break; //you may include other cases as required! default: break; } } } // This function accepts the a 2D character array and its length and display it on the screen. // The function montiers the encoder position and moves the menu up and down. // It returns the selected menu option to the calling functions int displayMenu(char menuInput[][maxItemSize], int menuLength) { int curPos, startPos, endPos; do { startPos = encoderPos % menuLength; Serial.print("startPos: "); Serial.println(startPos); lcd.setCursor(0, 0); // clear, er3sh // lcd.clear(); endPos = itemsPerScreen; if (menuLength < itemsPerScreen) { endPos = menuLength - startPos; } if ((menuLength - startPos) < itemsPerScreen) { endPos = menuLength - startPos; } Serial.print("endPos:"); Serial.println(endPos); for (cnt = 0; cnt <= (endPos - 1); cnt++) { if (cnt == 0) { lcd.setCursor(0, 0); lcd.print("->"); } //display.setCursor(16, cnt * fontSize); //display.println(menuInput[cnt + startPos]); lcd.setCursor(2, cnt); lcd.print(menuInput[cnt + startPos]); Serial.println(menuInput[cnt + startPos]); } cnt = 0; if (oldEncPos != encoderPos) { oldEncPos = encoderPos; } } while (digitalRead(enSW)); while (digitalRead(enSW) == 0); //wait till switch is reseleased lcd.clear(); return startPos; } void rotateX(int dir, int rev) { // Set motor direction clockwise digitalWrite(stpXdir, dir); for (int i = 0; i < rev; i++) { // Spin motor one revolution for (int x = 0; x < stepsPerRevolution; x++) { digitalWrite(stpXstp, HIGH); delayMicroseconds(600); digitalWrite(stpXstp, LOW); delayMicroseconds(600); } } } void rotateM(int dir, int rev) { // Set motor direction clockwise digitalWrite(stpMdir, dir); for (int i = 0; i < rev; i++) { // Spin motor one revolution for (int x = 0; x < stepsPerRevolution; x++) { digitalWrite(stpMstp, HIGH); delayMicroseconds(800); digitalWrite(stpMstp, LOW); delayMicroseconds(800); } } } void pump1() { // move stepper specific cm rotateX(1, 1); //pump1 working digitalWrite(pump011, HIGH); delay(5000); digitalWrite(pump011, LOW); // move stepper to home homing(); } void pump2() { // move stepper specific cm rotateX(1, 3); //pump1 working digitalWrite(pump021, HIGH); delay(5000); digitalWrite(pump021, LOW); // move stepper to home homing(); } void pump3() { // move stepper specific cm rotateX(1, 5); //pump1 working digitalWrite(pump031, HIGH); delay(5000); digitalWrite(pump031, LOW); // move stepper to home homing(); } void mix1() { // move stepper specific cm rotateX(1, 7); //pump3 working digitalWrite(pump031, HIGH); delay(1000); digitalWrite(pump031, LOW); // move stepper to pump2 rotateX(0, 3); //pump2 working digitalWrite(pump021, HIGH); delay(1000); digitalWrite(pump021, LOW); // move stepperX to mixer rotateX(1, 10); // move stepperM down rotateM(1, 5); digitalWrite(motor1, HIGH); digitalWrite(motor2, LOW); delay(2000); digitalWrite(motor1, LOW); digitalWrite(motor2, LOW); // move stepperM up rotateM(1, 5); homing(); } void homing() { while (digitalRead(limitX) == HIGH) { rotateX(1, 1); } while (digitalRead(limitM) == HIGH) { rotateM(0, 2); } }