Go Down

Topic: Python Laptop and Arduino via serial communicating too slow (Read 1 time) previous topic - next topic

1Ghasthunter1

Mar 26, 2020, 10:10 pm Last Edit: Mar 27, 2020, 06:29 pm by 1Ghasthunter1
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:
Code: [Select]
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)
Code: [Select]

#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>)

wildbill

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.

1Ghasthunter1

Quote
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.

Go Up