I have a robotic arm-type setup with 3 28BYJ-48 stepper motors each driven by a ULN2003 board. I am using an Arduino Mega with an Arduino Ethernet 2 shield.
I am sending roll, pitch, and yaw coordinates from the FlightGear simulator through a router and reading it with the ethernet shield on the Arduino. I have tested this individually and it works fine.
The issue is when I try and connect the stepper motors to move to the position read by the ethernet port, the motors move to the first position and then freeze. I never had this issue with servo motors when I had the same setup but now I need stepper motors to get 360 degrees instead of the 180 provided by the micro servo.
What is even weirder is that I was having this issue last week. Then this morning I ran the code again and everything worked. And then when I came back after lunch, the issue restarted once more. So I am very confused as to what might be causing this issue. Does anyone have any suggestions?
Here is the current code. I am using the AccelStepper library for the stepper motors
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <AccelStepper.h>
#define HALFSTEP 8
#define SOME_THRESHOLD 40
#define s1_1 30 // stepper 1, IN1 on ULN2003
#define s1_2 31 // stepper 1, IN2 on ULN2003
#define s1_3 32 // stepper 1, IN3 on ULN2003
#define s1_4 33 // stepper 1, IN4 on ULN2003
#define s2_1 50 // stepper 2, IN1 on ULN2003
#define s2_2 51 // stepper 2, IN2 on ULN2003
#define s2_3 52 // stepper 2, IN3 on ULN2003
#define s2_4 53 // stepper 2, IN4 on ULN2003
#define s3_1 40 // stepper 3, IN1 on ULN2003
#define s3_2 41 // stepper 3, IN2 on ULN2003
#define s3_3 42 // stepper 3, IN3 on ULN2003
#define s3_4 43 // stepper 3, IN4 on ULN2003
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x48, 0xD3};
IPAddress ip(192, 168, 1, 177);
unsigned int localPort = 8888; // local port to listen on
// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged"; // a string to send back
// NOTE: The sequence 1-3-2-4 is required for proper sequencing of 28BYJ-48
AccelStepper stepper1(HALFSTEP, s1_1, s1_3, s1_2, s1_4);
AccelStepper stepper2(HALFSTEP, s2_1, s2_3, s2_2, s2_4);
AccelStepper stepper3(HALFSTEP, s3_1, s3_3, s3_2, s3_4);
int roll, pitch, yaw, map_roll, map_pitch, map_yaw, s1_orange, s2_yellow, s3_green;
int init_pos = 90;
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
stepper1.setMaxSpeed(1000.0);
stepper1.setAcceleration(100.0);
stepper1.setSpeed(900);
stepper2.setMaxSpeed(1000.0);
stepper2.setAcceleration(100.0);
stepper2.setSpeed(900);
stepper3.setMaxSpeed(1000.0);
stepper3.setAcceleration(100.0);
stepper3.setSpeed(900);
// start the Ethernet
Ethernet.begin(mac, ip);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start UDP
Udp.begin(localPort);
}
void loop() {
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remote = Udp.remoteIP();
for (int i=0; i < 4; i++) {
Serial.print(remote[i], DEC);
if (i < 3) {
Serial.print(".");
}
}
Serial.print(", port ");
Serial.println(Udp.remotePort());
// read the packet into packetBufffer
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
Serial.println("Contents:");
Serial.println(packetBuffer);
//extract the roll pitch yaw values
roll = atoi(strtok(packetBuffer, ","));
pitch = atoi(strtok(NULL, ","));
yaw = atoi(strtok(NULL, ","));
Serial.print("FG Roll:");
Serial.println(roll);
Serial.print("FG Pitch:");
Serial.println(pitch);
Serial.print("FG Yaw:");
Serial.println(yaw);
s_setStepperTarget(stepper1, yaw);
Serial.print("Stepper Yaw:");
Serial.println(yaw);
s_setStepperTarget(stepper2, map(roll, -180, 180, 0, 360));
Serial.print("Stepper Roll:");
Serial.println(map(roll, -180, 180, 0, 360));
s_setStepperTarget(stepper3, map(pitch, -180, 180, 0, 360));
Serial.print("Stepper Pitch:");
Serial.println(map(pitch, -180, 180, 0, 360));
// send a reply to the IP address and port that sent us the packet we received
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(ReplyBuffer);
Udp.endPacket();
//Serial.println("here");
}
stepper1.run();
stepper2.run();
stepper3.run();
//Serial.println("done running");
delay(10);
}
void s_setStepperTarget(AccelStepper& stepper, int angle){
//1024 is about a quarter of a turn so 4096 will be a full turn
long newTarget = map(angle, 0, 360, 0, 4096);
long currentTarget = stepper.targetPosition();
// Calculate the shortest path to the new target
long currentPosition = stepper.currentPosition();
long distance = newTarget - currentPosition;
if (abs(distance) > 2048) {
if (distance > 0) {
newTarget -= 4096;
} else {
newTarget += 4096;
}
}
stepper.setCurrentPosition(currentPosition);
stepper.moveTo(newTarget);
Serial.println(stepper.currentPosition());
}


