Assistance required for Accelstepper library and arduino cloud

64 views
Skip to first unread message

Theodoros Karagiannis

unread,
Feb 13, 2025, 8:40:21 AMFeb 13
to accelstepper
Hello, 
I have developed a program using accelstepper library to control a 3-axis stepper motors via Arduino.
The program on its desktop version works perfectly, but when i tried to migrate it to Arduino cloud (in order to control the motors from iPhone), the same code has the following bug, the motors move in a very slow speed and i cannot change their speed. 
I am attaching you the code i am using in the Arduino cloud. Any ideas ?

#include <WiFiNINA.h>
#include <AccelStepper.h>

/*
  Sketch generated by the Arduino IoT Cloud Thing "Untitled"
  https://create.arduino.cc/cloud/things/069dba6c-43b5-42cc-afd0-e62bf37878a1

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  int speedX;
  int stepsX;
  int stepsY;
  bool moveX;
  bool moveY;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"
#include <EEPROM.h>
#include <Bounce2.h>

#define dirPinX 8
#define stepPinX 9

#define dirPinY 7
#define stepPinY 6

#define dirPinZ 4
#define stepPinZ 5

// Define the steppers and pins that are used
//AccelStepper stepper1; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
AccelStepper stepperX(1, stepPinX, dirPinX);
AccelStepper stepperY(1, stepPinY, dirPinY);
AccelStepper stepperZ(1, stepPinZ, dirPinZ);

int x;

// Timing variables
unsigned long lastUpdateX = 0, lastUpdateY = 0, lastUpdateZ = 0;
const unsigned long updateInterval = 5; // 5ms

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500);

  // Defined in thingProperties.h
  initProperties();
 
  pinMode(LED_BUILTIN, OUTPUT);

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  ArduinoCloud.printDebugInfo();
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

  pinMode(stepPinX,OUTPUT);
  pinMode(dirPinX,OUTPUT);
  pinMode(stepPinY,OUTPUT);
  pinMode(dirPinY,OUTPUT);
 
  stepperX.setMaxSpeed(10000);
  stepperY.setMaxSpeed(10000);
  stepperZ.setMaxSpeed(10000);

  stepperX.setAcceleration(8000);
  stepperY.setAcceleration(8000);
  stepperZ.setAcceleration(8000);

  stepperX.disableOutputs();
  stepperY.disableOutputs();
  stepperZ.disableOutputs();

}


void loop() {
  ArduinoCloud.update();
  setDebugMessageLevel(2);

  if (moveX){
    stepperX.runSpeed();
  }
  if(moveY){
    stepperY.runSpeed();
  }

  stepperZ.runSpeed();

}
 
/*
  Since PushbuttonX is READ_WRITE variable, onPushbuttonXChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onPushbuttonXChange()  {
  int x;

}

/*
  Since StepsX is READ_WRITE variable, onStepsXChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onStepsXChange()  {
  Serial.println(stepsX);
}

/*
  Since StepsY is READ_WRITE variable, onStepsYChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onStepsYChange()  {
  // Add your code here to act upon StepsY change
}



void onMoveXChange()  {
  if(moveX){
    unsigned long currentMillis = millis();
    ArduinoCloud.update();
    digitalWrite(LED_BUILTIN, HIGH);
   
    stepperX.enableOutputs();
    stepperX.setMaxSpeed(speedX);
    Serial.println(speedX);
    //stepperX.setSpeed(10000);
    stepperX.move(stepsX);

  } else {
    ArduinoCloud.update();
    stepperX.stop();
    stepperX.disableOutputs();
    digitalWrite(LED_BUILTIN, LOW);
  }
}


void onMoveYChange()  {
  if(moveY) {
    unsigned long currentMillis = millis();
    ArduinoCloud.update();
    digitalWrite(LED_BUILTIN, HIGH);
   
    stepperY.enableOutputs();
    stepperY.setMaxSpeed(5000);
    //stepperY.setSpeed(1000);
    stepperY.move(stepsY);

  } else {
    ArduinoCloud.update();
    stepperY.stop();
    stepperY.disableOutputs();
    digitalWrite(LED_BUILTIN, LOW);
  }
}

void onSpeedXChange() {
    Serial.print("SpeedX updated: ");
    Serial.println(speedX);
    stepperX.setMaxSpeed(speedX);
}

Jim Larson

unread,
Feb 13, 2025, 3:58:07 PMFeb 13
to accelstepper
First, I have no experience with Arduino Cloud. The following is based on a quick look at forum posts and some speculation. You need to do some research and some experimentation. Google is your friend.
My suspicion is that Arduino Cloud and its overhead is slowing the loop down. One Arduino Clod forum post suggests that an update of 20 times a second is reasonable! That means that runSpeed() is only called 20 times persecond - much too slow for proper response.
Another post suggests using two Arduinos (or two cores), one communicating to Arduino Cloud and one controlling the real time activities (motors).
You didn't mention what Arduino board you are using.

Sorry I can't help more. Please post to this forum as you experiment and learn more.

            -jim

Theodoros Karagiannis

unread,
Feb 14, 2025, 2:16:36 AMFeb 14
to accelstepper
I am using Arduino Nano 33 IoT. The cloud's overhead would be a problem, but even if there was a delay in the loop, after the "delay" the motors should be able to move in any speed they are set ... but this does not happen. I will keep looking ...

gjgsm...@gmail.com

unread,
Feb 14, 2025, 6:56:18 AMFeb 14
to accelstepper
I also have no experience with Arduino Cloud and I agree with Jim's comments. This is a common problem when stepping motors using an Arduino mcu. The main loop which is trying to step the motor, is now also busy doing other things like checking the cloud and serial printing etc... You need to seperate out the two activities - 1. State machine control/communication,updating variables etc... 2. Stepping the motor.
I assume from your code that you want to  control something like a three axis camera mount by pressing inputs on your phone to start and stop the motors remotely which means the inputs have to be continuous polled (via the Cloud) in real time by the mcu while stepping the motors.
Try running your stepping in a 'while' loop controlled by a change of state of a variable which will enable an exit from the loop. An interrupt can be used (with an ISR) to effect the the change of state of the variable, this will not generally affect the stepping rate. This is probably the simplest solution but won't work with the Cloud using only one mcu or a single core mcu. Using a second Arduino mcu to do the Cloud communication sounds like the easiest solution which can then change the state of the pins on the first arduino which have the interrupts attached to them.
A more complex but efficient solution is to use an ESP32 which has two cores. You use core0 for wifi communication - Arduino Cloud, and core1 to step the motors. Setup FreeRTOS Tasks (three) to do the communication, updating global variables and stepping, which can now all run concurrently. There is a lot of information online about ESP32 and FreeRTOS.
Reply all
Reply to author
Forward
0 new messages