Arduino doesn't control a stepper as it should

341 Views Asked by At

So I have decided to make a simple satellite tracker. I'm using Orbitron as my tracking software. It has a built-in DDE server so I can connect to it through java. So I wrote a small app in java that connects and reads the data about the satellite from Orbitron does some calculations (like calculating the error and applying additional steps when the error is too big to minimize it) and sends the data to an arduino uno over serial which controls two steppers (currently just the elevation one).

My problem is that when I start sending the data to the arduino, the first packet gets processed and rotates the motor the right direction and amount, but every other packet sent later just rotates it the wrong direction and/or amount, it has no effect or just makes the stepper start spinning like crazy.

I did try uploading a sample sketch for the Adafruit Stepper Shield (which I am using) and everything worked perfectly fine. Apparently there is a problem with my arduino code.

He it is:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

Adafruit_MotorShield AFMS = Adafruit_MotorShield(); //Create the Adafruit_MotorShield object

float singleStepAzim; //Store the size of the azimuth stepper single step
float singleStepElev; //Store the size of the elevation stepper single step

void setup() {
  Serial.begin(9600); //Start the serial comunication

  AFMS.begin(); //Start the motor shield

  /**Wait until data is available on the serial port**/
  while(Serial.available() <= 0){
    ;
  }

  singleStepAzim = Serial.readStringUntil(':').toFloat(); //Read and store the value of a single azimuth step
  singleStepElev = Serial.readStringUntil(';').toFloat(); //Read and store the value of a single elevation step
}

/**Create StepperMotor objects based on their single step size**/
Adafruit_StepperMotor *azimMotor = AFMS.getStepper(360 / singleStepAzim, 1);
Adafruit_StepperMotor *elevMotor = AFMS.getStepper(360 / singleStepElev, 2);

/**Same thing just by using static values**/
/*Adafruit_StepperMotor *azimMotor = AFMS.getStepper(360 / 7.5, 1);
Adafruit_StepperMotor *elevMotor = AFMS.getStepper(360 / 7.5, 2);*/

void loop() {
  /**Read the data if available**/
  if(Serial.available() > 0){
    /**Read the type and the content of the packet**/
    String type = Serial.readStringUntil(':');
    String data = Serial.readStringUntil(';');

    /**'type' == AZ - move the relavant stepper by 'data'**/
    if(type.equals("AZ")){
      //Move azimuth
      azimMotor->setSpeed(10); //Set the speed
      /**If the 'data' if negative then turn it backwards**/
      if(data.toInt() < 0){
        azimMotor->step(-data.toInt(), BACKWARD, INTERLEAVE); //USE SINGLE ??
      }else{
        azimMotor->step(data.toInt(), FORWARD, INTERLEAVE); //USE SINGLE ??
      }
      /**'type' == EL - move the relavant stepper by 'data'**/
    }else if(type.equals("EL")){
      //Move elevation
      elevMotor->setSpeed(10); //Set the speed
      /**If the 'data' if negative then turn it backwards**/
      if(data.toInt() < 0){
        elevMotor->step(-data.toInt(), BACKWARD, INTERLEAVE); //USE SINGLE ??
      }else{
        elevMotor->step(data.toInt(), FORWARD, INTERLEAVE); //USE SINGLE ??
      }
      /**'type' == RL - release the motor specified in 'data'**/
    }else if(type.equals("RL")){
      if(data == "AZ"){
        azimMotor->release();
      }else if(data == "EL"){
        elevMotor->release();
      }
      /**'type' == HL - hold the motor specified in 'data' in place**/
    }else if(type.equals("HL")){
      if(data == "AZ"){
        azimMotor->step(1, FORWARD, SINGLE);
        azimMotor->step(1, BACKWARD, SINGLE);
      }else if(data == "EL"){
        elevMotor->step(1, FORWARD, SINGLE);
        elevMotor->step(1, BACKWARD, SINGLE);
      }
    }
  }
}

First I thought the problem was that I was using serial to set the single step values, but apparently that wasn't the case. My next idea was that the arduino took too much time to process everything so I changed the interval at which the data was being sent from 0.5s to 1s and later all the way up to 10s. But still nothing. The stepper just doesn't want to rotate the right direction and amount.

Thanks for your help!

P.S.: The packet format is:

PACKET_TYPE:PACKET_DATA;

PACKET_TYPE being AZ (rotate azimuth), EL (rotate elevation), RL (release the motor specified in PACKET_DATA) and HL (hold the motor specified in PACKET_DATA).

This applies for everything read from the serial port in the main loop.

1

There are 1 best solutions below

2
On

Here is my suggestion. Verify if all data sent to Arduino is correct. Once done, keep the code simple. Start from scratch, I mean just keep it to positive value and uni-directional movement. You can even take out the elevation and just rotate it first. Verify is this is working and then move on to elevation.

P.S: What does 10 indicate in setSpeed(10) function?