Hello! I am trying to adjust the speed of a motor while it's running. The Arduino receives a string from PC to set the speed, acceleration, and running for three motors. In particular, the string has the following format: <mode, motorID, value1, value2, value3>.
- "mode" can be "SPEED", "ACCEL", and "RUN"
- "motorID" is a combination of integers 1, 2, and 3 (corresponds to three motors)
- "value1", "value2", and "value3" are the parameters set for motors under a specified mode. For example, if the "mode" is "SPEED", the values are motor speeds.
What I want the motors to do is adjusting the speed while running. So I send the following commands to Arduino: - 1st command: <SPEED,1,100,0,0> //set speed for motor 1
- 2nd command: <ACCEL,1,5000,0,0> //set accel for motor 1
- 3rd command: <RUN,1,10000,0,0> //move 10000 steps from the current position for motor 1
- 4th command: <SPEED,1,1000,0,0> //change the speed for motor 1
After sending the first three commands, the motor can work as expected. If we assume the time that Arduino received the 3rd command as t=0s, and we send the 4th command at t=10s, I want motor 1 can increase its speed from 100 to 1000 to finish the remaining steps (roughly 10000-100x10=9000 steps). However, it seems that my code can't set the speed 1000 for motor 1. Can anyone help me with this? Thanks in advance!
#include <AccelStepper.h>
// Define the pins for each motor
#define X_DIR 5
#define X_STP 2
#define Y_DIR 6
#define Y_STP 3
#define Z_DIR 7
#define Z_STP 4
// Define the constants for the motors
#define X_SPEED 1000 // X steps per second
#define Y_SPEED 1000 // Y
#define Z_SPEED 1000 // Z
#define X_ACCEL 5000.0 // X steps per second per second
#define Y_ACCEL 5000.0 // Y
#define Z_ACCEL 5000.0 // Z
// Define the baud rate of the Arduino
#define BAUD_RATE 230400
// ---------------
// Motor variables
int motorID = 0;
int motors[3] = {0,0,0};
AccelStepper stepper1(AccelStepper::DRIVER, X_STP, X_DIR);
AccelStepper stepper2(AccelStepper::DRIVER, Y_STP, Y_DIR);
AccelStepper stepper3(AccelStepper::DRIVER, Z_STP, Z_DIR);
AccelStepper steppers[3] = {stepper1, stepper2, stepper3};
// -----------------------
// Communication variables
const byte buffSize = 64;
char inputBuffer[buffSize];
char mode[buffSize] = {0};
float value1 = 0.0;
float value2 = 0.0;
float value3 = 0.0;
boolean readInProgress = false;
boolean newDataFromPC = false;
// ----------------
// Action variables
float values[3];
//=================
// PUBLIC FUNCTIONS
//=================
// ----------------------------------------------------
// Function called once to initialise the Arduino board
void setup() {
// Initialise the baud rate of the Serial port
Serial.begin(BAUD_RATE);
// Set the initial max speed of the system
stepper1.setMaxSpeed(X_SPEED);
stepper2.setMaxSpeed(Y_SPEED);
stepper3.setMaxSpeed(Z_SPEED);
// Set the acceleration of the system
stepper1.setAcceleration(X_ACCEL);
stepper2.setAcceleration(Y_ACCEL);
stepper3.setAcceleration(Z_ACCEL);
// Set the Arduino as ready
Serial.println("<READY>");
}
// ---------------------------------------------
// Function called repeatedly to run the Arduino
void loop() {
// Get the data from the PC
getDataFromPC();
if(newDataFromPC){
executeThisFunction();
}
}
const char startMarker = '<';
const char endMarker = '>';
byte bytesRecvd = 0;
// -------------------------------------------------
// Read the serial port and extract commands from it
void getDataFromPC() {
// Check if data is coming through the serial port
if (Serial.available() > 0)
{
// Read the next incoming character
char x = Serial.read();
// Detect the end marker and call the parser - Needs to be 1st if statement
if (x == endMarker) {
readInProgress = false;
newDataFromPC = true;
// Clear the buffer
inputBuffer[bytesRecvd] = 0;
return parseData();
}
// Save the current character in memory - Needs to be 2nd if statement
if (readInProgress) {
// Add the character to the buffer
inputBuffer[bytesRecvd] = x;
bytesRecvd ++;
// Correct if size is exceeding buffer size
if (bytesRecvd == buffSize) {
bytesRecvd = buffSize - 1;
}
}
// Detect the start marker and collect characters - Needs to be 3rd if statement
if (x == startMarker) {
bytesRecvd = 0;
readInProgress = true;
}
}
}
// -----------------------
// Parse the incoming data
void parseData() {
char * strtokIndx; // this is used by strtok() as an index
// Extract the MODE
strtokIndx = strtok(inputBuffer, ",");
strcpy(mode, strtokIndx);
// Extract the MOTORID
strtokIndx = strtok(NULL, ",");
String motorstr(strtokIndx);
// Convert into an integer
motorID = atoi(strtokIndx);
// Enable the motors
toggleMotors(motorstr);
// Extract the VALUE for motor 1
strtokIndx = strtok(NULL, ",");
value1 = atof(strtokIndx);
// Extract the VALUE for motor 2
strtokIndx = strtok(NULL, ",");
value2 = atof(strtokIndx);
// Extract the VALUE for motor 3
strtokIndx = strtok(NULL, ",");
value3 = atof(strtokIndx);
// Set the "value 1-3" for array "values"
values[0] = value1;
values[1] = value2;
values[2] = value3;
// Communicate back to the computer
newDataFromPC = true;
}
// Select the function to execute
void executeThisFunction() {
// Go to the SPEED setting function
if (strcmp(mode, "SPEED") == 0) {
updateSpeed();
}
// Go to the ACCEL setting function
else if (strcmp(mode, "ACCEL") == 0) {
updateAccel();
}
// Go to the RUN function
else if (strcmp(mode, "RUN") == 0) {
runFew();
}
}
void toggleMotors( String motorstr ) {
if(motorstr.indexOf("1") >= 0) {
motors[0] = 1;
}
if(motorstr.indexOf("2") >= 0) {
motors[1] = 1;
}
if(motorstr.indexOf("3") >= 0) {
motors[2] = 1;
}
}
// Update the speed of the motor
void updateSpeed() {
switch (motorID) {
// Apply settings to motor 1
case 1:
stepper1.setMaxSpeed(value1);
Serial.println("update speed for motor 1");
break;
// Apply settings to motor 2
case 2:
stepper2.setMaxSpeed(value2);
break;
// Apply settings to motor 3
case 3:
stepper3.setMaxSpeed(value3);
break;
}
// Reset all variables
clearVariables();
}
// --------------------------------
// Update the accel of the motor
void updateAccel() {
switch (motorID) {
// Apply settings to motor 1
case 1:
stepper1.setAcceleration(value1);
Serial.println("update accel for motor 1");
break;
// Apply settings to motor 2
case 2:
stepper2.setAcceleration(value2);
break;
// Apply settings to motor 3
case 3:
stepper3.setAcceleration(value3);
break;
}
// Reset all variables
clearVariables();
}
// ------------------------------------
// Clear all variables after the action
void clearVariables() {
memset(mode,0,sizeof(mode));
motorID = 0;
value1 = 0.0;
value2 = 0.0;
value3 = 0.0;
}
// Run the motors to move the syringes
void runFew() {
AccelStepper steppers[3] = {stepper1, stepper2, stepper3};
// Set the distance, and apply to the motor
for (int i = 0; i < 3; i += 1) {
if (motors[i] == 1) {
steppers[i].move(values[i]);
Serial.println("update move steps");
}
}
clearVariables();
// Initialise the motor status for the run loop
int stepperStatus[3] = {0, 0, 0};
// Start the main loop
while (array_sum(stepperStatus, 3) != array_sum(motors, 3)) {
// Iteration over the 3 steppers
for (int i = 0; i < 3; i += 1) {
// Check if the stepper is selected
if (motors[i] == 1) {
// Ask the stepper to move to position at constant speed.
if (stepperStatus[i] == 0 ) {
steppers[i].run();
}
// Check if it reached it's position - if yes, set the status
if (steppers[i].distanceToGo() == 0) {
stepperStatus[i] = 1;
}
}
}
getDataFromPC();
if (strcmp(mode, "SPEED") == 0){
updateSpeed();
}
if (strcmp(mode, "STOP") == 0){
//return stopAll();
break;
}
}
Serial.println("Jump while");
clearVariables();
}
