Stepper Motors Twitching when I Try To Control Them By Bluetooth

*** I am using a HC-05 Bluetooth Module to connect the Arduino Bluetooth Controller Android App to my Arduino Uno Wifi R4. My bluetooth module can connect easily to my phone and also to the app. The stepper motors work FINE when they are NOT being handled by an external controller (my phone). Any advice?*** My code is attatched below.:slight_smile:

/*
// Stepper motor pins
const int stepPinX = 2;
const int dirPinX  = 5;
const int stepPinY = 3;
const int dirPinY  = 6;

const int stepDelay = 500; // microseconds

bool motorsEnabled = false;

void setup() {
  // Motor pins
  pinMode(stepPinX, OUTPUT);
  pinMode(dirPinX, OUTPUT);
  pinMode(stepPinY, OUTPUT);
  pinMode(dirPinY, OUTPUT);

  // Initial direction
  digitalWrite(dirPinX, HIGH);
  digitalWrite(dirPinY, HIGH);

  // Start serial for Bluetooth communication
  Serial.begin(9600);
}

void loop() {
  // Check for Bluetooth input
  if (Serial.available()) {
    char command = Serial.read();
    if (command == 'START') {
      motorsEnabled = true;
    } else if (command == 'STOP') {
      motorsEnabled = false;
    }
  }

  // Only step motors if enabled
  if (motorsEnabled) {
    digitalWrite(stepPinX, HIGH);
    digitalWrite(stepPinY, HIGH);
    delayMicroseconds(stepDelay);

    digitalWrite(stepPinX, LOW);
    digitalWrite(stepPinY, LOW);
    delayMicroseconds(stepDelay);
  }
}
*/

For one thing, when you ask Serial.read(), only ONE character is read! Then you test for various commands after reading a single character. WHY??

This will not work. Use the string.h library to compare two character strings (delimited with double quotes) in C/C++, using strcmp() or strncmp().

You can compare one character to another character as follows
if (command == 'S') {

Earlier replies tell why. A tip is use single character comands.

Welcome to the forum!

First, I would recommend disabling the motors at the end of the setup() function, so that they remain disabled in case your loop() function is not controlling the motors (which is what is currently happening); for example, add the following after setting the initial direction values:

    digitalWrite(stepPinX, LOW);
    digitalWrite(stepPinY, LOW);

Second, to debug your Bluetooth commands, add the following statement inside the if(motorsEnabled) block in your loop() function, to allow you to check what is happening using the Serial Monitor in the IDE:

Serial.println("Motors enabled and stepping.");

Finally, because Serial communication can be unreliable when the connection is first made, I would suggest adding the following statement at the end of your setup() function, just after the Serial.begin(9600) statement:

delay(1000);
Serial.println("Serial communication established.");
Serial.println("Motors disabled.");

Thank you. I implemented the suggestions in here including using the string.h library but my below code still causes the motors to twitch - any other suggestion would be beyond helpful.

#include <string.h>  // Required for strcmp()

// Stepper motor pins
const int stepPinX = 2;
const int dirPinX  = 5;
const int stepPinY = 3;
const int dirPinY  = 6;

const int stepDelay = 500; // microseconds

bool motorsEnabled = false;

char commandBuffer[20];  // Buffer to store incoming command
byte bufferIndex = 0;

void setup() {
  // Motor pins
  pinMode(stepPinX, OUTPUT);
  pinMode(dirPinX, OUTPUT);
  pinMode(stepPinY, OUTPUT);
  pinMode(dirPinY, OUTPUT);

  // Initial direction
  digitalWrite(dirPinX, HIGH);
  digitalWrite(dirPinY, HIGH);

  // Start serial for Bluetooth communication
  Serial.begin(9600);
  digitalWrite(stepPinX, LOW);
  digitalWrite(stepPinY, LOW);
  
}

void loop() {
  // Read characters into buffer until newline
  while (Serial.available()) {
    char c = Serial.read();

    if (c == '\n') {
      commandBuffer[bufferIndex] = '\0';  // Null-terminate the string

      // Compare commands
      if (strcmp(commandBuffer, "START") == 0) {
        motorsEnabled = true;
      } else if (strcmp(commandBuffer, "STOP") == 0) {
        motorsEnabled = false;
      }

      bufferIndex = 0;  // Reset buffer for next command
    } else {
      if (bufferIndex < sizeof(commandBuffer) - 1) {
        commandBuffer[bufferIndex++] = c;
      }
    }
  }

  // Only step motors if enabled
  if (motorsEnabled) {
    digitalWrite(stepPinX, HIGH);
    digitalWrite(stepPinY, HIGH);
    delayMicroseconds(stepDelay);

    digitalWrite(stepPinX, LOW);
    digitalWrite(stepPinY, LOW);
    delayMicroseconds(stepDelay);
  }
}



There is nothing obviously wrong with the code, except that expecting the motors to step 1000 steps/second, starting from zero, may be unrealistic.

Test that by removing the serial input and running the resulting code:

#include <string.h>  // Required for strcmp()

// Stepper motor pins
const int stepPinX = 2;
const int dirPinX  = 5;
const int stepPinY = 3;
const int dirPinY  = 6;

const int stepDelay = 500; // microseconds

bool motorsEnabled = false;

char commandBuffer[20];  // Buffer to store incoming command
byte bufferIndex = 0;

void setup() {
  // Motor pins
  pinMode(stepPinX, OUTPUT);
  pinMode(dirPinX, OUTPUT);
  pinMode(stepPinY, OUTPUT);
  pinMode(dirPinY, OUTPUT);

  // Initial direction
  digitalWrite(dirPinX, HIGH);
  digitalWrite(dirPinY, HIGH);

  // Start serial for Bluetooth communication
  Serial.begin(9600);
  digitalWrite(stepPinX, LOW);
  digitalWrite(stepPinY, LOW);
  
}

void loop() {
    digitalWrite(stepPinX, HIGH);
    digitalWrite(stepPinY, HIGH);
    delayMicroseconds(stepDelay);

    digitalWrite(stepPinX, LOW);
    digitalWrite(stepPinY, LOW);
    delayMicroseconds(stepDelay);
 }

I would still suggest using print() statements to the Serial Monitor to check what is happening.

Also, how come your code does not use any BLE libraries, like ArduinoBLE or BluetoothSerial?