Python Laptop and Arduino via serial communicating too slow

Hello,

I've been working on a stepper motor controlled turret, and in order to control it via a joystick, I use a laptop to read my joystick values, and transmit them over serial to the Arduino. The data is transmitted in the format <xxx, yyy>, where xxx and you are greater than 100 and below 300.

Although the serial communication works, I have to run it very slowly, putting a delay of .5 seconds inside of my transmit function in python, or else the stepper motors disable themselves and nothing happens. Is there any way to fix this?

Python code:

import serial, time
import pygame
from pygame.locals import *
import math

turret_axis = 0
pitch_axis = 1
serialData = ''

arduino = serial.Serial('COM4', 115200, timeout=.1)

pygame.init()

joystick_count = pygame.joystick.get_count()

for i in range(joystick_count):
    joystick = pygame.joystick.Joystick(i)
    joystick.init()

    print("Joystick{}".format(i))
    print(joystick.get_name())
    print(joystick.get_numaxes())


def getXVal():
    global turretVal
    turretVal = joystick.get_axis(turret_axis)
    turretVal = round(turretVal, 2)
    turretVal = turretVal*100
    turretVal = turretVal + 200
    turretVal = str(turretVal)
    turretVal = turretVal[:3]
    return turretVal

def getYVal():
    global pitchVal
    pitchVal = joystick.get_axis(pitch_axis)
    pitchVal = round(pitchVal, 2)
    pitchVal = pitchVal*100
    pitchVal = pitchVal + 200
    pitchVal = str(pitchVal)
    pitchVal = pitchVal[:3]
    return pitchVal

def writeToSerial():
    time.sleep(.5)
    getXVal()
    getYVal()
    serialData = ('<'+turretVal+", "+pitchVal+">")
    print(serialData)
    arduino.write(serialData)

while True:
    pygame.event.pump()
    writeToSerial()

And here's the code running on my Arduino(atmega2560)

#include <AccelStepper.h>

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        
boolean newData = false;

//Stored Values from serial
int xInt = 0;
int yInt = 0;

//Stepper motor control pins
const int tStep = 46;
const int tDir = 48;
const int tEnable = 62;
const int pStep = 36;
const int pDir = 34;
const int pEnable = 30;

//Stepper MS Pins
const int tMS1 = 22;
const int tMS2 = 39;
const int pMS1 = 57;
const int pMS2 = 4;

AccelStepper tStepper(1, tStep, tDir);
AccelStepper pStepper(1, pStep, pDir);
//============

void setup() {
    Serial.begin(115200); //Setup serial
    initializeSteppers();
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        processData();
        newData = false;
    }
    runSteppers();
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index
 
    strtokIndx = strtok(tempChars,","); // this continues where the previous call left off
    xInt = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    yInt = atoi(strtokIndx);     // convert this part to a float

}

//============

void processData() {
  xInt = (xInt-200)*-10;
  yInt = (yInt-200)*-10;
}

void initializeSteppers() {
  pinMode(tEnable, OUTPUT);
  pinMode(pEnable, OUTPUT);
  pinMode(tMS1, OUTPUT);
  pinMode(tMS2, OUTPUT);
  pinMode(pMS1, OUTPUT);
  pinMode(pMS2, OUTPUT);

  //Enable Steppers
  digitalWrite(tEnable, LOW);
  digitalWrite(pEnable, LOW);

  //Configure for 1/4 microstepping
  digitalWrite(tMS1, LOW);
  digitalWrite(tMS2, HIGH);
  digitalWrite(pMS1, LOW);
  digitalWrite(pMS2, HIGH);

  //set stepper speeds and accel
  tStepper.setMaxSpeed(2000);
  pStepper.setMaxSpeed(100);
  tStepper.setAcceleration(4000);
  pStepper.setAcceleration(1000);

}

void runSteppers(){
  pStepper.moveTo(yInt);
  tStepper.moveTo(xInt);
  Serial.println(xInt);
  Serial.println(yInt);
  tStepper.run();
  pStepper.run();
  
}

Any help would be appreciated. Thanks

Update March 27:
I've found that whenever I transmit from my laptop too fast, my pin 13 LED becomes stuck on, and my whole program gets disabled as if the Arduino is constantly initializing itself without stopping. I've also moved from transmitting two pieces of data to three (<data, data, data>)

I would be inclined to only transmit when the joystick values have changed. You may be able to run at a faster baud rate too.

You may be able to run at a faster baud rate too.

I've done some basic math(I'm not sure how accurate it is), but consider the following:
The data I transmit is in ASCII format and each transmission looks like this: "<xxx, xxx, x>". Converted to bits, this piece of ASCII text is 98 bits long. Then, if we consider the baud rate of the serial connection, 115200(115200 bits per second), we can divide 115,200 bits/second and 98 bits/second, we get a theoretical maximum of about 1,175 transmissions per second. Right now, I can max out my transmission rate to 3.33 times per second before the Arduino locks up. By dividing my transmission rate now by the theoretical maximum transmission rate, I'm technically running at .2% of the transmission speed I could be running at assuming everything is working okay, so I don't think that my baud rate is an issue. I am again, I'm no expert, so please correct me if this is the wrong way to think about this. However, I'm still unsure of what's locking up my Arduino.

I do like your idea of transmitting only when the controls change, and I will most likely implement this soon.

I've still had no luck, any ideas?

I didnt get too much help from here, so I decided to figure it out myself. The issue was that I didn't give my python script enough time to initialize the Serial comms with the arduino, so the arduino was constantly trying to reinitialize every time a message was sent. If the message send interval was lower than the time that it took for the arduino to initialize the serial comms, then it would continually try to reinit itself and not function. By adding a delay at the start of my python program, this issue was solved.

What I did, to keep the Arduino synced to a RPi3 was have the RPi reset the Uno, Mega, and Due, through the reset pin on the Arduino Devices.