Arduino UNO R4 Minima - I can send keystrokes, or I can control a stepper motor. But I can't do both things in the same sketch

Dear all,
years ago I made a successful sketch to control a microscope Z-stage via Arduino + serial monitor.
The only library included is AccelStepper.h and the sketch accepts keyboard input to perform the desired kind of rotation.

The full sketch with comments and details is available here: http://www.cesarebrizio.it/Arduino/Z-Stage.html

Now I needed to implement the sketch in such a way that, after each movement, the sketch simulates a F1 keypress. To that purpose, I purchased an Arduino 1 R4 Minima, that guarantees compatibility with the Keyboard.h library.

First, I tried my original sketch on my new Arduino 1 R4 Minima: it works flawlessly!

Then, I prepared a new version of the sketch that sends a F1 keypress after each stepper.run();
I just added a Keyboard.begin(); in the setup and the following three lines after the stepper.run();

  Keyboard.press(KEY_F1);
  delay(100);
  Keyboard.releaseAll();

The F1 keypresses are sent as expected, but the stepper is never activated.

I suspect that there is some incompatibility between AccelStepper.h and Keyboard.h.

Perhaps some expert user can educate me?

One more question. The main loop of the original version of the sketch is waiting for keys sent via the Serial Monitor of the Arduino IDE, by pressing the desired key + enter.

  if (Serial.available() > 0) 
  {
    incomingByte = Serial.read();
    {
      if (incomingByte == 'R') ....

Now, it looks like Serial.available() is always > 0, even when I'm not sending any character via the Serial Monitor of the Arduino IDE.

Thank you for your much welcome help!

Cesare Brizio

So, read and print the extra characters and see what they are. Print in HEX.

Thanks Paul,
I have found that every time i call the Keyboard.releaseAll() function I receive a line feed character.
I modified the source code to ignore it.
My serial monitor input is regularly received, but the stepper is still inactive.
It must be an issue of incompatibility among libraries.

Usually you also have a carriage return character. Did your serial.Print() show more than 1 character?

You are pointing me in an interesting direction.
Right now, I have another issue, I can't upload the program for whatever reason. Unfortunately right now I have to go, thanks for your help, I'll get back to you next week.

Hopefully that is the direction of learning how to debug your program. Good luck!

I succeeded in a last ditch attempt. Two quick pressures on the reset button restored the capability to upload. Now I can safely state that I don't get any other character than chr(10) when calling Keyboard.releaseAll().
Thanks to your advice, I restructured the loop as needed. If I get that character or any other meaningless character, nothing happens.
Now, with a working loop and rock-solid "if's", we are back where we started.
The same commands, stepper.moveTo() and stepper.Run() that work flawlessly, cease to work as soon as i include Keyboard.h and add the lines related with that library (Keyboard.begin() etc...).

The documentation doesn't help: Keyboard - Arduino Reference

To control the stepper motor, I use the 4, 5, 6 and 7 digital pins. May some contraindication be there, e.g., the keyboard library grabbing control of those same pins (excuse my english!) ?

**I'm still stuck. **
Now, with a working loop and rock-solid "if's", we are back where we started.
The same commands, stepper.moveTo() and stepper.Run() that work flawlessly, cease to work as soon as i include Keyboard.h and add the lines related with that library (Keyboard.begin() etc...).

Hi @Delta_G and thank you for your suggestion to post the full code. Please find it here.
I didn't post it before because I was hoping that someone who incurred in the same problem may enlighten me with answers about general compatibility issues between keyboard.h and accelStepper.h.

Here is the full code: again, if I omit including keyboard.h and the keyboard-related lines from the very same code, I can control the stepper by sending keys from the serial monitor as usual.

Many thanks for your help.

Cesare

/*
 
Stepper-based microscope Z-stage

Circuit and comments: 
See http://www.cesarebrizio.it/Arduino/Z-Stage.html
Circuit is as illustrated here:
https://www.tdegypt.com/wp-content/uploads/2017/08/stepper-motor-wiring.png
the only exception being that the sketch uses digital outputs 4 - 5 - 6 - 7
while the Fritzing diagram uses digital outputs 8 - 9 - 10 - 11
 
 created 9 Jan 2021
 modified 9 Feb 2024 - added a "send keyboard press after each step"
 by Cesare Brizio
 
This example code is in the public domain.

This sketch controls the rotation of the knob of a microscope Z-stage 
based on a stepper motor and custom-made mechanical coupling.
Stepper model is 28BYJ48, controlled via the X113647 Stepper Motor 
Driver (based on the ULN2003A IC) normally purchased with the stepper.  

The knob can rotate 360 degrees in both direction. 
Commands for incremental rotation are provided.
The platform is managed by serial dialogue, managed via Serial Monitor 
or Tera Term.
The following commands are implemented:
---> continuous rotation
R = Rotate clockwise continuously (meaning: for several turns)
L = Rotate counter-clockwise continuously (meaning: for several turns)
S = Stop rotating
---> 360° continuous rotation
r = Rotate for 360° clockwise
l = Rotate for 360° counter-clockwise
---> rotation by small increments
k = rotate 4° clockwise
K = rotate 4° counter-clockwise
f = rotate 5° clockwise
F = rotate 5° counter-clockwise
t = rotate 10° clockwise
T = rotate 10° counter-clockwise
w = rotate 20° clockwise
W = rotate 20° counter-clockwise
q = rotate 40° clockwise
Q = rotate 40° counter-clockwise

It's very obvious that the source code could be optimized, but I preferred to keep 
a repetitive structure with a separate IF for each possible value of incomingByte.
 
Sources of information:
Small stepper control: http://arduino-info.wikispaces.com/SmallSteppers

*/

/*-----( Import needed libraries )-----*/
#include <AccelStepper.h>
#include <Keyboard.h> // Needed only if keyboard stroke is to be sent (REQUIRES Arduino UNO R4 Minima)

/*-----( Declare Constants and Pin Numbers )-----*/
/* NEVER PUT ; AFTER A #define statement!!!! */
// motor pins
#define motorPin1  4     // Blue   - 28BYJ-48 pin 1
#define motorPin2  5     // Pink   - 28BYJ-48 pin 2
#define motorPin3  6     // Yellow - 28BYJ-48 pin 3
#define motorPin4  7     // Orange - 28BYJ-48 pin 4
                        // Red    - 28BYJ-48 pin 5 (VCC)
                        // Blue   - 28BYJ-48 pin GND  
#define STEPS_PER_TURN 2048 // number of steps in 360°
#define STEPS_PER_FOUR 22 // number of steps in 4°
#define STEPS_PER_FIVE 28 // number of steps in 5°
#define STEPS_PER_TEN 57 // number of steps in 10°
#define STEPS_PER_TWENTY 114 // number of steps in 20°
#define STEPS_PER_FORTY 228 // number of steps in 40°

int motorSpeed = 500; // High speeds (800 and above) may cause erratic behavior in 28BYJ-48
int motorAccel = 400; // As above: better avoiding extreme accelerations
int myPos = 0; // will be used to define a starting point for 360° rotations
int LeftTurnUp = 0; // Couple of flags to determine rotation direction
int RightTurnDown = 0; // Couple of flags to determine rotation direction
int Continuous = 2; // used below to discriminate single rotation commands
// Continuous will be set to 1 or 0 only when a valid command character will be received
int incomingByte = 0; // for incoming serial data
int STEPS_TO_DO = 0; // to allocate the number of steps needed to perform the required rotation

/*-----( Objects for stepper control )-----*/
// Set up the stepper as 4 wire bipolar on pin 4,5,6,7
// NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ48
AccelStepper stepper(4,motorPin1,motorPin3,motorPin2,motorPin4); 

void setup()
{
  Serial.begin(9600);
  stepper.setMinPulseWidth(20); // Advisable setting to avoid that pulses from Arduino
                                // are too quick to be decoded
  stepper.setMaxSpeed(motorSpeed);
  stepper.setSpeed(motorSpeed);
  stepper.setAcceleration(motorAccel);
  // the following two lines reset "step zero" to the current position
  stepper.setCurrentPosition(stepper.currentPosition());
  stepper.runToPosition();
  Serial.println("Available commands:");
  Serial.println("====> Continuous rotation");
  Serial.println("R = continuous clockwise rotation");
  Serial.println("L = continuous counter-clockwise rotation");
  Serial.println("S = stop rotation");
  Serial.println("====> 360° Rotation");
  Serial.println("o = 360° clockwise rotation");
  Serial.println("O = 360° counter-clockwise rotation");
  Serial.println("====> Rotation by small increments");
  Serial.println("k = rotate 4° clockwise");
  Serial.println("K = rotate 4° counter-clockwise");
  Serial.println("f = rotate 5° clockwise");
  Serial.println("F = rotate 5° counter-clockwise");
  Serial.println("t = rotate 10° clockwise");
  Serial.println("T = rotate 10° counter-clockwise");
  Serial.println("w = rotate 20° clockwise");
  Serial.println("W = rotate 20° counter-clockwise");
  Serial.println("q = rotate 40° clockwise");
  Serial.println("Q = rotate 40° counter-clockwise");
  Keyboard.begin(); // required to initialize the communication with the keyboard
}

void loop()
{

  if (Serial.available() > 0) 
  {
    Serial.println("Serial.available() > 0");
    incomingByte = Serial.read();
    Serial.print("Received ");
    Serial.println(incomingByte);

    {
      if (incomingByte == 'R')
      {
        Serial.println("received «R» - activating continuous clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 1;
        Continuous = 1; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
      } 
      
      if (incomingByte == 'L')
      {
        Serial.println("received «L» - activating continuous counter-clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        RightTurnDown = 0;
        LeftTurnUp = 1;
        Continuous = 1; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
      }

      if (incomingByte == 'S')
      {
        Serial.println("received «S» - stopping rotation");
        // Reset the flags that determine rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 0;
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
      } 

      if (incomingByte == 'o')
      {
        Serial.println("received «o» - activating single clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step forward 2047 steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_TURN;
      } 
      
      if (incomingByte == 'O')
      {
        Serial.println("received «O» - activating single counter-clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        RightTurnDown = 0;
        LeftTurnUp = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step backwards 2047 steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_TURN;
      }


      if (incomingByte == 'k')
      {
        Serial.println("received «k» - activating 4° clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step forward STEPS_PER_FIVE steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_FOUR;
      } 
      
      if (incomingByte == 'K')
      {
        Serial.println("received «K» - activating 4° counter-clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        RightTurnDown = 0;
        LeftTurnUp = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step backwards STEPS_PER_FIVE steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_FOUR;
      }


      if (incomingByte == 'f')
      {
        Serial.println("received «f» - activating 5° clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step forward STEPS_PER_FIVE steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_FIVE;
      } 
      
      if (incomingByte == 'F')
      {
        Serial.println("received «F» - activating 5° counter-clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        RightTurnDown = 0;
        LeftTurnUp = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step backwards STEPS_PER_FIVE steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_FIVE;
      }


      if (incomingByte == 't')
      {
        Serial.println("received «t» - activating 10° clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step forward STEPS_PER_TEN steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_TEN;
      } 
      
      if (incomingByte == 'T')
      {
        Serial.println("received «T» - activating 10° counter-clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        RightTurnDown = 0;
        LeftTurnUp = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step backwards STEPS_PER_TEN steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_TEN;
      }



      if (incomingByte == 'w')
      {
        Serial.println("received «w» - activating 20° clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step forward STEPS_PER_TWENTY steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_TWENTY;
      } 
      
      if (incomingByte == 'W')
      {
        Serial.println("received «W» - activating 20° counter-clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        RightTurnDown = 0;
        LeftTurnUp = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step backwards STEPS_PER_TWENTY steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_TWENTY;
      }


      if (incomingByte == 'q')
      {
        Serial.println("received «q» - activating 40° clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        LeftTurnUp = 0;
        RightTurnDown = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step forward STEPS_PER_TWENTY steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_FORTY;
      } 
      
      if (incomingByte == 'Q')
      {
        Serial.println("received «Q» - activating 40° counter-clockwise rotation");
        // The two lines that follow allow to send commands in any sequence:
        // before execution, a quick stop is performed
        stepper.stop(); // Stop as fast as possible: sets new target
        stepper.runToPosition(); // Now stopped after quickstop
        // The following couple of flags determines rotation direction
        RightTurnDown = 0;
        LeftTurnUp = 1;
        Continuous = 0; // used below to discriminate single rotation commands
        stepper.setCurrentPosition(stepper.currentPosition()); // Set step 0 "here"
        stepper.setSpeed(motorSpeed); // Previous commands have reset the speed
        // Since I will have to step backwards STEPS_PER_TWENTY steps, I store my current 
        // position as starting point of the rotation
        myPos=stepper.currentPosition();
        STEPS_TO_DO = STEPS_PER_FORTY;
      }
    }
  }

  if (Continuous == 1) // continuous rotation 
    {

    Serial.println("=================================================================");
    Serial.println("     Variables status before attempting stepper activation"); 
    Serial.println("=================================================================");
    Serial.print("incomingByte ");
    Serial.println(incomingByte);  
    Serial.print("Continuous ");
    Serial.println(Continuous);  
    Serial.print("myPos ");
    Serial.println(myPos);
    Serial.print("STEPS_TO_DO ");
    Serial.println(STEPS_TO_DO);

    if (LeftTurnUp == 1)  //left turn
      {
        stepper.moveTo(10000); //move many steps - more then mechanical needed
    }

    if (RightTurnDown == 1)  //right turn
      {
        stepper.moveTo(-10000); //move many steps - more then mechanical needed      
    }
    stepper.run();
    Serial.println("THAT ONE - You have 10 seconds to change the active window. Keystroke will be sent to the foreground program window.");
    delay(10000);        
    Keyboard.press(KEY_F1);
    delay(100);
    Keyboard.releaseAll();  
    Continuous = 2; // If Continuous is not 1 nor 0, any input different than those admissible will not enter this "If"
    incomingByte = '-';  // IncomingByte is assigned a spurious value to ensure that the current value is not recycled
  }

  if (Continuous == 0) // partial rotation 
    {

    Serial.println("=================================================================");
    Serial.println("     Variables status before attempting stepper activation"); 
    Serial.println("=================================================================");
    Serial.print("incomingByte ");
    Serial.println(incomingByte);  
    Serial.print("Continuous ");
    Serial.println(Continuous);  
    Serial.print("myPos ");
    Serial.println(myPos);
    Serial.print("STEPS_TO_DO ");
    Serial.println(STEPS_TO_DO);

    if (LeftTurnUp == 1)  //left turn
      {
        stepper.moveTo(myPos+STEPS_TO_DO); // number of  steps in 5, 10, 20 or 360°
    }

    if (RightTurnDown == 1)  //right turn
      {
       stepper.moveTo(myPos-STEPS_TO_DO); // number of  steps in 5, 10, 20 or 360°
    }

    stepper.run();
    Serial.println("THIS ONE - You have 10 seconds to change the active window. Keystroke will be sent to the foreground program window.");
    delay(10000);
    Keyboard.press(KEY_F1);
    delay(100);
    Keyboard.releaseAll();
    Continuous = 2; // If Continuous is not 1 nor 0, any input different than those admissible will not enter this "If"
    incomingByte = '-';  // IncomingByte is assigned a spurious value to ensure that the current value is not recycled
  }
} 

Hi @Delta_G ,
I'm very obviously in search of a solution and I didn't mean to look argumentative.
Initially, I wrongly assumed that a solution would take the shape of a suggestion to use different libraries.

I thank you also for clarifying that there's not a compatibility problem.

I would be grateful for any solution or any idea by anyone who may understand where the problem is.

All the best,
Cesare

There are some other strange usages of AccelStepper methods, but this definitely cannot work. During your long delay() no steps are created, so your stepper does not move. AccelStepper needs a blocking free design.
That's not a problem of AccelStepper.h and Keyboard.h.
Alternatively you could use the MobaTools library, which is able to create the steps even during delay().

@MicroBahner Hi Franz-Peter,
many thanks! I am sure that you hit the nail on the head.
In fact, the original, perfectly working version of the same program is lacking both the keyboard library and the delay after the stepper.run(). Silly me for not noticing it! I was very wrong in blaming keyboard.h.

One last question for you, Franz-Peter: right now I can't make tests. In line of principle, do you think that if I move the stepper.run() line after all the Keyboard calls, the stepper may work regularly? Something like:

    Serial.println("THAT ONE - You have 10 seconds to change the active window. Keystroke will be sent to the foreground program window.");
    delay(10000);        
    Keyboard.press(KEY_F1);
    delay(100);
    Keyboard.releaseAll();  
    stepper.run();

Again thank you.

No, that doesn't matter. The run() method creates ONE step at most per call. So to move your stepper you must call run() really, really often.
No matter if you call it before or after your delay(10000), that way it can only create one step every 10 seconds.

Thanks for the clarification.
Now I have just to find a way to send the F1 key before, or after, completing the desired number of steps, and without interfering with the stepper rotation.
I'll find a way!

All the best,
Cesare

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