Problem in controlling stepper

hello
i control stepper using joystick thru esp32
and i mapped the joystick reading from 0 , 4095 to 0 ,255

my joystick readings after mapping is about 169 or 170
And its on other esp32 code

that's the motherboard code

#include "BLEDevice.h"  // Bluetooth libray
#include <Stepper.h>    // Libray to control unipolar or bipolar stepper motors

#define enablePin 12  // enablePin allows to activate or deactivate the motor, for example, the motor is activated only when you move the joystick
#define stepPin 14
#define dirPin 15
#define limitSwitchLeft 16
#define limitSwitchRight 17
#define ledSensor 18
#define solenoidPin 32

const int stepsPerRevolution = 200;  // One revolution = 360° so step angle is 1.8⁰, 1.8 x 200 = 360. More steps = More precision
int xPosition = 115;
uint8_t score = 10;  // Default number of points
uint8_t newScore = 10;
int solenoidValue = 0;
int solenoidState = 1;

TaskHandle_t xHandle = NULL;

// initialize stepper library
Stepper stepper(stepsPerRevolution, stepPin, dirPin);

// BLUETOOTH IDENTIFIERS - The associated gamepad has the same identifiers, that's why they can communicate with each other
// The service ID.
static BLEUUID serviceUUID("69159f1c-f430-11ea-adc1-0242ac120002");
// The position X characteristic ID.
static BLEUUID charPositionXUUID("ac82943a-f430-11ea-adc1-0242ac120002");
// The score characteristic ID.
static BLEUUID charScoreUUID("c2de5a5c-f430-11ea-adc1-0242ac120002");
// The solenoid characteristic ID.
static BLEUUID charSolenoidUUID("dc92348c-f430-11ea-adc1-0242ac120002");
// END BLUTOOTH IDENTIFIERS

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristicPositionX;
static BLERemoteCharacteristic* pRemoteCharacteristicScore;
static BLERemoteCharacteristic* pRemoteCharacteristicSolenoid;
static BLEAdvertisedDevice* myDevice;

// BLUETOOTH data transfer functions
static void notifyCallbackPositionX(
  BLERemoteCharacteristic* pBLERemoteCharacteristicPositionX,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
  for (int i = 0; i < length; i++) {
    xPosition = pData[i];
  }
}

static void notifyCallbackSolenoid(
  BLERemoteCharacteristic* pBLERemoteCharacteristicSolenoid,
  uint8_t* pDataSolenoid,
  size_t length,
  bool isNotify) {
  for (int i = 0; i < length; i++) {
    solenoidValue = pDataSolenoid[i];
  }
}

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
  }
};

bool connectToServer() {

  BLEClient* pClient = BLEDevice::createClient();

  pClient->setClientCallbacks(new MyClientCallback());

  // Connect to the remove BLE Server.
  pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)

  // Obtain a reference to the service we are after in the remote BLE server.
  BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
  if (pRemoteService == nullptr) {
    pClient->disconnect();
    return false;
  }


  // Obtain a reference to the characteristic POSITION_X in the service of the remote BLE server.
  pRemoteCharacteristicPositionX = pRemoteService->getCharacteristic(charPositionXUUID);
  if (pRemoteCharacteristicPositionX == nullptr) {
    pClient->disconnect();
    return false;
  }

  // Obtain a reference to the characteristic SCORE in the service of the remote BLE server.
  pRemoteCharacteristicScore = pRemoteService->getCharacteristic(charScoreUUID);
  if (pRemoteCharacteristicScore == nullptr) {
    pClient->disconnect();
    return false;
  }

  // Obtain a reference to the characteristic POSITION_X in the service of the remote BLE server.
  pRemoteCharacteristicSolenoid = pRemoteService->getCharacteristic(charSolenoidUUID);
  if (pRemoteCharacteristicSolenoid == nullptr) {
    pClient->disconnect();
    return false;
  }

  // Read the value of the characteristic.
  if (pRemoteCharacteristicPositionX->canRead()) {
    std::string value = pRemoteCharacteristicPositionX->readValue();
  }

  if (pRemoteCharacteristicPositionX->canNotify())
    pRemoteCharacteristicPositionX->registerForNotify(notifyCallbackPositionX);

  // Read the value of the characteristic.
  if (pRemoteCharacteristicSolenoid->canRead()) {
    std::string value = pRemoteCharacteristicSolenoid->readValue();
  }

  if (pRemoteCharacteristicSolenoid->canNotify())
    pRemoteCharacteristicSolenoid->registerForNotify(notifyCallbackSolenoid);

  connected = true;
  return true;
}
/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 */
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {

    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {

      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;

    }  // Found our server
  }    // onResult
};     // MyAdvertisedDeviceCallbacks
// END BLUETOOTH data transfer functions

// This function is executed when the joystick moves. Short explanation: a joystick permanently sends a value between 0 and 255 depending on its location.
void moveXAxis(void* parameter) {
  for (;;) {
    digitalWrite(enablePin, HIGH);  // Motor disabled

    // If the joystick sends a value between 100 and 130, it means that it is in the center and does not move, the motor are therefore stopped
    if ((xPosition > 150) && (xPosition < 190)) {  // If the motor trigger on their own without touching the joystick it means that the joystick send values lower than 100 and greater than 130 when not touching it, this is a joystick issue, open the gamepad code and monitor the values of the joystick.
      digitalWrite(stepPin, LOW);
      digitalWrite(enablePin, HIGH);  // Motor disabled
    }

    // If the joystick sends a value greater than 130 then it means it has been moved to one side, the motor are therefore activated
    while (xPosition >= 190) {
      int speed_ = map(xPosition, 190, 245, 1200, 1500);  // This means that between the value 130 and 230 sent by the joystick, the speed will go from 900 to 1600. If for example the joystick is moved very slightly, the speed will be 900, if on the other hand the joystick is moved to the maximum, the speed will be 1600. If your motor stalls, the last thing to try is to lower the maximum speed to 1500 for example but this is not a good solution because this side will go slower than the others, try all the other solutions before or change the motor if it is faulty.
      stepper.setSpeed(speed_);

      if (digitalRead(limitSwitchLeft) == HIGH) {  // If limit switch left is not triggered
        digitalWrite(enablePin, LOW);              // Motor enabled
        stepper.step(-1);                          // Move in first direction
      } else {                                     // If limit switch left is triggered
        digitalWrite(enablePin, HIGH);             // Motor disabled - Can so only move in other direction
      }
    }

    // If the joystick sends a value lower than 100 then it means it has been moved to the other side, the motor are therefore activated
    while (xPosition <= 120) {
      int speed_ = map(xPosition, 120, 10, 1200, 1500);  // This means that between the value 100 and 20 sent by the joystick, the speed will go from 900 to 1600. If for example the joystick is moved very slightly, the speed will be 900, if on the other hand the joystick is moved to the maximum, the speed will be 1600. If your motor stalls, the last thing to try is to lower the maximum speed to 1500 for example but this is not a good solution because this side will go slower than the others, try all the other solutions before or change the motor if it is faulty.
      stepper.setSpeed(speed_);

      if (digitalRead(limitSwitchRight) == HIGH) {  // If limit switch right is not triggered
        digitalWrite(enablePin, LOW);               // Motor enabled
        stepper.step(1);                            // Move in second direction
      } else {                                      // If limit switch right is triggered
        digitalWrite(enablePin, HIGH);              // Motor disabled - Can so only move in other direction
      }
    }
  }
}

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enablePin, OUTPUT);
  pinMode(limitSwitchLeft, INPUT_PULLUP);
  pinMode(limitSwitchRight, INPUT_PULLUP);
  pinMode(solenoidPin, OUTPUT);
  pinMode(ledSensor, INPUT);
  digitalWrite(enablePin, HIGH);

  BLEDevice::init("");

  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  pBLEScan->setActiveScan(true);
  pBLEScan->start(0, false);

  // The moveXAxis function is started in multitasking, not in the main loop() function
  xTaskCreate(
    moveXAxis,      // Function that should be called
    "move X axis",  // Name of the task (for debugging)
    1000,           // Stack size (bytes)
    NULL,           // Parameter to pass
    1,              // Task priority
    &xHandle        // Task handle
  );
}  // End of setup.


// This is the Arduino main loop function.
void loop() {

  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are
  // connected we set the connected flag to be true.

  if (doConnect == true) {
    if (connectToServer()) {
      pRemoteCharacteristicScore->writeValue(score);
    }
    doConnect = false;
  } else {
    // If Gamepad and Motherboard are connected together
    if (connected) {

      if (score >= 1) {                         // If the player has not lost the game
        int detected = digitalRead(ledSensor);  // Contains the value of the receiver laser

        if (solenoidValue == 1) {  // If the button to trigger the solenoid is pressed on the gamepad

          if (solenoidState == 1) {           // This prevents from keeping the button pressed, it would heat up the solenoid
            digitalWrite(solenoidPin, HIGH);  // The solenoid is on
            delay(80);                        // Changing this delay can vary the hitting power
            digitalWrite(solenoidPin, LOW);   // The solenoid is off
          }
          solenoidState = 0;  // The solenoid has been activated, its state is set to 0, the state will return to 1 when the button is no longer pressed
        } else {
          solenoidState = 1;               // The button to trigger the solenoid is not pressed, the state is 1 wich means "Ready"
          digitalWrite(solenoidPin, LOW);  // The solenoid is off
        }

        if (detected == 0) {                                  // If the laser beam has been deflected by an obstacle
          newScore = score - 1;                               // The player loses a point
          pRemoteCharacteristicScore->writeValue(score - 1);  // The score is sent to the gamepad to turn off a led

          if (newScore >= 1) {  // If the player has not lost
            delay(700);         // The laser receiver is stopped for 700ms, this avoids losing several points at once if, for example, the ball has crossed the laser beam at low speed
          }
        }

        score = newScore;
      }

    } else if (doScan) {
      BLEDevice::getScan()->start(50);  // This try to reconnect the bluetooth if disconnected
    }
  }

  delay(10);  // All the loop function has a slight delay otherwise it prevents the bluetooth from connecting, you can try to increase this value if your blutooth gamepad does not connect to the motherboard
}  // End of loop


my stepper is moving without touching the joystick
video for the problem

where's the problem why its moving to right without even touching the joystick
thanks

full code pls

1 Like

have a read thru how-to-get-the-best-out-of-this-forum
put some Serial.println() statements in the code to print the values of critical variables and show the flow of program control
then upload code plus the corresponding output of the serial monitor

1 Like

thanks i updated with full code
i use esp32 with joystick connected to other esp32 in the board

sorry i didn't and i'm a beginner could you tell me which values exactly i could print to help
thanks

for example in the loop print xPosition

void moveXAxis(void* parameter) {
  for (;;) {
     Serial.println(xPosition);

look at your control algorithm - if there are variables which may change and effect the operation print the values at critical points to give you some idea what is happening

i see 2 places in the code using map(). neither is as you say

  int speed_ = map(xPosition, 190, 245, 1200, 1500);
  int speed_ = map(xPosition, 120, 10, 1200, 1500); 
1 Like

Its already done in the controller esp32 code
Not the mother board attached code
Sorry for not mention that before

Joystick readings before mapping
0,4095
Joystick readings after mapping
0,255
Joystick without touching after mapping
170

Sorry for saying that
But i mean mapping the joys tick readings on the controller esp32
Not the mother board oard attached code

what do you mean "mother board"?

what code has the problem that you describe?

// BLUETOOTH data transfer functions
static void notifyCallbackPositionX(
  BLERemoteCharacteristic* pBLERemoteCharacteristicPositionX,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
  for (int i = 0; i < length; i++) {
    xPosition = pData[i];
  }
}

static void notifyCallbackSolenoid(
  BLERemoteCharacteristic* pBLERemoteCharacteristicSolenoid,
  uint8_t* pDataSolenoid,
  size_t length,
  bool isNotify) {
  for (int i = 0; i < length; i++) {
    solenoidValue = pDataSolenoid[i];
  }
}

strange construction, in loop will variable overwritten until end of array. what you try to do here?



#define LeftRimOK digitalRead(limitSwitchLeft)
#define RightRimOK digitalRead(limitSwitchRight)
#define MotorSTOP (digitalWrite(enablePin,HIGH))
#define MotorEnable (digitalWrite(enablePin,LOW))

// This function is executed when the joystick moves.
//Short explanation: a joystick permanently sends a value between 0 and 255 depending on its location. Middlepoint is 170
void moveXAxis(void* parameter) {
  for (;;) {
    int pos = xPosition - 170;
    stepper.setSpeed(abs(pos) * 2 + 1200);

    if (abs(pos) < 10) MotorSTOP;
    else {
      MotorEnable;

      while (pos >= 10) {
        if (LeftRimOK)stepper.step(-1);                          // Move in first direction
        else MotorSTOP ;                                                 // If limit switch left is not triggered
      }
      while (pos <= -10) {
        if (RightRimOK)stepper.step(1);                            // Move in second direction
        else MotorSTOP;                                                     // If limit switch right is not triggered
      }
    }
  }
}

Hi @osamaghamry

welcome to the arduino-forum.
Well done to post your code as a code-section in the very first posting.

I want to give some general advice that will help a lot to solve your problems faster .

English seems not to be your native language and it seems that your english is somehow limited.

Your postings contains only very short descriptions. These descriptions are too short to be understandable.

My estimation is: if you go on posting such short postings it will take three days and 20 to 50 postings just to make clear what the problem is. But not yet solving your problem!

This is the reason why I highly recommend that you write your postings in two steps.
Applying these two steps will speed up solving your problems very much.

step 2: copy & paste the result.
huh ? what is step 1??
step 1 is to write a very detailed description.
You may think "my english is limited I can't write much in english"
That's right. And that is the reason why you should write the posting in your native language and then let do google-translate translate your detailed long posting to english
and then
step 2 : post the translated result.

You seem to be a beginner and posted a highly complex code from which I doubt that you have written this code yourself.

You are already at the stage of sending data from one ESP32 to another ESP32 and then control a stepper-motor.
There are about 50 possible places where your problem can be.

Would you like to check 50 * 50 = 2500 different code-versions trying to make it work?
Surely not!
It will be much more efficient to step back to a much simpler code which has only 3 places where the bug might be and to test 3 code-versions to make this smaller code work.

And then test the next part.
And then test the next part.
etc. etc.

The first thing to do is writing down a detailed 20 to 50 sentences long description of your project in your native language and then let translate google to english

best regards Stefan

thanks so much stefan for your advice , you are right
i'll consider all of that next time
of course i didn't write that code i bought it with some project and it should work as it is ,
but it didn't with me , so i tried to figure out how to solve it by asking here
and i may write this post again with the two steps
i was just in hurry this time
thanks

thanks so much for your effort i'll try it and comeback with the result

There are a few potential reasons why you may be having trouble controlling a stepper motor, and the solution will depend on the specifics of the problem you are encountering. Here are a few troubleshooting steps to consider:

  1. Check your wiring: Stepper motors require a specific wiring configuration, so make sure that you have wired the motor correctly. Check the datasheet for your particular motor to ensure that you have connected the wires properly.
  2. Check your power supply: Stepper motors require a sufficient power supply to operate correctly. Make sure that the voltage and current provided by your power supply are appropriate for your motor.
  3. Check your driver: Stepper motors require a driver to control their movement. Make sure that your driver is compatible with your motor and that it is configured correctly. Check the datasheet for your driver to ensure that you have set the correct microstepping mode and current limit.
  4. Check your control signal: If you are using a microcontroller or other device to control your stepper motor, make sure that the signal being sent is correct. Check your code to ensure that you are sending the correct signals to the driver.
  5. Check your mechanical setup: Stepper motors can sometimes encounter mechanical resistance that can prevent them from moving correctly. Make sure that your mechanical setup is free from obstructions and that the motor is properly mounted.

By troubleshooting these potential issues, you may be able to identify the source of the problem and resolve it.

did you ask chatGPT? did you even read post #1?

thanks so much for all your effort
i found the problem was in the wiring the joystick
i supposed to connect the 5v pin of joystick to 3v pin on the esp not 5v pin as written
and now worked good

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