Thanks Bob I've got the Master and Slave working VIA I2C and using the 5V DC power from the master to power the slave. My next issue is I have a STOP button on the VB Form which is supposed to stop all steppers and flush the commands. This works for the master but not the slave. Chat GPT has been great to this point but it's stumped.
Below is the code for the Master
#include <AccelStepper.h>
#include <Wire.h>
// Local steppers
AccelStepper stepperX(AccelStepper::DRIVER, 2, 5);
AccelStepper stepperY(AccelStepper::DRIVER, 3, 6);
AccelStepper stepperZ(AccelStepper::DRIVER, 4, 7);
#define EN_PIN 8
#define LIMIT_X_PIN 9
#define LIMIT_Y_PIN 10
#define LIMIT_Z_PIN 11
bool movingX = false, movingY = false, movingZ = false;
void setup() {
Serial.begin(9600);
Wire.begin(); // Master
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW);
pinMode(LIMIT_X_PIN, INPUT_PULLUP);
pinMode(LIMIT_Y_PIN, INPUT_PULLUP);
pinMode(LIMIT_Z_PIN, INPUT_PULLUP);
stepperX.setMaxSpeed(1000);
stepperY.setMaxSpeed(1000);
stepperZ.setMaxSpeed(1000);
stepperX.setAcceleration(500);
stepperY.setAcceleration(500);
stepperZ.setAcceleration(500);
}
void loop() {
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim();
if (command == "STOP") {
stopAllMotion();
Serial.println("STOPPED - CLEARED");
return;
}
char axis = command.charAt(0);
int idx1 = command.indexOf(',');
int idx2 = command.lastIndexOf(',');
if (idx1 == -1 || idx2 == -1 || idx1 == idx2) return;
long steps = command.substring(1, idx1).toInt();
int speed = command.substring(idx1 + 1, idx2).toInt();
int accel = command.substring(idx2 + 1).toInt();
if (axis == 'X' || axis == 'Y' || axis == 'Z') {
handleLocalAxis(axis, steps, speed, accel);
} else {
sendToSlave(axis, steps, speed, accel);
}
}
handleLimitsAndRun(stepperX, movingX, LIMIT_X_PIN, 'X');
handleLimitsAndRun(stepperY, movingY, LIMIT_Y_PIN, 'Y');
handleLimitsAndRun(stepperZ, movingZ, LIMIT_Z_PIN, 'Z');
}
void handleLocalAxis(char axis, long steps, int speed, int accel) {
AccelStepper* target = nullptr;
bool* moving = nullptr;
if (axis == 'X') { target = &stepperX; moving = &movingX; }
else if (axis == 'Y') { target = &stepperY; moving = &movingY; }
else if (axis == 'Z') { target = &stepperZ; moving = &movingZ; }
if (target && moving) {
target->setMaxSpeed(speed);
target->setAcceleration(accel);
target->move(steps);
*moving = true;
}
}
void handleLimitsAndRun(AccelStepper &stepper, bool &moving, int pin, char axis) {
if (moving && digitalRead(pin) == LOW) {
Serial.print(axis); Serial.println(" LIMIT TRIGGERED");
stepper.stop(); stepper.setCurrentPosition(stepper.currentPosition()); stepper.move(0);
moving = false;
}
if (moving) {
stepper.run();
if (stepper.distanceToGo() == 0) {
moving = false;
Serial.print(axis); Serial.println(" DONE");
}
}
}
void stopAllMotion() {
stopStepper(stepperX, movingX);
stopStepper(stepperY, movingY);
stopStepper(stepperZ, movingZ);
while (Serial.available()) Serial.read();
}
void stopStepper(AccelStepper& stepper, bool& flag) {
stepper.stop();
stepper.setCurrentPosition(stepper.currentPosition());
stepper.move(0);
flag = false;
}
void sendToSlave(char axis, long steps, int speed, int accel) {
byte address = 0;
if (axis >= 'A' && axis <= 'C') address = 8;
else if (axis >= 'D' && axis <= 'F') address = 9;
else if (axis >= 'G' && axis <= 'I') address = 10;
else {
Serial.println("Unknown slave axis.");
return;
}
Wire.beginTransmission(address);
Wire.write(axis);
Wire.write((byte*)&steps, sizeof(steps));
Wire.write((byte*)&speed, sizeof(speed));
Wire.write((byte*)&accel, sizeof(accel));
Wire.endTransmission();
Serial.print("Sent to Slave ");
Serial.print(address);
Serial.print(" -> ");
Serial.print(axis);
Serial.print(", ");
Serial.print(steps);
Serial.print(", ");
Serial.print(speed);
Serial.print(", ");
Serial.println(accel);
}
Below is the code for the SLAVE
#include <Wire.h>
#include <AccelStepper.h>
// Change this for each slave
#define SLAVE_ADDRESS 8
char axisLabels[3] = {'A', 'B', 'C'};
AccelStepper steppers[3] = {
AccelStepper(AccelStepper::DRIVER, 2, 5), // A
AccelStepper(AccelStepper::DRIVER, 3, 6), // B
AccelStepper(AccelStepper::DRIVER, 4, 7) // C
};
bool moving[3] = {false, false, false};
void setup() {
Serial.begin(9600); // Initialize serial communication for debugging
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveEvent);
for (int i = 0; i < 3; i++) {
steppers[i].setMaxSpeed(1000);
steppers[i].setAcceleration(500);
}
}
void loop() {
// Run motors if they are moving
for (int i = 0; i < 3; i++) {
if (moving[i]) {
steppers[i].run();
if (steppers[i].distanceToGo() == 0) {
moving[i] = false; // Once the movement is done, mark as not moving
}
}
}
}
void receiveEvent(int howMany) {
if (howMany < 1) return;
// Read the command byte
char command = Wire.read();
Serial.print("Command received: ");
Serial.println(command); // Debugging line to see if command is received correctly
if (command == 'M' && howMany >= 1 + 1 + sizeof(long) + 2 * sizeof(int)) {
char axis = Wire.read();
long steps;
int speed, accel;
Wire.readBytes((char*)&steps, sizeof(steps));
Wire.readBytes((char*)&speed, sizeof(speed));
Wire.readBytes((char*)&accel, sizeof(accel));
// Debugging the received data
Serial.print("Received: Axis ");
Serial.print(axis);
Serial.print(", Steps: ");
Serial.print(steps);
Serial.print(", Speed: ");
Serial.print(speed);
Serial.print(", Accel: ");
Serial.println(accel);
// Determine which motor to move based on the received axis
for (int i = 0; i < 3; i++) {
if (axis == axisLabels[i]) {
steppers[i].setMaxSpeed(speed);
steppers[i].setAcceleration(accel);
steppers[i].move(steps);
moving[i] = true;
Serial.println("Move command executed.");
}
}
}
}
But it doesn't seem to work. here is the the VB code for stop button
Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
If SerialPort1.IsOpen Then
SerialPort1.Write("STOP" & vbLf)
Else
MessageBox.Show("Not connected to Arduino.")
End If
End Sub