Hello Larry.
So in relation to:
I believe i have resolved this one with the code below.
//================================================^================================================
//
// https://forum.arduino.cc/t/model-railway-turntable-in-a-spin-so-much-im-dizzy/1263988
//
// HLD
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================================
// 1.00 24/05/25 Started writing sketch
// 1.10 24/05/25 Added code to read the Rotary Encoder
// 1.20 24/05/25 Added Stepping Motor code
// 1.30 24/05/27 Added the State Machine named "resetMachine"
// 1.40 24/05/27 Added Homing after zeroing the motor
// 1.50 24/05/27 Added LED effects when Zeroing and Homing
// 1.60 24/05/27 When the motor stops stepping, turn off motor coil currents
// 1.70 24/05/27 Added LED action when calibrating the Motor position
// 1.80 24/05/28 Added added debug macros, added some sketch comments
//
//#include <Wire.h>
// M A C R O S
//================================================^================================================
#define LEDon HIGH //PIN---[220R]---A[LED]K---GND
#define LEDoff LOW
#define PRESSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED HIGH
#define CLOSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define OPENED HIGH
#define OPTOclosed HIGH //use with "HIGH when closed" opto devices
#define OPTOopened LOW //use with "LOW when open" opto devices
//======================================================================== <-------<<<<<<<
//these macros are used for debug purposes
//
#define DEBUG //comment this line to stop printing to the Serial Monitor,
// less memory used, speeds execution. i.e. all Serial.print... lines are deleted
//debug Macros
#ifdef DEBUG
#define SERIALBEGIN(...) Serial.begin(__VA_ARGS__)
#define DPRINT(...) Serial.print(__VA_ARGS__)
#define DPRINTLN(...) Serial.println(__VA_ARGS__)
#define DPRINTF(...) Serial.print(F(__VA_ARGS__)) //text only, using the F macro
#define DPRINTLNF(...) Serial.println(F(__VA_ARGS__)) //text only, using the F macro plus new line
#else
#define SERIALBEGIN(...)
#define DPRINT(...)
#define DPRINTLN(...)
#define DPRINTF(...)
#define DPRINTLNF(...)
#endif
// G P I O s
//================================================^================================================
//
//a structure to define input objects, switches or sensors
struct makeInput {
const byte pin; //the digital input pin number
unsigned long switchTime; //the time the switch was closed
byte lastState; //the state the input was last in
byte counter; //a counter used to validate a switch change in state
}; //END of struct makeInput
const byte inputPins[] = { 4, 14, 15, 16, 17 };
//Digital Inputs
//define the input connected to a PB switch
//========================
makeInput EncoderSw = {
4, 0, OPENED, 0 //pin, switchTime, lastState, counter
};
//========================
makeInput DeleteSw = {
14, 0, OPENED, 0 //pin, switchTime, lastState, counter
};
//========================
makeInput SetPosSw = {
15, 0, OPENED, 0 //pin, switchTime, lastState, counter
};
//========================
makeInput CCW_Sw = {
16, 0, OPENED, 0 //pin, switchTime, lastState, counter
};
//========================
makeInput CW_Sw = {
17, 0, OPENED, 0 //pin, switchTime, lastState, counter
};
//========================
makeInput OptoSensor = {
18, 0, OPTOopened, 0 //pin, switchTime, lastState, counter
};
byte filter = 10;
//TIMER "switches" runs every 5ms.
//5ms * 10 = 50ms is needed to validate a switch change in state.
//A switch change in state is valid "only after" 10 identical changes are detected.
//This is used to filter out EMI noise in the system
const byte EncoderOutA = 3; //there is a pull-up resistor inside the rotary encoder
const byte EncoderOutB = 2; //there is a pull-up resistor inside the rotary encoder
//OUTPUTS
//===================================
const byte outputPins[] = { 13, 12, 11, 10, 9, 8, 7, 6, 5 };
const byte heartbeatLED = 13;
const byte cwLED = 12;
const byte ccwLED = 11;
const byte deleteLED = 10;
const byte setPosLED = 9;
//stepping motor
const byte IN4 = 8;
const byte IN3 = 7;
const byte IN2 = 6;
const byte IN1 = 5;
// V A R I A B L E S
//================================================^================================================
//
// "Setpping Motor" 2 8 B Y J - 4 8
//a 5-wire unipolar stepper motor that runs on 5V
//
//Stepping Motor stepping pattern
//index 0 1 2 3 4 5 6 7 8
int lookup[] = { B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001, B00000 };
//index 8 in the array is B00000
//we use this step pattern to turn off the motor current when the motor is stopped
//Stepper Motor inputs
// IN1, Bit 0 _____
// IN2, Bit 1 ____ |
// IN3, Bit 2 ___ ||
// IN4, Bit 3 __ |||
// ||||
//ex. step pattern B01000
//IN1 is bit 0
//IN2 is bit 1
//IN3 is bit 2
//IN4 is bit 3
//where we are pointing to in the above array
int stepIndex = 0; //where we are in the Look-Up table
int savedStepIndex; //a copy of stepIndex when powering off the motor
byte homeFlashCounter; //used in flshing the LEDs at the HOME position
int EncoderCounter;
int homingCounter = 0; //number of steps away from the motor zero position
long currentMotorPosition = 0; //number of steps away from the HOME position
const int homeSteps = 100; //number of CW steps from the motor zero position
const unsigned long motorSpeed = 2400ul; //larger the number, slower the the motor movement
const unsigned long CW_CCW_Interval = 5000ul; //5 seconds to verify if CW and CCW still being held
//================================================^================================================
// millis() / micros() B a s e d T I M E R S
//================================================^================================================
//TIMER objects are non-blocking
struct makeTIMER {
#define MILLIS 1
#define MICROS 1000 //we can use this value to divide into a variable to get milliseconds
#define ENABLED true
#define DISABLED false
#define YES true
#define NO false
#define STILLtiming 0
#define EXPIRED 1
#define TIMERdisabled 2
//these are the bare minimum "members" needed when defining a TIMER
int TimerType; //what kind of TIMER is this? MILLIS/MICROS
unsigned long Time; //when the TIMER started
unsigned long Interval; //delay time which we are looking for
bool TimerFlag; //is the TIMER enabled ? ENABLED/DISABLED
bool Restart; //do we restart this TIMER ? YES/NO
//================================================
//condition returned: STILLtiming (0), EXPIRED (1) or TIMERdisabled (2)
//function to check the state of our TIMER ex: if(myTimer.checkTIMER() == EXPIRED);
byte checkTIMER() {
//========================
//is this TIMER enabled ?
if (TimerFlag == ENABLED) {
//========================
//has this TIMER expired ?
if (getTime() - Time >= Interval) {
//========================
//should this TIMER restart again?
if (Restart == YES) {
//restart this TIMER
Time = getTime();
}
//this TIMER has expired
return EXPIRED;
}
//========================
else {
//this TIMER has not expired
return STILLtiming;
}
} //END of if (TimerFlag == ENABLED)
//========================
else {
//this TIMER is disabled
return TIMERdisabled;
}
} //END of checkTime()
//================================================
//function to enable and restart this TIMER ex: myTimer.enableRestartTIMER();
void enableRestartTIMER() {
TimerFlag = ENABLED;
//restart this TIMER
Time = getTime();
} //END of enableRestartTIMER()
//================================================
//function to disable this TIMER ex: myTimer.disableTIMER();
void disableTIMER() {
TimerFlag = DISABLED;
} //END of disableTIMER()
//================================================
//function to restart this TIMER ex: myTimer.restartTIMER();
void restartTIMER() {
Time = getTime();
} //END of restartTIMER()
//================================================
//function to force this TIMER to expire ex: myTimer.expireTimer();
void expireTimer() {
//force this TIMER to expire
Time = getTime() - Interval;
} //END of expireTimer()
//================================================
//function to set the Interval for this TIMER ex: myTimer.setInterval(100);
void setInterval(unsigned long value) {
//set the Interval
Interval = value;
} //END of setInterval()
//================================================
//function to return the current time
unsigned long getTime() {
//return the time i.e. millis() or micros()
//========================
if (TimerType == MILLIS) {
return millis();
}
//========================
else {
return micros();
}
} //END of getTime()
}; //END of struct makeTIMER
// D e f i n e a l l t h e T I M E R S
//================================================^================================================
/*example
//========================
makeTIMER toggleLED =
{
MILLIS/MICROS, 0, 500ul, ENABLED/DISABLED, YES/NO //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
Functions we can access:
toggleLED.checkTIMER();
toggleLED.enableRestartTIMER();
toggleLED.disableTIMER();
toggleLED.expireTimer();
toggleLED.setInterval(100ul);
*/
//========================
makeTIMER heartbeatTIMER = {
MILLIS, 0, 500ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER switchesTIMER = {
MILLIS, 0, 5ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER encoderTIMER = {
MILLIS, 0, 2ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER machineTIMER = {
MILLIS, 0, 5ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER resetCommonTIMER = {
MILLIS, 0, 1000ul, DISABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER stepperTIMER = {
MICROS, 0, motorSpeed, DISABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER deleteLedTIMER = {
MILLIS, 0, 100ul, DISABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
// S t a t e M a c h i n e
//================================================^================================================
//the States in our machine (use names that mean something to you)
enum STATES : byte //save RAM, use bytes
{
ResetStartup, //do power up stuff
Check_CW_CCW_Sw, //checking to see if CW and CCW are closed
CW_CCW_Timing, //wait to see if the switches have been closed long enough
ResetMotor, //wait here while motor is going CCW and looking for Opto Sensor
MovingHome, //set up things to home the motor
HomingWait, //wait here while the motor is homing, waiting for the Opto Sensor to close
ResetFinished //flash LEDs, reset the "Reset State Machine"
};
STATES resetMachine = ResetStartup;
// s e t u p ( )
//================================================^================================================
void setup() {
//SERIALBEGIN(115200);
Serial.begin(115200);
//some time to get serial stuff working
//delay(1000);
//======================
//use INPUT_PULLUP so the pin does not float, floating pins can cause faulty readings
//configure the input pins
for (byte x = 0; x < sizeof(inputPins); x++) {
pinMode(inputPins[x], INPUT_PULLUP);
}
//======================
//configure the output pins
for (byte x = 0; x < sizeof(outputPins); x++) {
digitalWrite(outputPins[x], LOW);
pinMode(outputPins[x], OUTPUT);
}
DPRINTLNF("Power Up");
} //END of setup()
// l o o p ( )
//================================================^================================================
void loop() {
//======================================================================== T I M E R heartbeat
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
//if the TIMER is enabled, is it time to toggle the heartbeat LED ?
if (heartbeatTIMER.checkTIMER() == EXPIRED) {
//when this TIMER expires, toggle the heartbeat LED
//this LED is a rudimentary way of displaying if the sketch code is blocking or stuttering
//toggle the heartbeat LED
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== T I M E R switches
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
//if the TIMER is enabled, is it time to check our switches ?
if (switchesTIMER.checkTIMER() == EXPIRED) {
//when this TIMER expires, check if any switch/sensor has changed state
checkSwitches();
}
//======================================================================== T I M E R encoder
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
//if the TIMER is enabled, is it time to read the Rotary Encoder ?
if (encoderTIMER.checkTIMER() == EXPIRED) {
//when this TIMER expires, check the rotary encode to see if it has been turned
readRotaryEncoder();
}
//======================================================================== T I M E R machine
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
//if the TIMER is enabled, is it time to service our State Machines ?
if (machineTIMER.checkTIMER() == EXPIRED) {
//when this TIMER expires, service any/all the State Machines
//check all the "State Machines"
checkMachines();
}
//======================================================================== T I M E R stepper
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
//if the TIMER is enabled, is it time to move the Stepping Motor ?
if (stepperTIMER.checkTIMER() == EXPIRED) {
//when this TIMER expires, step the motor
//there are 4 exclusionary events that move the stepper motor
//i.e. only one event can be operated on at a time
// 1. HomingWait: Motor going HOME
// 2. ResetMotor: Motor going to ZERO
// 3. CW switch closed: Motor going CW
// 4. CCW switch closed: Motor going CCW
//======================== H o m i n g W a i t
//are we waiting for the motor to home ?
if (resetMachine == HomingWait) {
//get ready for the next step
stepIndex++;
//should we go back to the beginning index ?
if (stepIndex > 7) {
stepIndex = 0;
}
//move the motor
stepMotor(stepIndex);
//we have gone 1 more CW step
homingCounter++;
//DPRINTLN(homingCounter);
//========================
//are we finished homing ?
if (homingCounter >= homeSteps) {
//motor is now sitting at HOME
currentMotorPosition = 0;
//setting up toggling of the LEDs every 500ms
homeFlashCounter = 0;
//LED toggle duration is 500ms
resetCommonTIMER.setInterval(500ul);
//restart the common TIMER
resetCommonTIMER.enableRestartTIMER();
//all LEDs OFF
digitalWrite(cwLED, LEDoff);
digitalWrite(ccwLED, LEDoff);
digitalWrite(deleteLED, LEDoff);
digitalWrite(setPosLED, LEDoff);
//we are at HOME, reset the "Reset State Machine"
resetMachine = ResetFinished;
//save the current stepIndex
savedStepIndex = stepIndex;
//to save power, turn off stepper coils
stepIndex = 8;
stepMotor(stepIndex);
//we are done, disable this TIMER
stepperTIMER.disableTIMER();
}
}
//======================== R e s e t M o t o r
//are we resetting the motor position to zero ?
else if (resetMachine == ResetMotor) {
//get ready for the next step
stepIndex--;
//should we go back to the ending index ?
if (stepIndex < 0) {
stepIndex = 7;
}
//move the motor
stepMotor(stepIndex);
//========================
//has the OptoSensor gone CLOSED ?
if (OptoSensor.lastState == OPTOclosed) {
//we are at position ZERO
currentMotorPosition = 0;
//it is now time to HOME the motor
//next state in the "Reset State Machine"
resetMachine = MovingHome;
//we are done, disable this TIMER
stepperTIMER.disableTIMER();
}
}
//======================== C W s w i t c h c l o s e d
//when the CW switch is closed AND the CCW switch is OPENED
else if (CW_Sw.lastState == CLOSED && CCW_Sw.lastState == OPENED) {
//get ready for the next step
stepIndex++;
//should we go back to the beginning index ?
if (stepIndex > 7) {
stepIndex = 0;
}
//move the motor
stepMotor(stepIndex);
//advance the Motor Position
currentMotorPosition++;
DPRINTLN(currentMotorPosition);
}
//======================== C C W s w i t c h c l o s e d
//when the CCW switch is closed AND the CW switch is OPENED
else if (CCW_Sw.lastState == CLOSED && CW_Sw.lastState == OPENED) {
//get ready for the next step
stepIndex--;
//should we go back to the ending index ?
if (stepIndex < 0) {
stepIndex = 7;
}
//move the motor
stepMotor(stepIndex);
//reduce the Motor Position
currentMotorPosition--;
DPRINTLN("Distance from Home Position = ");
DPRINTLN(currentMotorPosition);
}
}
//======================================================================== T I M E R deleteLed
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
//if the TIMER is enabled, is it time to toggle the Delete LED ?
if (deleteLedTIMER.checkTIMER() == EXPIRED) {
//toggle the Delete LED
digitalWrite(deleteLED, digitalRead(deleteLED) == HIGH ? LOW : HIGH);
}
//================================================
//other non blocking code goes here
//================================================
} //END of loop()
// c h e c k M a c h i n e s ( )
//================================================^================================================
void checkMachines() {
//======================================================================== "Reset State Machine"
switch (resetMachine) {
//======================== R e s e t S t a r t u p
case ResetStartup:
{
//do startup stuff here
//next state in the "Reset State Machine"
resetMachine = Check_CW_CCW_Sw;
}
break;
//================================================ <-------<<<<<<<
//When the mortor is stopped,
//this State Machine will sit
//in this state
//======================== C h e c k _ C W _ C C W _ S w
case Check_CW_CCW_Sw:
{
//are both CW and CCW switches CLOSED ?
if (digitalRead(CW_Sw.pin) == CLOSED && digitalRead(CCW_Sw.pin) == CLOSED) {
DPRINTLNF("Both switches are closed");
//disable any motor movement
stepperTIMER.disableTIMER();
resetCommonTIMER.setInterval(CW_CCW_Interval);
resetCommonTIMER.enableRestartTIMER();
//next state in the "Reset State Machine"
resetMachine = CW_CCW_Timing;
}
}
break;
//======================== C W _ C C W _ T i m i n g
case CW_CCW_Timing:
{
//has a switch been released ?
if (digitalRead(CW_Sw.pin) == OPENED || digitalRead(CCW_Sw.pin) == OPENED) {
digitalWrite(cwLED, LEDoff);
digitalWrite(ccwLED, LEDoff);
//back to checking for the 2 switches CLOSED
//next state in the "Reset State Machine"
resetMachine = Check_CW_CCW_Sw;
break;
}
//has the TIMER expired ?
if (resetCommonTIMER.checkTIMER() == EXPIRED) {
//during motor zeroing, turn ON the LEDs
digitalWrite(cwLED, LEDon);
digitalWrite(ccwLED, LEDon);
digitalWrite(deleteLED, LEDon);
digitalWrite(setPosLED, LEDon);
//restore the saved stepIndex
stepIndex = savedStepIndex;
stepMotor(stepIndex);
//allow the motor to move
stepperTIMER.enableRestartTIMER();
//next state in the "Reset State Machine"
resetMachine = ResetMotor;
}
}
break;
//======================== R e s e t M o t o r
case ResetMotor:
{
//wait here until the motor is at the zero position
}
break;
//======================== M o v i n g H o m e
case MovingHome:
{
DPRINTLNF("Motor is at Zero");
DPRINTLNF("Motor is now Homing");
//start out at the first element on our Lookup table
stepIndex = 0;
//initialize the number of steps away from the motor zero position
homingCounter = 0;
//allow the motor to move
stepperTIMER.enableRestartTIMER();
//next state in the "Reset State Machine"
resetMachine = HomingWait;
}
break;
//======================== H o m i n g W a i t
case HomingWait:
{
//wait here while homing the motor
}
break;
//======================== R e s e t F i n i s h e d
case ResetFinished:
{
//we are at the Motor Home position, toggle the LEDs
if (homeFlashCounter < 4) {
//has the common TIMER expired ?
if (resetCommonTIMER.checkTIMER() == EXPIRED) {
//toggle the LEDs
digitalWrite(cwLED, digitalRead(cwLED) == HIGH ? LOW : HIGH);
digitalWrite(ccwLED, digitalRead(ccwLED) == HIGH ? LOW : HIGH);
digitalWrite(deleteLED, digitalRead(deleteLED) == HIGH ? LOW : HIGH);
digitalWrite(setPosLED, digitalRead(setPosLED) == HIGH ? LOW : HIGH);
//ready next flash
homeFlashCounter++;
}
break;
}
//all LEDs OFF
digitalWrite(cwLED, LEDoff);
digitalWrite(ccwLED, LEDoff);
digitalWrite(deleteLED, LEDoff);
digitalWrite(setPosLED, LEDoff);
//we are now finished with motor calibration
DPRINTLNF("Motor is Home");
DPRINTLNF("System has Reset");
//reset this State Machine
//next state in the "Reset State Machine"
resetMachine = ResetStartup;
}
break;
} //END of switch/case
} //END of checkMachines()
// c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches() {
byte currentState;
//======================================================================== EncoderSw.pin
currentState = digitalRead(EncoderSw.pin);
//===================================
//has this switch changed state ?
if (EncoderSw.lastState != currentState) {
EncoderSw.counter++;
//is this change in state stable ?
if (EncoderSw.counter >= filter) {
//get ready for the next sequence
EncoderSw.counter = 0;
//update to this new state
EncoderSw.lastState = currentState;
//========================
//did this switch close ?
if (currentState == CLOSED) {
//reset the Encoder Counter
EncoderCounter = 0;
DPRINTF("Encoder Counter = ");
DPRINTLN(EncoderCounter);
//the time this switch closed
EncoderSw.switchTime = millis();
}
//========================
//did this switch open ?
else if (currentState == OPENED) {
DPRINTF("The time the switch was closed = ");
DPRINTLN(millis() - EncoderSw.switchTime);
}
}
}
//===================================
//a valid switch change has not been confirmed
else {
EncoderSw.counter = 0;
}
//END of EncoderSw.pin
//======================================================================== CW_Sw.pin
//only proceed if the "Reset State Machine" is sitting in the Check_CW_CCW_Sw state
if (resetMachine == Check_CW_CCW_Sw) {
currentState = digitalRead(CW_Sw.pin);
//===================================
//has this switch changed state ?
if (CW_Sw.lastState != currentState) {
CW_Sw.counter++;
//is this change in state stable ?
if (CW_Sw.counter >= filter) {
//get ready for the next sequence
CW_Sw.counter = 0;
//update to this new state
CW_Sw.lastState = currentState;
//========================
//did this switch close ?
if (currentState == CLOSED) {
DPRINTLNF("Motor going Clockwise");
//restore the saved stepIndex
stepIndex = savedStepIndex;
stepMotor(stepIndex);
//movement is now allowed and the Motor will move CW
stepperTIMER.enableRestartTIMER();
digitalWrite(cwLED, LEDon);
}
//========================
//did this switch open ?
else if (currentState == OPENED) {
DPRINTLNF("Motor Stopped");
//save the current stepIndex
savedStepIndex = stepIndex;
//to save power, turn off stepper coils
stepIndex = 8;
stepMotor(stepIndex);
//the TIMER is now disabled and the Motor will stop
stepperTIMER.disableTIMER();
digitalWrite(cwLED, LEDoff);
}
}
}
}
//===================================
//a valid switch change has not been confirmed
else {
CW_Sw.counter = 0;
}
//END of CW_Sw.pin
//======================================================================== CCW_Sw.pin
//only proceed if the "Reset State Machine" is sitting in the Check_CW_CCW_Sw state
if (resetMachine == Check_CW_CCW_Sw) {
currentState = digitalRead(CCW_Sw.pin);
//===================================
//has this switch changed state ?
if (CCW_Sw.lastState != currentState) {
CCW_Sw.counter++;
//is this change in state stable ?
if (CCW_Sw.counter >= filter) {
//get ready for the next sequence
CCW_Sw.counter = 0;
//update to this new state
CCW_Sw.lastState = currentState;
//========================
//did this switch close ?
if (currentState == CLOSED) {
DPRINTLNF("Motor going Counter Clockwise");
//restore the saved stepIndex
stepIndex = savedStepIndex;
stepMotor(stepIndex);
//movement is now allowed and the Motor will move CCW
stepperTIMER.enableRestartTIMER();
digitalWrite(ccwLED, LEDon);
}
//========================
//did this switch open ?
else if (currentState == OPENED) {
DPRINTLNF("Motor Stopped");
//save the current stepIndex
savedStepIndex = stepIndex;
//to save power, turn off stepper coils
stepIndex = 8;
stepMotor(stepIndex);
//the TIMER is now disabled and the Motor will stop
stepperTIMER.disableTIMER();
digitalWrite(ccwLED, LEDoff);
}
}
}
}
//===================================
//a valid switch change has not been confirmed
else {
CCW_Sw.counter = 0;
}
//END of CCW_Sw.pin
//======================================================================== DeleteSw.pin
currentState = digitalRead(DeleteSw.pin);
//===================================
//has this switch changed state ?
if (DeleteSw.lastState != currentState) {
DeleteSw.counter++;
//is this change in state stable ?
if (DeleteSw.counter >= filter) {
//get ready for the next sequence
DeleteSw.counter = 0;
//update to this new state
DeleteSw.lastState = currentState;
//========================
//did this switch close ?
if (currentState == CLOSED) {
DPRINTLNF("Delete switch closed");
deleteLedTIMER.enableRestartTIMER();
}
//========================
//did this switch open ?
else if (currentState == OPENED) {
DPRINTLNF("Delete switch opened");
digitalWrite(deleteLED, LEDoff);
deleteLedTIMER.disableTIMER();
}
}
}
//===================================
//a valid switch change has not been confirmed
else {
DeleteSw.counter = 0;
}
//END of DeleteSw.pin
//======================================================================== SetPosSw.pin
currentState = digitalRead(SetPosSw.pin);
//===================================
//has this switch changed state ?
if (SetPosSw.lastState != currentState) {
SetPosSw.counter++;
//is this change in state stable ?
if (SetPosSw.counter >= filter) {
//get ready for the next sequence
SetPosSw.counter = 0;
//update to this new state
SetPosSw.lastState = currentState;
//========================
//did this switch close ?
if (currentState == CLOSED) {
DPRINTLNF("Set switch closed");
//toggle LED
//digitalWrite(setPosLED, digitalRead(setPosLED) == HIGH ? LOW : HIGH);
digitalWrite(setPosLED, LEDon);
}
//========================
//did this switch open ?
else if (currentState == OPENED) {
DPRINTLNF("Set switch opened");
digitalWrite(setPosLED, LEDoff);
}
}
}
//===================================
//a valid switch change has not been confirmed
else {
SetPosSw.counter = 0;
}
//END of SetPosSw.pin
//======================================================================== OptoSensor.pin
currentState = digitalRead(OptoSensor.pin);
//===================================
//has this switch changed state ?
if (OptoSensor.lastState != currentState) {
OptoSensor.counter++;
//is this change in state stable ?
if (OptoSensor.counter >= filter) {
//get ready for the next sequence
OptoSensor.counter = 0;
//update to this new state
OptoSensor.lastState = currentState;
//========================
//did this switch close ?
//if (currentState == CLOSED)
if (currentState == OPTOclosed) {
DPRINTLNF("Opto Sensor has Closed");
}
//========================
//did this switch open ?
//else if (currentState == OPENED)
else if (currentState == OPTOopened) {
DPRINTLNF("Opto Sensor has Opened");
}
}
}
//===================================
//a valid switch change has not been confirmed
else {
OptoSensor.counter = 0;
}
//END of OptoSensor.pin
} //END of checkSwitches()
// r e a d R o t a r y E n c o d e r ( )
//================================================^================================================
void readRotaryEncoder() {
static byte lastStateA = digitalRead(EncoderOutA);
byte currentStateA;
currentStateA = digitalRead(EncoderOutA);
//=========================================
//has this state changed ?
if (lastStateA != currentStateA) {
//update to the new state
lastStateA = currentStateA;
//========================
//when the outputB state is different from the outputA state,
//we are rotating clockwise CW
if (digitalRead(EncoderOutB) != currentStateA) {
//CW
EncoderCounter++;
}
//========================
//we are rotating counter clock wise CCW
else {
//CCW
EncoderCounter--;
}
DPRINTF("Encoder Counter = ");
DPRINTLN(EncoderCounter);
}
} //END of readRotaryEncoder()
// s t e p M o t o r ( )
//================================================^================================================
void stepMotor(int output) {
digitalWrite(IN1, bitRead(lookup[output], 0));
digitalWrite(IN2, bitRead(lookup[output], 1));
digitalWrite(IN3, bitRead(lookup[output], 2));
digitalWrite(IN4, bitRead(lookup[output], 3));
} //END of stepMotor()
//================================================^================================================
Im guessing from your line of questioning that there is a way to code in the reported value change whenever there is a motor position change rather than CW and CCW individually but im not sure how.