AccelStepper 'move' and 'runSpeed' in same loop not working

Hello, and thank you in advance if you're reading this. I'm a newbie to the world of Arduino, and I'm having trouble giving multiple commands to a stepper motor in the same void loop. Each of these commands by themselves in the loop, is working just fine. You will find my hardware list, code, and wiring schematic below.

What I wanted this code to do: Move the stepper motor clockwise 200 steps, pause for 2 seconds, then have the stepper motor move continuously counterclockwise at 200 steps/second until the beam of the break beam sensor is broken. Once the beam breaks, I wanted it to then stop moving continuously and instead move one last time counterclockwise 200 steps.

What is actually happening: The code does everything I wanted, except the middle portion. It seems to ignore the "runSpeed" command. So it just loops the first "move(200)" command over and over until I break the beam, and then it moves counterclockwise 200 steps.

I'm just not sure why it skips/ignores the "runSpeed" command after the "move" and "runToPostion" commands are executed. Is there some kind of hierarchy thing between these commands I don't understand? Am I missing something vital in the code? I would greatly appreciate any insights. Thanks!

Hardware:
Arduino Micro
MP6500 Stepper Motor Driver Carrier (Pololu)
NEMA 17 Bipolar Stepper Motor (Lin Engineering WO-4118L-07S)
IR Break Beam Sensor - 5mm LEDs (Adafruit)
break beam stepper motor circuit

[code]
#include <AccelStepper.h>
#include <MultiStepper.h>

// Connections to driver
const int dirPin = 2;  // Direction
const int stepPin = 3; // Step

#define SENSORPIN 4

AccelStepper myStepper(AccelStepper::DRIVER, stepPin, dirPin);

// variables will change:
int sensorState = 0, lastState = 0;       // variable for reading the pushbutton status

void setup() {
  // initialize the sensor pin as an input:
  pinMode(SENSORPIN, INPUT);
  digitalWrite(SENSORPIN, HIGH); // turn on the pullup

  // Setup the Outputs:
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  myStepper.setMaxSpeed(500);
  myStepper.setSpeed(-200);
  myStepper.setAcceleration(500);
}

void loop() {
  // move forward 200 steps
  myStepper.move(200);
  myStepper.runToPosition();

  // pause for 2 seconds
  delay(2000);

  // move continuously backward
  myStepper.runSpeed();

  // read the state of the pushbutton value:
  sensorState = digitalRead(SENSORPIN);

  // check if the sensor beam is broken
  // if it is, the sensorState is LOW:
  if (sensorState == LOW) {
    // go backward 200 steps
    myStepper.move(-200);
    myStepper.runToPosition();
  }
  lastState = sensorState;
}
[/code]

runSpeed() executes at most one step and must be called as fast as possible.

" Poll the motor and step it if a step is due, implementing a constant speed as set by the most recent call to setSpeed(). You must call this as frequently as possible, but at least once per step interval,"

This is the reference for all of the member functions of the AccelStepper class:

AccelStepper Class

I have found the MobaTools stepper library a bit easier to learn and simpler to use if you are interested. The library is available via the IDE library manager. Non-blocking movement functions that do not need to be called for each step is one advantage, I think.

This assumption is wrong
a single call to .runSpeed(); does a single step

from your description

Does this mean that the continioulsy counterclockwise rotation sometimes will be

  • 50 steps
  • or 430 steps
  • or 2600 steps
  • or 50002 steps
    ??

anyway using the MobaTools will make your life easier because with the MobaTools you can start / stop / change speed at any time
and you can execute lines of code in parallel to the stepper moving
while using functions like RunToPosition are blocking
This means nothing else can be done until the movement of RunToPosition has finished.
The MobaTools act non-bocking

best regards Stefan

After your message and @StefanL38's message, I think I understand this better now. So the reason I was able to get "continuous" spinning with runSpeed() by itself in the loop is just because it would call for one step, loop around, call for one step, loop around, etc.? I have looked at the AcceclStepper Class before, but I just didn't completely understand what that blurb was saying. Thank you for the reference and your response!

I understand this better now, thank you @StefanL38.
And I appreciate you and @groundFungus recommending MobaTools. I'm going to look into that today and see what I can figure out. Thanks to you both!

Here is a link to a WOKWI-simulation that demonstrates the following things:

  • realising your functionality with the mobatools
  • a state-machine is used for realising your functionality
  • the code has quite some comments to explain what the code is doing
  • the code has quite a lot serial-prints to the serial monitor to make visible what the code is doing
  • the states of the state-machine are printed once everytime the state changes
  • uses non-blocking timing based on function millis()

It will take some time to understand all lines of code
If you do understand them you have reached some advanced knowledge how to code

  • in a way to keep the code responsive all the time
  • use serial printing for making visible what your code is REALLY doing

WOKWI simulation demonstrating how to use the stepper-motor functions of the mobatools library

best regards Stefan

Wow, this is incredible! You must've just written this?! Thank you so much, I'm sure that took a bit of time, even for an advanced coder. I certainly don't understand all of it completely, but I'm able to follow along, especially with the helpful comments. I will be spending a lot of time looking this over and cross-referencing the MobaTools documentation to try to get a full understanding of it. I appreciate you doing this because even with the MobaTools documentation, it can be difficult to understand all of this without an example to follow along.

One thing I noticed...I wired up a button to pin 5 so I could try this. It did most of what I expected (what you wrote in the notes), but after the beam was broken, the motor only stopped, it didn't perform the one revolution backward...it only stopped. Do you know why this might be?

Last thing I wanted to ask about this code: when the beam was broken, it took about 2 seconds for the motor to stop. Is there a way to make the response quicker?

Again, thank you so much! You've given me a lot to study.

your description of the wanted functionality is

  • move the stepper-motor 200 steps clockwise
    regardless of what the sensoris detecting. After finishing the 200 steps

-pause for 2seconds

  • then have the stepper motor move continuously counterclockwise at 200 steps/second until the beam of the break beam sensor is broken

-Once the beam breaks, I wanted it to then stop moving continuously and instead move one last time counterclockwise 200 steps.

this is what the code is doing.

What you are asking for seems to be a different functionality than the one you described above

So think about it and post a new wordeddescription of the functionality that you want.

to analyse this you should post the complete serial output as a a code-section
switch on the time-stamp in the serial monitor

It might be that this is caused by the INPUT_PULL-up configuration of the IO-pins
For further analysing you can add more serialdebug-output that makesvisible what the code is doing and which IO-pin has which logic state LOW/HIGH at which mode of the state-machine.

No, I think there has been a miscommunication, that is what I wanted as functionality! What I originally wrote (and what you repeated in your last message) is exactly what I wanted the code to do. I'm just saying that once I wired it up and tested the code with my actual circuit, the last part ("move one last time counterclockwise 200 steps") is not happening. Once the beam is broken, the motor just stops. That last CCW 200 steps isn't actually happening with the motor. Hopefully that makes sense...

As requested, here is the copied output from the serial monitor:

15:43:38.338 -> Setup-Start
15:43:38.338 -> press button for start
15:43:39.508 -> state changed from sm_idling to sm_RotFwd1Rev
15:43:39.508 -> state changed from sm_RotFwd1Rev to sm_wait1Rev
15:43:43.119 -> state changed from sm_wait1Rev to sm_Pausing
15:43:45.132 -> state changed from sm_Pausing to sm_CheckForBeamBreaksm_WaitRotBack1Rev
15:43:48.679 -> Beam interrupted at step-position -40
15:43:48.679 -> rotating back to step-position 
15:43:48.679 -> state changed from sm_CheckForBeamBreaksm_WaitRotBack1Rev to sm_WaitRotBack1Rev
15:43:51.746 -> -240
15:43:51.746 -> press button for new start
15:43:51.746 -> state changed from sm_WaitRotBack1Rev to sm_idling

Thanks for your continued help on this and getting back to me so quickly!

This line indicates beam is interrupted

These lines indicate
stepper-motor is rotating back

printing -240 shows it
The beam is interrupted at step-counter -40
and then rotates backto step-counter -240
which is 200 steps CCW from position -40

I have modified the WOKWI-simulation to print alot more
analyse what is printed to the serial monitor

I loaded the updated code and copied the serial monitor output. I also took a video of what has been happening and uploaded to Youtube: stepper break beam test - YouTube

I watched the serial monitor in realtime while I broke the beam, and I noticed while it was displaying all the "Back1Rev" steps (starting at 09:52:34.080) that the motor was still continuously rotating clockwise. When the serial monitor reached these lines:
09:52:37.133 -> "Back1Rev" myStepMotor.distanceToGo() changed from 1 to 0
09:52:37.133 -> 1 revolution CCW finished
that was actually when the motor stopped its continuous clockwise rotation. And then it never did the actual 1 revolution counterclockwise.

09:52:20.773 -> "idling:" 1
09:52:20.773 -> "idling:" digitalRead(sensorPin)=1
09:52:20.773 -> "idling:" digitalRead(sensorPin)=1
09:52:20.773 -> Setup-Start
09:52:20.773 -> press button for start
09:52:21.803 -> "idling:" digitalRead(sensorPin)=1
09:52:22.778 -> "idling:" digitalRead(sensorPin)=1
09:52:23.106 -> state changed from sm_idling to sm_RotFwd1Rev
09:52:23.106 -> state changed from sm_RotFwd1Rev to sm_wait1Rev
09:52:26.718 -> state changed from sm_wait1Rev to sm_Pausing
09:52:28.725 -> starting continous rotating
09:52:28.725 -> state changed from sm_Pausing to sm_CheckForBeamBreaksm_WaitRotBack1Rev
09:52:28.725 -> "Check:" digitalRead(sensorPin)=1
09:52:29.235 -> "Check:" digitalRead(sensorPin)=1
09:52:29.703 -> "Check:" digitalRead(sensorPin)=1
09:52:30.239 -> "Check:" digitalRead(sensorPin)=1
09:52:30.709 -> "Check:" digitalRead(sensorPin)=1
09:52:31.215 -> "Check:" digitalRead(sensorPin)=1
09:52:31.722 -> "Check:" digitalRead(sensorPin)=1
09:52:32.234 -> "Check:" digitalRead(sensorPin)=1
09:52:32.701 -> "Check:" digitalRead(sensorPin)=1
09:52:33.212 -> "Check:" digitalRead(sensorPin)=1
09:52:33.719 -> "Check:" digitalRead(sensorPin)=1
09:52:34.080 -> Beam interrupted at step-position -183
09:52:34.080 -> rotating back to step-position 
09:52:34.080 -> state changed from sm_CheckForBeamBreaksm_WaitRotBack1Rev to sm_WaitRotBack1Rev
09:52:34.080 -> "Back1Rev" myStepMotor.distanceToGo() changed from 0 to 199
09:52:34.080 -> "Back1Rev" myStepMotor.distanceToGo() changed from 199 to 198
09:52:34.080 -> "Back1Rev" myStepMotor.distanceToGo() changed from 198 to 197
09:52:34.113 -> "Back1Rev" myStepMotor.distanceToGo() changed from 197 to 196
09:52:34.113 -> "Back1Rev" myStepMotor.distanceToGo() changed from 196 to 195
09:52:34.113 -> "Back1Rev" myStepMotor.distanceToGo() changed from 195 to 194
09:52:34.159 -> "Back1Rev" myStepMotor.distanceToGo() changed from 194 to 193
09:52:34.159 -> "Back1Rev" myStepMotor.distanceToGo() changed from 193 to 192
09:52:34.159 -> "Back1Rev" myStepMotor.distanceToGo() changed from 192 to 191
09:52:34.159 -> "Back1Rev" myStepMotor.distanceToGo() changed from 191 to 190
09:52:34.207 -> "Back1Rev" myStepMotor.distanceToGo() changed from 190 to 189
09:52:34.207 -> "Back1Rev" myStepMotor.distanceToGo() changed from 189 to 188
09:52:34.207 -> "Back1Rev" myStepMotor.distanceToGo() changed from 188 to 187
09:52:34.252 -> "Back1Rev" myStepMotor.distanceToGo() changed from 187 to 186
09:52:34.252 -> "Back1Rev" myStepMotor.distanceToGo() changed from 186 to 185
09:52:34.252 -> "Back1Rev" myStepMotor.distanceToGo() changed from 185 to 184
09:52:34.252 -> "Back1Rev" myStepMotor.distanceToGo() changed from 184 to 183
09:52:34.299 -> "Back1Rev" myStepMotor.distanceToGo() changed from 183 to 182
09:52:34.299 -> "Back1Rev" myStepMotor.distanceToGo() changed from 182 to 181
09:52:34.299 -> "Back1Rev" myStepMotor.distanceToGo() changed from 181 to 180
09:52:34.299 -> "Back1Rev" myStepMotor.distanceToGo() changed from 180 to 179
09:52:34.346 -> "Back1Rev" myStepMotor.distanceToGo() changed from 179 to 178
09:52:34.346 -> "Back1Rev" myStepMotor.distanceToGo() changed from 178 to 177
09:52:34.346 -> "Back1Rev" myStepMotor.distanceToGo() changed from 177 to 176
09:52:34.346 -> "Back1Rev" myStepMotor.distanceToGo() changed from 176 to 175
09:52:34.380 -> "Back1Rev" myStepMotor.distanceToGo() changed from 175 to 174
09:52:34.380 -> "Back1Rev" myStepMotor.distanceToGo() changed from 174 to 173
09:52:34.380 -> "Back1Rev" myStepMotor.distanceToGo() changed from 173 to 172
09:52:34.427 -> "Back1Rev" myStepMotor.distanceToGo() changed from 172 to 171
09:52:34.427 -> "Back1Rev" myStepMotor.distanceToGo() changed from 171 to 170
09:52:34.427 -> "Back1Rev" myStepMotor.distanceToGo() changed from 170 to 169
09:52:34.473 -> "Back1Rev" myStepMotor.distanceToGo() changed from 169 to 168
09:52:34.473 -> "Back1Rev" myStepMotor.distanceToGo() changed from 168 to 167
09:52:34.473 -> "Back1Rev" myStepMotor.distanceToGo() changed from 167 to 166
09:52:34.473 -> "Back1Rev" myStepMotor.distanceToGo() changed from 166 to 165
09:52:34.521 -> "Back1Rev" myStepMotor.distanceToGo() changed from 165 to 164
09:52:34.521 -> "Back1Rev" myStepMotor.distanceToGo() changed from 164 to 163
09:52:34.521 -> "Back1Rev" myStepMotor.distanceToGo() changed from 163 to 162
09:52:34.521 -> "Back1Rev" myStepMotor.distanceToGo() changed from 162 to 161
09:52:34.555 -> "Back1Rev" myStepMotor.distanceToGo() changed from 161 to 160
09:52:34.555 -> "Back1Rev" myStepMotor.distanceToGo() changed from 160 to 159
09:52:34.601 -> "Back1Rev" myStepMotor.distanceToGo() changed from 159 to 158
09:52:34.601 -> "Back1Rev" myStepMotor.distanceToGo() changed from 158 to 157
09:52:34.601 -> "Back1Rev" myStepMotor.distanceToGo() changed from 157 to 156
09:52:34.601 -> "Back1Rev" myStepMotor.distanceToGo() changed from 156 to 155
09:52:34.648 -> "Back1Rev" myStepMotor.distanceToGo() changed from 155 to 154
09:52:34.648 -> "Back1Rev" myStepMotor.distanceToGo() changed from 154 to 153
09:52:34.648 -> "Back1Rev" myStepMotor.distanceToGo() changed from 153 to 152
09:52:34.648 -> "Back1Rev" myStepMotor.distanceToGo() changed from 152 to 151
09:52:34.696 -> "Back1Rev" myStepMotor.distanceToGo() changed from 151 to 150
09:52:34.696 -> "Back1Rev" myStepMotor.distanceToGo() changed from 150 to 149
09:52:34.696 -> "Back1Rev" myStepMotor.distanceToGo() changed from 149 to 148
09:52:34.696 -> "Back1Rev" myStepMotor.distanceToGo() changed from 148 to 147
09:52:34.742 -> "Back1Rev" myStepMotor.distanceToGo() changed from 147 to 146
09:52:34.742 -> "Back1Rev" myStepMotor.distanceToGo() changed from 146 to 145
09:52:34.742 -> "Back1Rev" myStepMotor.distanceToGo() changed from 145 to 144
09:52:34.789 -> "Back1Rev" myStepMotor.distanceToGo() changed from 144 to 143
09:52:34.789 -> "Back1Rev" myStepMotor.distanceToGo() changed from 143 to 142
09:52:34.789 -> "Back1Rev" myStepMotor.distanceToGo() changed from 142 to 141
09:52:34.789 -> "Back1Rev" myStepMotor.distanceToGo() changed from 141 to 140
09:52:34.835 -> "Back1Rev" myStepMotor.distanceToGo() changed from 140 to 139
09:52:34.835 -> "Back1Rev" myStepMotor.distanceToGo() changed from 139 to 138
09:52:34.835 -> "Back1Rev" myStepMotor.distanceToGo() changed from 138 to 137
09:52:34.835 -> "Back1Rev" myStepMotor.distanceToGo() changed from 137 to 136
09:52:34.882 -> "Back1Rev" myStepMotor.distanceToGo() changed from 136 to 135
09:52:34.882 -> "Back1Rev" myStepMotor.distanceToGo() changed from 135 to 134
09:52:34.882 -> "Back1Rev" myStepMotor.distanceToGo() changed from 134 to 133
09:52:34.882 -> "Back1Rev" myStepMotor.distanceToGo() changed from 133 to 132
09:52:34.928 -> "Back1Rev" myStepMotor.distanceToGo() changed from 132 to 131
09:52:34.928 -> "Back1Rev" myStepMotor.distanceToGo() changed from 131 to 130
09:52:34.928 -> "Back1Rev" myStepMotor.distanceToGo() changed from 130 to 129
09:52:34.928 -> "Back1Rev" myStepMotor.distanceToGo() changed from 129 to 128
09:52:34.976 -> "Back1Rev" myStepMotor.distanceToGo() changed from 128 to 127
09:52:34.976 -> "Back1Rev" myStepMotor.distanceToGo() changed from 127 to 126
09:52:34.976 -> "Back1Rev" myStepMotor.distanceToGo() changed from 126 to 125
09:52:35.024 -> "Back1Rev" myStepMotor.distanceToGo() changed from 125 to 124
09:52:35.024 -> "Back1Rev" myStepMotor.distanceToGo() changed from 124 to 123
09:52:35.024 -> "Back1Rev" myStepMotor.distanceToGo() changed from 123 to 122
09:52:35.024 -> "Back1Rev" myStepMotor.distanceToGo() changed from 122 to 121
09:52:35.071 -> "Back1Rev" myStepMotor.distanceToGo() changed from 121 to 120
09:52:35.071 -> "Back1Rev" myStepMotor.distanceToGo() changed from 120 to 119
09:52:35.071 -> "Back1Rev" myStepMotor.distanceToGo() changed from 119 to 118
09:52:35.071 -> "Back1Rev" myStepMotor.distanceToGo() changed from 118 to 117
09:52:35.118 -> "Back1Rev" myStepMotor.distanceToGo() changed from 117 to 116
09:52:35.118 -> "Back1Rev" myStepMotor.distanceToGo() changed from 116 to 115
09:52:35.118 -> "Back1Rev" myStepMotor.distanceToGo() changed from 115 to 114
09:52:35.118 -> "Back1Rev" myStepMotor.distanceToGo() changed from 114 to 113
09:52:35.164 -> "Back1Rev" myStepMotor.distanceToGo() changed from 113 to 112
09:52:35.164 -> "Back1Rev" myStepMotor.distanceToGo() changed from 112 to 111
09:52:35.164 -> "Back1Rev" myStepMotor.distanceToGo() changed from 111 to 110
09:52:35.212 -> "Back1Rev" myStepMotor.distanceToGo() changed from 110 to 109
09:52:35.212 -> "Back1Rev" myStepMotor.distanceToGo() changed from 109 to 108
09:52:35.212 -> "Back1Rev" myStepMotor.distanceToGo() changed from 108 to 107
09:52:35.212 -> "Back1Rev" myStepMotor.distanceToGo() changed from 107 to 106
09:52:35.257 -> "Back1Rev" myStepMotor.distanceToGo() changed from 106 to 105
09:52:35.257 -> "Back1Rev" myStepMotor.distanceToGo() changed from 105 to 104
09:52:35.257 -> "Back1Rev" myStepMotor.distanceToGo() changed from 104 to 103
09:52:35.257 -> "Back1Rev" myStepMotor.distanceToGo() changed from 103 to 102
09:52:35.303 -> "Back1Rev" myStepMotor.distanceToGo() changed from 102 to 101
09:52:35.303 -> "Back1Rev" myStepMotor.distanceToGo() changed from 101 to 100
09:52:35.303 -> "Back1Rev" myStepMotor.distanceToGo() changed from 100 to 99
09:52:35.350 -> "Back1Rev" myStepMotor.distanceToGo() changed from 99 to 98
09:52:35.350 -> "Back1Rev" myStepMotor.distanceToGo() changed from 98 to 97
09:52:35.350 -> "Back1Rev" myStepMotor.distanceToGo() changed from 97 to 96
09:52:35.350 -> "Back1Rev" myStepMotor.distanceToGo() changed from 96 to 95
09:52:35.396 -> "Back1Rev" myStepMotor.distanceToGo() changed from 95 to 94
09:52:35.396 -> "Back1Rev" myStepMotor.distanceToGo() changed from 94 to 93
09:52:35.396 -> "Back1Rev" myStepMotor.distanceToGo() changed from 93 to 92
09:52:35.396 -> "Back1Rev" myStepMotor.distanceToGo() changed from 92 to 91
09:52:35.443 -> "Back1Rev" myStepMotor.distanceToGo() changed from 91 to 90
09:52:35.443 -> "Back1Rev" myStepMotor.distanceToGo() changed from 90 to 89
09:52:35.443 -> "Back1Rev" myStepMotor.distanceToGo() changed from 89 to 88
09:52:35.443 -> "Back1Rev" myStepMotor.distanceToGo() changed from 88 to 87
09:52:35.489 -> "Back1Rev" myStepMotor.distanceToGo() changed from 87 to 86
09:52:35.489 -> "Back1Rev" myStepMotor.distanceToGo() changed from 86 to 85
09:52:35.489 -> "Back1Rev" myStepMotor.distanceToGo() changed from 85 to 84
09:52:35.535 -> "Back1Rev" myStepMotor.distanceToGo() changed from 84 to 83
09:52:35.535 -> "Back1Rev" myStepMotor.distanceToGo() changed from 83 to 82
09:52:35.535 -> "Back1Rev" myStepMotor.distanceToGo() changed from 82 to 81
09:52:35.535 -> "Back1Rev" myStepMotor.distanceToGo() changed from 81 to 80
09:52:35.582 -> "Back1Rev" myStepMotor.distanceToGo() changed from 80 to 79
09:52:35.582 -> "Back1Rev" myStepMotor.distanceToGo() changed from 79 to 78
09:52:35.582 -> "Back1Rev" myStepMotor.distanceToGo() changed from 78 to 77
09:52:35.582 -> "Back1Rev" myStepMotor.distanceToGo() changed from 77 to 76
09:52:35.624 -> "Back1Rev" myStepMotor.distanceToGo() changed from 76 to 75
09:52:35.624 -> "Back1Rev" myStepMotor.distanceToGo() changed from 75 to 74
09:52:35.624 -> "Back1Rev" myStepMotor.distanceToGo() changed from 74 to 73
09:52:35.669 -> "Back1Rev" myStepMotor.distanceToGo() changed from 73 to 72
09:52:35.669 -> "Back1Rev" myStepMotor.distanceToGo() changed from 72 to 71
09:52:35.669 -> "Back1Rev" myStepMotor.distanceToGo() changed from 71 to 70
09:52:35.669 -> "Back1Rev" myStepMotor.distanceToGo() changed from 70 to 69
09:52:35.704 -> "Back1Rev" myStepMotor.distanceToGo() changed from 69 to 68
09:52:35.704 -> "Back1Rev" myStepMotor.distanceToGo() changed from 68 to 67
09:52:35.704 -> "Back1Rev" myStepMotor.distanceToGo() changed from 67 to 66
09:52:35.750 -> "Back1Rev" myStepMotor.distanceToGo() changed from 66 to 65
09:52:35.750 -> "Back1Rev" myStepMotor.distanceToGo() changed from 65 to 64
09:52:35.750 -> "Back1Rev" myStepMotor.distanceToGo() changed from 64 to 63
09:52:35.796 -> "Back1Rev" myStepMotor.distanceToGo() changed from 63 to 62
09:52:35.796 -> "Back1Rev" myStepMotor.distanceToGo() changed from 62 to 61
09:52:35.796 -> "Back1Rev" myStepMotor.distanceToGo() changed from 61 to 60
09:52:35.796 -> "Back1Rev" myStepMotor.distanceToGo() changed from 60 to 59
09:52:35.842 -> "Back1Rev" myStepMotor.distanceToGo() changed from 59 to 58
09:52:35.842 -> "Back1Rev" myStepMotor.distanceToGo() changed from 58 to 57
09:52:35.842 -> "Back1Rev" myStepMotor.distanceToGo() changed from 57 to 56
09:52:35.842 -> "Back1Rev" myStepMotor.distanceToGo() changed from 56 to 55
09:52:35.888 -> "Back1Rev" myStepMotor.distanceToGo() changed from 55 to 54
09:52:35.888 -> "Back1Rev" myStepMotor.distanceToGo() changed from 54 to 53
09:52:35.888 -> "Back1Rev" myStepMotor.distanceToGo() changed from 53 to 52
09:52:35.934 -> "Back1Rev" myStepMotor.distanceToGo() changed from 52 to 51
09:52:35.934 -> "Back1Rev" myStepMotor.distanceToGo() changed from 51 to 50
09:52:35.934 -> "Back1Rev" myStepMotor.distanceToGo() changed from 50 to 49
09:52:35.934 -> "Back1Rev" myStepMotor.distanceToGo() changed from 49 to 48
09:52:35.980 -> "Back1Rev" myStepMotor.distanceToGo() changed from 48 to 47
09:52:35.980 -> "Back1Rev" myStepMotor.distanceToGo() changed from 47 to 46
09:52:35.980 -> "Back1Rev" myStepMotor.distanceToGo() changed from 46 to 45
09:52:36.027 -> "Back1Rev" myStepMotor.distanceToGo() changed from 45 to 44
09:52:36.027 -> "Back1Rev" myStepMotor.distanceToGo() changed from 44 to 43
09:52:36.027 -> "Back1Rev" myStepMotor.distanceToGo() changed from 43 to 42
09:52:36.027 -> "Back1Rev" myStepMotor.distanceToGo() changed from 42 to 41
09:52:36.073 -> "Back1Rev" myStepMotor.distanceToGo() changed from 41 to 40
09:52:36.073 -> "Back1Rev" myStepMotor.distanceToGo() changed from 40 to 39
09:52:36.073 -> "Back1Rev" myStepMotor.distanceToGo() changed from 39 to 38
09:52:36.119 -> "Back1Rev" myStepMotor.distanceToGo() changed from 38 to 37
09:52:36.119 -> "Back1Rev" myStepMotor.distanceToGo() changed from 37 to 36
09:52:36.166 -> "Back1Rev" myStepMotor.distanceToGo() changed from 36 to 35
09:52:36.166 -> "Back1Rev" myStepMotor.distanceToGo() changed from 35 to 34
09:52:36.166 -> "Back1Rev" myStepMotor.distanceToGo() changed from 34 to 33
09:52:36.204 -> "Back1Rev" myStepMotor.distanceToGo() changed from 33 to 32
09:52:36.204 -> "Back1Rev" myStepMotor.distanceToGo() changed from 32 to 31
09:52:36.250 -> "Back1Rev" myStepMotor.distanceToGo() changed from 31 to 30
09:52:36.250 -> "Back1Rev" myStepMotor.distanceToGo() changed from 30 to 29
09:52:36.250 -> "Back1Rev" myStepMotor.distanceToGo() changed from 29 to 28
09:52:36.295 -> "Back1Rev" myStepMotor.distanceToGo() changed from 28 to 27
09:52:36.295 -> "Back1Rev" myStepMotor.distanceToGo() changed from 27 to 26
09:52:36.341 -> "Back1Rev" myStepMotor.distanceToGo() changed from 26 to 25
09:52:36.341 -> "Back1Rev" myStepMotor.distanceToGo() changed from 25 to 24
09:52:36.341 -> "Back1Rev" myStepMotor.distanceToGo() changed from 24 to 23
09:52:36.388 -> "Back1Rev" myStepMotor.distanceToGo() changed from 23 to 22
09:52:36.388 -> "Back1Rev" myStepMotor.distanceToGo() changed from 22 to 21
09:52:36.434 -> "Back1Rev" myStepMotor.distanceToGo() changed from 21 to 20
09:52:36.434 -> "Back1Rev" myStepMotor.distanceToGo() changed from 20 to 19
09:52:36.480 -> "Back1Rev" myStepMotor.distanceToGo() changed from 19 to 18
09:52:36.480 -> "Back1Rev" myStepMotor.distanceToGo() changed from 18 to 17
09:52:36.527 -> "Back1Rev" myStepMotor.distanceToGo() changed from 17 to 16
09:52:36.574 -> "Back1Rev" myStepMotor.distanceToGo() changed from 16 to 15
09:52:36.574 -> "Back1Rev" myStepMotor.distanceToGo() changed from 15 to 14
09:52:36.621 -> "Back1Rev" myStepMotor.distanceToGo() changed from 14 to 13
09:52:36.621 -> "Back1Rev" myStepMotor.distanceToGo() changed from 13 to 12
09:52:36.668 -> "Back1Rev" myStepMotor.distanceToGo() changed from 12 to 11
09:52:36.714 -> "Back1Rev" myStepMotor.distanceToGo() changed from 11 to 10
09:52:36.714 -> "Back1Rev" myStepMotor.distanceToGo() changed from 10 to 9
09:52:36.761 -> "Back1Rev" myStepMotor.distanceToGo() changed from 9 to 8
09:52:36.807 -> "Back1Rev" myStepMotor.distanceToGo() changed from 8 to 7
09:52:36.853 -> "Back1Rev" myStepMotor.distanceToGo() changed from 7 to 6
09:52:36.899 -> "Back1Rev" myStepMotor.distanceToGo() changed from 6 to 5
09:52:36.945 -> "Back1Rev" myStepMotor.distanceToGo() changed from 5 to 4
09:52:36.992 -> "Back1Rev" myStepMotor.distanceToGo() changed from 4 to 3
09:52:36.992 -> "Back1Rev" myStepMotor.distanceToGo() changed from 3 to 2
09:52:37.086 -> "Back1Rev" myStepMotor.distanceToGo() changed from 2 to 1
09:52:37.133 -> "Back1Rev" myStepMotor.distanceToGo() changed from 1 to 0
09:52:37.133 -> 1 revolution CCW finished
09:52:37.133 -> -383
09:52:37.133 -> press button for new start
09:52:37.133 -> state changed from sm_WaitRotBack1Rev to sm_idling
09:52:37.133 -> "idling:" digitalRead(sensorPin)=0
09:52:38.111 -> "idling:" digitalRead(sensorPin)=1
09:52:39.134 -> "idling:" digitalRead(sensorPin)=1

This is - letter by letter - the description that you wrote how the functionality shall be

the same description as list

  1. move stepper-motor 200 steps (do not react on beam interruption)

  2. pause for 2 seconds (do not react on beam interruption)

  3. then have the stepper motor move continuously **counterclockwise ** at 200 steps/second until the beam of the break beam sensor is broken (DO react on beam interruption)

  4. Once the beam breaks, I wanted it to then stop moving continuously and instead move one last time **counterclockwise ** 200 steps

The rotation-direction that you specified in 3. and in 4. are both counter-clockwise

while in 3. which has the code

case sm_CheckForBeamBreak:
      dbgi("Check:",digitalRead(sensorPin),500);
      if ( digitalRead(sensorPin) == pressed) {
        myStepMotor.stop();                  // stop continous rotation
        Serial.print("Beam interrupted at step-position ");
        Serial.println(myStepMotor.readSteps() );

the serial monitor prints

09:52:33.719 -> "Check:" digitalRead(sensorPin)=1
09:52:34.080 -> Beam interrupted at step-position -183 
09:52:34.080 -> rotating back to step-position 
09:52:34.080 -> state changed from sm_CheckForBeamBreaksm_WaitRotBack1Rev to sm_WaitRotBack1Rev

at
09:52:34.080 -> Beam interrupted at step-position -183
you interrupted the beam
and
the line

        myStepMotor.stop();                  // stop continous rotation

is executed
directly after this "stop" command

  1. starts which you described as

and this is exactly what is happening

You can't really see the stop of the continiously rotation because in the same millisecond the rotating back 200 steps starts.

The rotate back 200 steps starts at the same millisecond the beam gets interrupted.

And this is exactly what is shown in the video too

So if you want a different behaviour than the one that you observe now

You have to

modify

and write

new

and with more details
a new description of the wanted behaviour

You have to specifiy what does "stop" mean?
a "real" stop? If so for how long?

best regards Stefan

Oh man, I'm very sorry! I got my wires crossed on this one. I understand what's happening with this code now, and it is exactly what I needed. Sorry for me mixing up the CW and CCW. You're the man! Thanks again for helping with this!

@StefanL38 I made some changes to the code you provided, but now I'm getting the error: "'printStateIfChanged' was not declared in this scope"

Would it be more appropriate to post the code here and ask why this is happening, or should I start a new topic?

as long as the question is to the same project. Starting a new thread for the same project is seen as cross-posting which would be against forum-rules

How should anybody ever analyse your changed code if you do not post the actual code as a complete sketch??

best regards Stefan

I just didn't want to post it yet if this wasn't the right place to do that. You've explained that it is though, so here it is, below.

I added a 2nd button and wanted it to do something slightly different. The first button is still doing what I had originally asked (just backwards--I had the CW and CCW backwards in my original post and request, but that was an easy switch in the code).

What I wanted the 2nd button to do: rotate the motor CCW 200 steps, pause for 2 seconds, rotate CW 200 steps, pause for 1.5 seconds, rotate CCW 200 steps again, pause for 2 seconds again, rotate continuously CW, and when the beam is broken, stop continuous rotation and rotate CW 200 steps, then back to idle.

Once I started playing around with the code in the 2nd Switch (for button 2), the compiler started giving me this error:

'printStateIfChanged' was not declared in this scope

Thanks again for your insight!

#include <MobaTools.h>
const byte dirPin  = 2;
const byte stepPin = 3;

const byte sensorPin = 4;
const byte buttonPin1 = 5;
const byte buttonPin2 = 9;

const int STEPS_REVOLUTION = 200;

// modes of operation = states of the state-machine
const byte sm_idling            = 0;
const byte sm_RotFwd1Rev        = 1;
const byte sm_wait1Rev          = 2;
const byte sm_PausingA          = 3;
const byte sm_CheckForBeamBreak = 4;
const byte sm_WaitRotBack1Rev   = 5;
const byte sm_PausingB          = 6;
const byte sm_PausingC          = 7;

// 2D-array of chars for indicating the state
// the state-machine is in with letters instead of a number
// which makes it easier to understand by just reading
const char stateName[][20] = {"sm_idling",
                              "sm_RotFwd1Rev",
                              "sm_wait1Rev",
                              "sm_PausingA",
                              "sm_CheckForBeamBreak",
                              "sm_WaitRotBack1Rev"
                              "sm_PausingB",
                              "sm_PausingC",
                             };

const byte pressed   = LOW;
const byte unPressed = HIGH;

byte myState = sm_idling;
const int oneRevolution = 200;

unsigned long waitTimer;

MoToStepper myStepMotor(STEPS_REVOLUTION, STEPDIR); // HALFSTEP ist default

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  pinMode(sensorPin, INPUT);
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);

  myStepMotor.attach(stepPin, dirPin);
  myStepMotor.setSpeed( 240 );       // = 24 rotations/Min
  myStepMotor.setRampLen( oneRevolution / 4 );   // = 1/4 Revolution
  myStepMotor.setZero();            // Set reference point for motor 1

  myState = sm_idling;
  Serial.println("press button for start" );

  printStateIfChanged(myState);
}

void loop() {
  // everything happens inside the function myStepperStateMachine
  myStepperStateMachine();
}

void myStepperStateMachine() {

  printStateIfChanged(myState);

  switch (myState) {

    // through the break;-statement each case is mutually exclusive
    case sm_idling:
      // check if button is pressed
      if ( digitalRead(buttonPin1) == pressed) {
        // if button is pressed
        myState = sm_RotFwd1Rev; // change to other state
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_RotFwd1Rev:
      myStepMotor.doSteps(-oneRevolution); // set new targetposition
      myState = sm_wait1Rev;
      break; // immediately jump down to END-OF-SWITCH

    // wait for stepper-motor to reach target position
    case sm_wait1Rev:
      if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
        waitTimer = millis();        // store snapshot of time as time-reference for waiting
        myState = sm_PausingA;
      }
      break; // immediately jump down to END-OF-SWITCH

    // wait until pausing time is over
    case sm_PausingA:
      // check if 2000 milliseconds have passed by (since waitTimer = millis(); )
      if ( TimePeriodIsOver(waitTimer, 2000)  ) {
        // if REALLY 2000 milliseconds have passed by
        myStepMotor.rotate(1);  // start continous rotating // opposite direction is .rotate(-1);
        myState = sm_CheckForBeamBreak;
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_CheckForBeamBreak:
      if ( digitalRead(sensorPin) == pressed) {
        myStepMotor.stop();                  // stop continous rotation
        Serial.print("Beam interrupted at step-position ");
        Serial.println(myStepMotor.readSteps() );
        // start rotation one rev CW
        myStepMotor.doSteps(oneRevolution);
        Serial.println("rotating back to step-position " );
        // as the step-pulses are created in the backround
        // code executes the lines below
        myState = sm_WaitRotBack1Rev;
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_WaitRotBack1Rev:
      //if ( !myStepMotor.moving() ) { // if motor has reached target-position
      if ( myStepMotor.distanceToGo() == 0 ) {
        Serial.println(myStepMotor.readSteps() );
        myState = sm_idling;
        Serial.println("press button for new start" );
      }
      //myState = sm_idling;
      break; // immediately jump down to END-OF-SWITCH
  } //END-OF-SWITCH

  switch (myState) {

    // through the break;-statement each case is mutually exclusive
    case sm_idling:
      // check if button is pressed
      if ( digitalRead(buttonPin2) == pressed) {
        // if button is pressed
        myState = sm_RotFwd1Rev; // change to other state
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_RotFwd1Rev:
      myStepMotor.doSteps(-oneRevolution); // set new targetposition
      myState = sm_wait1Rev;
      break; // immediately jump down to END-OF-SWITCH

    // wait for stepper-motor to reach target position
    case sm_wait1Rev:
      if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
        waitTimer = millis();        // store snapshot of time as time-reference for waiting
        myState = sm_PausingB;
      }
      break; // immediately jump down to END-OF-SWITCH

    // wait until pausing time is over
    case sm_PausingB:
      // check if 2000 milliseconds have passed by (since waitTimer = millis(); )
      if ( TimePeriodIsOver(waitTimer, 2000)  ) {
        // if REALLY 2000 milliseconds have passed by
        myStepMotor.doSteps(oneRevolution); // set new targetposition
        myState = sm_wait1Rev;
        break; // immediately jump down to END-OF-SWITCH

      // wait for stepper-motor to reach target position
      case sm_wait1Rev:
        if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
          waitTimer = millis();        // store snapshot of time as time-reference for waiting
          myState = sm_PausingC;
        }
        break; // immediately jump down to END-OF-SWITCH

      // wait until pausing time is over
      case sm_PausingC:
        // check if 1500 milliseconds have passed by (since waitTimer = millis(); )
        if ( TimePeriodIsOver(waitTimer, 1500)  ) {
          // if REALLY 1500 milliseconds have passed by
          myStepMotor.doSteps(-oneRevolution); // set new targetposition
          myState = sm_wait1Rev;
          break; // immediately jump down to END-OF-SWITCH

        // wait for stepper-motor to reach target position
        case sm_wait1Rev:
          if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
            waitTimer = millis();        // store snapshot of time as time-reference for waiting
            myState = sm_PausingA;
          }
          break; // immediately jump down to END-OF-SWITCH

        // wait until pausing time is over
        case sm_PausingA:
          // check if 2000 milliseconds have passed by (since waitTimer = millis(); )
          if ( TimePeriodIsOver(waitTimer, 2000)  ) {
            // if REALLY 2000 milliseconds have passed by
            myStepMotor.rotate(1);  // start continuous rotating // opposite direction is .rotate(-1);
            myState = sm_CheckForBeamBreak;
          }
          break; // immediately jump down to END-OF-SWITCH

        case sm_CheckForBeamBreak:
          if ( digitalRead(sensorPin) == pressed) {
            myStepMotor.stop();                  // stop continuous rotation
            Serial.print("Beam interrupted at step-position ");
            Serial.println(myStepMotor.readSteps() );
            // start rotation one rev CW
            myStepMotor.doSteps(oneRevolution);
            Serial.println("rotating back to step-position " );
            // as the step-pulses are created in the background
            // code executes the lines below
            myState = sm_WaitRotBack1Rev;
          }
          break; // immediately jump down to END-OF-SWITCH

        case sm_WaitRotBack1Rev:
          //if ( !myStepMotor.moving() ) { // if motor has reached target-position
          if ( myStepMotor.distanceToGo() == 0 ) {
            Serial.println(myStepMotor.readSteps() );
            myState = sm_idling;
            Serial.println("press button for new start" );
          }
          //myState = sm_idling;
          break; // immediately jump down to END-OF-SWITCH
        } //END-OF-SWITCH
      }

      // easy to use helper-function for non-blocking timing
      boolean TimePeriodIsOver (unsigned long & startOfPeriod, unsigned long TimePeriod) {
        unsigned long currentMillis  = millis();
        if ( currentMillis - startOfPeriod >= TimePeriod ) {
          // more time than TimePeriod has elapsed since last time if-condition was true
          startOfPeriod = currentMillis; // a new period starts right here so set new starttime
          return true;
        }
        else return false;            // actual TimePeriod is NOT yet over
      }

      void printStateIfChanged(byte p_state) {
        static byte lastState;

        // check if value of p_state is different than last time calling the function
        if (lastState != p_state) {
          // if it IS different
          Serial.print("state changed from ");
          Serial.print(stateName[lastState]);
          Serial.print(" to ");
          Serial.println(stateName[p_state]);
          lastState = p_state; // update lastState to new value
        }
      }

Some of your if blocks are missing closing braces.

Thank you for catching that! I added the missing closing braces. After that, the compiler gave an error message:
duplicate case value
For "case sm_wait1Rev"

I assumed that meant I was calling that same state in the loop multiple times, but each was slightly different, so I made different states for each "waitRev". After that, the code compiled properly!

The problem now though...when I push the Button #2, it doesn't do what I had wanted it to do (quote below):

Instead, when I push Button #2, it does the exact same thing as Button #1, which is: rotate CCW 200 steps, pause for 2 seconds, rotate continuously CW, and when the beam is broken, stop continuous rotation and rotate CW 200 steps, then back to idle.

Any thoughts on why it is skipping/ignoring the additional movement commands I gave for the Button #2 switch?

#include <MobaTools.h>
const byte dirPin  = 2;
const byte stepPin = 3;

const byte sensorPin = 4;
const byte buttonPin1 = 5;
const byte buttonPin2 = 9;

const int STEPS_REVOLUTION = 200;

// modes of operation = states of the state-machine
const byte sm_idling            = 0;
const byte sm_RotFwd1Rev        = 1;
const byte sm_waitRevA          = 2;
const byte sm_PausingA          = 3;
const byte sm_CheckForBeamBreak = 4;
const byte sm_WaitRotBack1Rev   = 5;
const byte sm_waitRevB          = 6;
const byte sm_PausingB          = 7;
const byte sm_waitRevC          = 8;
const byte sm_PausingC          = 9;

// 2D-array of chars for indicating the state
// the state-machine is in with letters instead of a number
// which makes it easier to understand by just reading
const char stateName[][20] = {"sm_idling",
                              "sm_RotFwd1Rev",
                              "sm_waitRevA",
                              "sm_PausingA",
                              "sm_CheckForBeamBreak",
                              "sm_WaitRotBack1Rev"
                              "sm_waitRevB",
                              "sm_PausingB",
                              "sm_waitRevC",
                              "sm_PausingC",
                             };

const byte pressed   = LOW;
const byte unPressed = HIGH;

byte myState = sm_idling;
const int oneRevolution = 200;

unsigned long waitTimer;

MoToStepper myStepMotor(STEPS_REVOLUTION, STEPDIR); // HALFSTEP ist default

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  pinMode(sensorPin, INPUT);
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);

  myStepMotor.attach(stepPin, dirPin);
  myStepMotor.setSpeed( 240 );       // = 24 rotations/Min
  myStepMotor.setRampLen( oneRevolution / 4 );   // = 1/4 Revolution
  myStepMotor.setZero();            // Set reference point for motor 1

  myState = sm_idling;
  Serial.println("press button for start" );

  printStateIfChanged(myState);
}

void loop() {
  // everything happens inside the function myStepperStateMachine
  myStepperStateMachine();
}

void myStepperStateMachine() {

  printStateIfChanged(myState);

  switch (myState) {

    // through the break;-statement each case is mutually exclusive
    case sm_idling:
      // check if button is pressed
      if ( digitalRead(buttonPin1) == pressed) {
        // if button is pressed
        myState = sm_RotFwd1Rev; // change to other state
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_RotFwd1Rev:
      myStepMotor.doSteps(-oneRevolution); // set new targetposition
      myState = sm_waitRevA;
      break; // immediately jump down to END-OF-SWITCH

    // wait for stepper-motor to reach target position
    case sm_waitRevA:
      if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
        waitTimer = millis();        // store snapshot of time as time-reference for waiting
        myState = sm_PausingA;
      }
      break; // immediately jump down to END-OF-SWITCH

    // wait until pausing time is over
    case sm_PausingA:
      // check if 2000 milliseconds have passed by (since waitTimer = millis(); )
      if ( TimePeriodIsOver(waitTimer, 2000)  ) {
        // if REALLY 2000 milliseconds have passed by
        myStepMotor.rotate(1);  // start continous rotating // opposite direction is .rotate(-1);
        myState = sm_CheckForBeamBreak;
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_CheckForBeamBreak:
      if ( digitalRead(sensorPin) == pressed) {
        myStepMotor.stop();                  // stop continous rotation
        Serial.print("Beam interrupted at step-position ");
        Serial.println(myStepMotor.readSteps() );
        // start rotation one rev CW
        myStepMotor.doSteps(oneRevolution);
        Serial.println("rotating back to step-position " );
        // as the step-pulses are created in the backround
        // code executes the lines below
        myState = sm_WaitRotBack1Rev;
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_WaitRotBack1Rev:
      //if ( !myStepMotor.moving() ) { // if motor has reached target-position
      if ( myStepMotor.distanceToGo() == 0 ) {
        Serial.println(myStepMotor.readSteps() );
        myState = sm_idling;
        Serial.println("press button for new start" );
      }
      //myState = sm_idling;
      break; // immediately jump down to END-OF-SWITCH
  } //END-OF-SWITCH

  switch (myState) {

    // through the break;-statement each case is mutually exclusive
    case sm_idling:
      // check if button is pressed
      if ( digitalRead(buttonPin2) == pressed) {
        // if button is pressed
        myState = sm_RotFwd1Rev; // change to other state
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_RotFwd1Rev:
      myStepMotor.doSteps(-oneRevolution); // set new targetposition
      myState = sm_waitRevB;
      break; // immediately jump down to END-OF-SWITCH

    // wait for stepper-motor to reach target position
    case sm_waitRevB:
      if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
        waitTimer = millis();        // store snapshot of time as time-reference for waiting
        myState = sm_PausingB;
      }
      break; // immediately jump down to END-OF-SWITCH

    // wait until pausing time is over
    case sm_PausingB:
      // check if 2000 milliseconds have passed by (since waitTimer = millis(); )
      if ( TimePeriodIsOver(waitTimer, 2000)  ) {
        // if REALLY 2000 milliseconds have passed by
        myStepMotor.doSteps(oneRevolution); // set new targetposition
        myState = sm_waitRevC;
        break; // immediately jump down to END-OF-SWITCH
      }
    // wait for stepper-motor to reach target position
    case sm_waitRevC:
      if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
        waitTimer = millis();        // store snapshot of time as time-reference for waiting
        myState = sm_PausingC;
      }
      break; // immediately jump down to END-OF-SWITCH

    // wait until pausing time is over
    case sm_PausingC:
      // check if 1500 milliseconds have passed by (since waitTimer = millis(); )
      if ( TimePeriodIsOver(waitTimer, 1500)  ) {
        // if REALLY 1500 milliseconds have passed by
        myStepMotor.doSteps(-oneRevolution); // set new targetposition
        myState = sm_waitRevA;
        break; // immediately jump down to END-OF-SWITCH
      }
    // wait for stepper-motor to reach target position
    case sm_waitRevA:
      if ( !myStepMotor.moving() ) { // if motor HAS reached target-position
        waitTimer = millis();        // store snapshot of time as time-reference for waiting
        myState = sm_PausingA;
      }
      break; // immediately jump down to END-OF-SWITCH

    // wait until pausing time is over
    case sm_PausingA:
      // check if 2000 milliseconds have passed by (since waitTimer = millis(); )
      if ( TimePeriodIsOver(waitTimer, 2000)  ) {
        // if REALLY 2000 milliseconds have passed by
        myStepMotor.rotate(1);  // start continuous rotating // opposite direction is .rotate(-1);
        myState = sm_CheckForBeamBreak;
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_CheckForBeamBreak:
      if ( digitalRead(sensorPin) == pressed) {
        myStepMotor.stop();                  // stop continuous rotation
        Serial.print("Beam interrupted at step-position ");
        Serial.println(myStepMotor.readSteps() );
        // start rotation one rev CW
        myStepMotor.doSteps(oneRevolution);
        Serial.println("rotating back to step-position " );
        // as the step-pulses are created in the background
        // code executes the lines below
        myState = sm_WaitRotBack1Rev;
      }
      break; // immediately jump down to END-OF-SWITCH

    case sm_WaitRotBack1Rev:
      //if ( !myStepMotor.moving() ) { // if motor has reached target-position
      if ( myStepMotor.distanceToGo() == 0 ) {
        Serial.println(myStepMotor.readSteps() );
        myState = sm_idling;
        Serial.println("press button for new start" );
      }
      //myState = sm_idling;
      break; // immediately jump down to END-OF-SWITCH
  } //END-OF-SWITCH
}

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long & startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

void printStateIfChanged(byte p_state) {
  static byte lastState;

  // check if value of p_state is different than last time calling the function
  if (lastState != p_state) {
    // if it IS different
    Serial.print("state changed from ");
    Serial.print(stateName[lastState]);
    Serial.print(" to ");
    Serial.println(stateName[p_state]);
    lastState = p_state; // update lastState to new value
  }
}