I'm trying to continuously control the movement of a stepper motor using OSC and the AccelStepper library with an Arduino MKR WIFI 1010.
Right now the setup is functionnal and i am able to receive OSC data and move the stepper accordingly. However when continuously reading the value for the position, the stepper rattles and stutters. My guess is there is a conflict when calling OscWiFi.update() and stepper.run(). It doesn't seem to be affected this bad when i use a potentiometer to move the stepper.
Testing with a simple example library code everything runs smoothly.
Here is the relevant code :
#include <AccelStepper.h>
#include <ArduinoOSCWiFi.h>
#include "secrets.h"
const long minPosition = 0;
const long maxPosition = -800;
float targetPositionOSC = 0; // Default starting value
float targetPositionA = 0;
const int maxSpeed = 2000;
const int acceleration = 500;
// Stepper setup
#define STEP_PIN 2
#define DIR_PIN 3
#define POT_PIN A5
AccelStepper stepper1(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
void setup() {
///WIFI stuff
Serial.begin(115200);
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
while (true);
}
WiFi.begin(ssid, pwd);
Serial.println("Waiting for connection to WiFi");
WiFi.config(ip, gateway, subnet);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.print("WiFi connected, IP = ");
IPAddress ip = WiFi.localIP();
Serial.println(ip);
Serial.println("Connected to WiFi network.");
/// Subscribe to OSC
OscWiFi.subscribe(recv_port, "/test", targetPositionOSC);
/// Set default stepper settings
stepper1.setMaxSpeed(maxSpeed);
stepper1.setAcceleration(acceleration);
stepper1.setCurrentPosition(0);
}
void loop() {
// Read potentiometer and map to target position
//int potValue = analogRead(POT_PIN);
//long targetPositionA = map(potValue, 0, 1023, minPosition, maxPosition);
OscWiFi.update();
stepper1.moveTo(targetPositionOSC);
// Run the stepper motor (non-blocking)
stepper1.run();
}
A work around i found is to poll for OSC updates at intervals using
unsigned long now = millis();
// Delay OSC
if (now - lastUpdate >= updateInterval) {
OscWiFi.update();
lastUpdate = now;
}
Hover i'd like to continuously control the stepper, is there any way to do it without conflicting with the stepper.run() command ?
I think you call stepper1.moveTo(targetPositionOSC); too often. It doesn't make sense to call it faster then steps are generated. And if I remember correctly the run() function runs into problems if the target is changed too quickly.
how is updateInterval set in your workaround?
N.B. It doesn't make sense too to use a float variable as target position. The target position for a stepper can only be an integer.
Thanks, the updateInterval is set as a constant.
Here is my full code with the workaround. I have to use stepper1.runToPosition() instead of stepper1.run() . The movement is smooth but the updates cannot be very close together so realtime is not possible.
#include <AccelStepper.h>
#include <ArduinoOSCWiFi.h>
#include "secrets.h"
const long minPosition = 0;
const long maxPosition = -800;
float targetPositionOSC = 0; // Default starting value
float targetPositionA = 0;
const int maxSpeed = 2000;
const int acceleration = 500;
// Timing control
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 1000; // ms between updates
// Stepper setup
#define STEP_PIN 2
#define DIR_PIN 3
#define POT_PIN A5
AccelStepper stepper1(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
void setup() {
///WIFI stuff
Serial.begin(115200);
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
while (true);
}
WiFi.begin(ssid, pwd);
Serial.println("Waiting for connection to WiFi");
WiFi.config(ip, gateway, subnet);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.print("WiFi connected, IP = ");
IPAddress ip = WiFi.localIP();
Serial.println(ip);
Serial.println("Connected to WiFi network.");
/// Subscribe to OSC
OscWiFi.subscribe(recv_port, "/test", targetPositionOSC);
/// Set default stepper settings
stepper1.setMaxSpeed(maxSpeed);
stepper1.setAcceleration(acceleration);
stepper1.setCurrentPosition(0);
}
void loop() {
// Read potentiometer and map to target position
//int potValue = analogRead(POT_PIN);
//long targetPositionA = map(potValue, 0, 1023, minPosition, maxPosition);
//Timing workaround
unsigned long now = millis();
if (now - lastUpdate >= updateInterval) {
OscWiFi.update(); // Process incoming OSC messages
lastUpdate = now;
}
//OscWiFi.update();
stepper1.moveTo(targetPositionOSC);
// Run the stepper motor (non-blocking)
//stepper1.run();
stepper1.runToPosition();
}
You can try this ( untested ) and then vary updateIntervall to get the best compromise between fast reaction and smooth move.
void loop() {
//Timing workaround
unsigned long now = millis();
if (now - lastUpdate >= updateInterval) {
OscWiFi.update(); // Process incoming OSC messages
lastUpdate = now;
stepper1.moveTo(targetPositionOSC);
}
// Run the stepper motor (non-blocking)
stepper1.run();
Can you please post links to:
Stepper Motor
Stepper Driver
Power Supply
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
Can you post some images of your project?
So we can see your component layout.
What is the stepper motor load?
I know it is a lot, BUT we need to know if it is a basic hardware problem before hitting the software.