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;
}
}