Rotary switch to control the menu on lcd display 16x2

Previously, I used an adkeyboard to control a stepper motor on an LCD display. Now, I want to modify the following code to use a rotary encoder to operate the menu. This is my first time using a rotary switch to control the menu. Please teach me how to do it. Thank you. I am using an Arduino Uno, a 16x2 LCD display, and a rotary encoder.

#include <Encoder.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <AccelStepper.h>
#include <SoftwareSerial.h>

#define DEFAULT_SUBSTATE 0
#define SETUP_SUBSTATE 2
#define PROCESS_SUBSTATE 3
#define WAITING_SUBSTATE 4

#define GO_HOME_STATE 0
#define IDLE_STATE 1
#define START_STATE 69
#define SETTING_STATE 2
#define STOP_STATE 70

#define NOTHING 0
#define UP 1
#define DOWN 2
#define SELECT 3

// Function prototypes
void processCommand(char command);
void rotaryInterrupt();
void setupMenu();
void updateLCD();

// Rotary Encoder Pins
int encoderDTpin = 2;
int encoderCLKpin = 3;
Encoder myEnc(encoderDTpin, encoderCLKpin);
volatile long newPosition = 0;

const int stepPin = 5;
const int dirPin = 2;
const int enPin = 8;
const int limitSwitchPin = 10;
int motorIsMoving = LOW;
int mainState = GO_HOME_STATE;
int subState = DEFAULT_SUBSTATE;
int homeIsNotSet = false;
int manualSetting = 0;
int targetProbePosition = 0;

AccelStepper stepper(1, stepPin, dirPin);
LiquidCrystal_I2C lcd(0x27, 16, 2);

bool isMoving = false;
#define rxPin 9
#define txPin 11

// Set up a new SoftwareSerial object
SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);

void setup() {
  Serial.begin(9600);

  // Define pin modes for TX and RX
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);

  // Set the baud rate for the SoftwareSerial object
  mySerial.begin(9600);

  pinMode(enPin, OUTPUT); //for stepper motor enable pin
  digitalWrite(enPin, LOW); // set low to Enable the stepper motor driver
  pinMode(limitSwitchPin, INPUT_PULLUP);
  digitalWrite(limitSwitchPin, HIGH); // pullup high

  stepper.setMaxSpeed(4000.0); // Set maximum speed in steps per second
  stepper.setAcceleration(2000.0); // Set acceleration in steps per second per second

  lcd.backlight();
  lcd.init();
  lcd.begin(16, 2);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CP:"); //current position
  lcd.setCursor(0, 1);
  lcd.print(stepper.currentPosition());

  mainState = GO_HOME_STATE;
  subState = SETUP_SUBSTATE;

  // Set up rotary encoder interrupt
  attachInterrupt(digitalPinToInterrupt(encoderCLKpin), rotaryInterrupt, CHANGE);
}

void loop() {
  updateLCD(); // Update the LCD display
  if (mySerial.available() > 0) {
    char command = mySerial.read();
    processCommand(command);
  }

  if (mainState == GO_HOME_STATE) {
    if( subState == SETUP_SUBSTATE )
    {
      lcd.setCursor(9, 0);
      lcd.print("S HOME");//setting home
      subState = DEFAULT_SUBSTATE;
    }
    if( manualSetting == SELECT )
    {
      if( homeIsNotSet == false )
      {
        stepper.setSpeed(-1000);
        stepper.runSpeed();
        homeIsNotSet = false;
        if( digitalRead(limitSwitchPin) == LOW )
        {
          homeIsNotSet = true;
          stepper.setCurrentPosition(0); //reset the position to zero
          stepper.stop();
        }
      }
      else if ( homeIsNotSet == true )
      {
        stepper.moveTo(1000); // Adjust the distance as needed
        stepper.runToPosition();
        manualSetting = NOTHING;
        mainState = IDLE_STATE;
        subState = SETUP_SUBSTATE;
      }
    }
  } else if (mainState == IDLE_STATE) {
    if( subState == SETUP_SUBSTATE )
    {
      lcd.setCursor(9, 0);
      lcd.print("M Menu");// main menu
      subState = DEFAULT_SUBSTATE;
    }
  } else if (mainState == SETTING_STATE) {
    if( subState == SETUP_SUBSTATE )
    {
      lcd.setCursor(9, 0);
      lcd.print("Set PP");//set probe position
      subState = DEFAULT_SUBSTATE;
    }
    if( manualSetting == UP )
    {
      manualSetting = NOTHING;
      stepper.moveTo(stepper.currentPosition() - 100); // Adjust the distance as needed
      stepper.runToPosition();
      manualSetting = false;
    }
    else if ( manualSetting == DOWN )
    {
      manualSetting = NOTHING;
      stepper.moveTo(stepper.currentPosition() + 100); // Adjust the distance as needed
      stepper.runToPosition();
    }
    else if ( manualSetting == SELECT )
    {
      manualSetting = NOTHING;
      targetProbePosition = stepper.currentPosition();
      lcd.setCursor(8, 1);
      lcd.print("set:");
      lcd.print(targetProbePosition);
      stepper.moveTo(1000); // Adjust the distance as needed
      stepper.runToPosition();
    }
  } else if (mainState == START_STATE) {
   if( subState == SETUP_SUBSTATE )
    {
      lcd.setCursor(9, 0);
      lcd.print("S Test");//start test
      subState = PROCESS_SUBSTATE;
    }
    else if( ( subState == PROCESS_SUBSTATE) && ( targetProbePosition != 0 ) )
    {
      //move to targetProbePosition
      subState = WAITING_SUBSTATE;
      manualSetting = NOTHING;
      stepper.moveTo(targetProbePosition); // Adjust the distance as needed
      stepper.runToPosition();
    }
    else if( subState == WAITING_SUBSTATE )
    {
      if( stepper.currentPosition() >= targetProbePosition - 5 )
      {
        subState = DEFAULT_SUBSTATE;
        manualSetting = NOTHING;
        lcd.setCursor(10, 1);
        lcd.print("T Ready");//taegr ready
        mySerial.println("b");
      }
    }
  } else if (mainState == STOP_STATE) {
    if( subState == SETUP_SUBSTATE )
    {
      lcd.setCursor(0, 0);
      lcd.print("Stop t");//stop test
      subState = PROCESS_SUBSTATE;
    }
    if( ( subState == PROCESS_SUBSTATE ) && ( targetProbePosition != 0 ) )
    {
      //move to targetProbePosition
      subState = DEFAULT_SUBSTATE;
      manualSetting = NOTHING;
      stepper.moveTo(1000); // Adjust the distance as needed
      stepper.runToPosition();
      lcd.setCursor(9, 1);
      lcd.print("A Home");  //at home    
    }
  }

  if ((digitalRead(limitSwitchPin) == LOW) && (mainState != GO_HOME_STATE)) {
    stepper.stop();
    mySerial.println("e");
  }
}

void rotaryInterrupt() {
  long newEncPosition = myEnc.read();
  if (newEncPosition != newPosition) {
    newPosition = newEncPosition;
    if (newPosition > myEnc.read()) {
      manualSetting = DOWN;
    } else {
      manualSetting = UP;
    }
  }
}

void updateLCD() {
  lcd.setCursor(0, 1);
  lcd.print(stepper.currentPosition());
  lcd.print("");
}

void processCommand(char command) {
  switch (command) {
    case 'a':
      mainState = START_STATE;
      subState = SETUP_SUBSTATE;
      manualSetting = NOTHING;
      Serial.println("Moving to Probe");
      break;

    case 'c':
      mainState = STOP_STATE;
      subState = SETUP_SUBSTATE;
      manualSetting = NOTHING;
      Serial.println("Moving to Home");
      break;

    case 'b':
      Serial.println("platform touch probe");
      break;

    case 'e':
      Serial.println("emergency stop");
      break;
  }
}

I moved your topic to an appropriate forum category @ansonnai.

In the future, please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

what arduino are you using?
does the encoder work? e.g. tested with one of the examples from the library

once it is working

  1. have a char array which contains the menu items
  2. on startup output to the LCD sufficient menu items to fill the display
  3. as you rotate the the QEI switch move a cursor up and down the displayed items
  4. a switch press selects the menu item
  5. as you rotate the switch when the cursor reaches the top/bottom of the screen you clear the LCD and display the offset menu items

recommend you implement a program to test the menu operation without sensors etc
when it is working add sensors etc

edit: also be worth looking at Arduino LCD menu - may give you some ideas

You have a declaration of conflicting pins:
line 30: int encoderDTpin = 2;
line 36: const int dirPin = 2;

The same pin declared for different devices.

This is affecting your function: rotaryInterrupt() called by
encoder action.

Use another pin for : const int dirPin , because encoderDTpin require interrupt pin.

im using arduino uno R3

https://www.youtube.com/watch?v=Hd-iQXCqmWU

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.