0

I am trying to move a stepper motor when a specific command is send to Arduino Mega 2560. This command is read character by character and stored in a string variable. Whenever a new command is sent, an act should be performed. However, it is not happening and I believe that the problem is in reading the sent command. I tried clearing the character and string variables, but to no avail. The sketch should run a loop that moves the motor clockwise or counterclockwise according to the command sent, which can be "crx*" for clockwise or "clx*" for anticlockwise, where "*" is the reading stop criterion of the characters. Any suggestions what to do? The script:

void(* resetFunc) (void) = 0;//Reset turn

// Stepper Motor X
const int stepPinX = 2; //X.STEP
const int dirPinX = 5; // X.DIR
const int pinEnable = 8;

// String read
char c;
String readString; //main captured String

// Unit steps
double av_len = 1.029; //medium length
double interval;
int cnt_steps = 0;
const int num_d = 200;//parameterized step
int fact = int(num_d / av_len);
int unit_len = fact * 1;//unit length (1mm)

void setup()
{
  // Sets pins as Outputs
  pinMode(stepPinX, OUTPUT);
  pinMode(dirPinX, OUTPUT);
  pinMode(pinEnable, OUTPUT);

  digitalWrite(pinEnable, HIGH);//lock driver on cnc shield 

  Serial.begin(115200);
  Serial.setTimeout(1);
  
  while (1) {
    
    while ( (Serial.available() == 0) )
    {

    }

    if (Serial.available())  {
      c = Serial.read();  //gets one byte from serial buffer
      //Serial.println(readString);
      if (c == '*') {
        Serial.println(readString);//test response
        if (readString == "crx") {
          cnt_steps = cnt_steps + 1;
          Serial.println(cnt_steps);
          digitalWrite(pinEnable, LOW);
          digitalWrite(dirPinX, HIGH);
          for (int x = 0; x < unit_len; x++) {
            digitalWrite(stepPinX, HIGH);
            delayMicroseconds(500);
            digitalWrite(stepPinX, LOW);
            delayMicroseconds(500);
          }
           
        }
        else if (readString == "clx") {
          cnt_steps += -1;
          Serial.println(cnt_steps);
          digitalWrite(pinEnable, LOW);
          digitalWrite(dirPinX, LOW);
          for (int x = 0; x < unit_len; x++) {
            digitalWrite(stepPinX, HIGH);
            delayMicroseconds(500);
            digitalWrite(stepPinX, LOW);
            delayMicroseconds(500);
          }
        }
         digitalWrite(pinEnable, HIGH);//lock driver on cnc shield    
         c = (char)0;
         Serial.flush();
         readString = "";
         //resetFunc();
      }

      else {
        readString += c; //makes the string readString

      }
    }
  }
}


void loop() {

}
7
  • What are you sending to to your sketch? What does it print back on the serial port? Commented Dec 6, 2022 at 13:27
  • @EdgarBonet I send the commands "crx*" for clockwise rotation and "cry*" counterclockwise and "*" is the criterion for stopping character reading. The sketch should not print anything, but I asked it to print the commands sent to see if the reading was correct Commented Dec 6, 2022 at 13:45
  • 1. This sketch will not understand "cry*": it expects either "crx*" or "clx*". 2. Re “The sketch should not print anything”: It should. It has some Serial.println() here and there. Let me ask again: what does it print to the serial port? Commented Dec 6, 2022 at 14:00
  • @EdgarBonet Ignore the "cry*". It was a typo. The correct one is "clx*". When receiving one of the aforementioned commands, the sketch must perform the loops contained within the conditions, as shown in the script. The Serial.println() are exclusively for making sure that the serial reading of the characters is being done. Can be commented. Depending on the conditions, the sketch acts on digital ports 2, 5 and 8 through the loops. Commented Dec 6, 2022 at 14:33
  • @EdgarBonet What happens is that the sketch executes the loops only after the first command is sent via serial. If I try a second time, nothing happens. It's as if the serial read doesn't match any of the "crx*" or "clx*" conditions. Commented Dec 6, 2022 at 14:33

2 Answers 2

1

When sending text commands to an Arduino, it is common to define a “line-oriented protocol”: each command is transmitted as a single line, with the line ending signifying the end of the command. Common line endings are carriage return (CR = '\r' = 0x0d = 13), line feed (LF = '\n' = 0x0a = 10) and the sequence CR+LF.

The Arduino serial monitor is designed to support this convention by automatically appending a line ending when you press “Send”. This line ending can be configured to one of the following options:

  • No line ending
  • Newline (meaning “line feed”)
  • Carriage return
  • Both NL & CR (but CR is actually sent before LF)

In your case, you have chosen to use '*' as a command termination character. For this to work, you have to choose “No line ending” and add the “*” explicitly to the command. Alternatively, you may consider changing your sketch so that it expects '\r' or '\n', which is a more standard way of ending a command.

0

In addition to the good responses you have already received, I offer this.

For the Arduino, know the differences between String string and char arrays - there is much on this e.g., https://forum.arduino.cc/t/string-vs-string-vs-char-arrays-correct-approach/537468 . Many do not want to deal with the vagaries of String, but their use can be convenient.

Run this code:

String readstring = "xxx";

void setup() {
  Serial.begin(115200);
}

void loop() {
  if (Serial.available()) {
    readstring = Serial.readStringUntil('/n');
    Serial.print(readstring);
    Serial.println(" received");
    if (readstring.equals("crx")) {
      // move counter clockwise
      Serial.println("moving counter clockwise");
      // counterclockwise() <-- your function
    }
    else if (readstring.equals("clx") ) {
      // move clockwise
      Serial.println("moving clockwise");
      // clockwise() <-- your function
    }
    else {
      // bad command
      Serial.println("Bad command received - no action");
      // badcommand() <-- your function
    }
  }
}

If you add functions for the stepper, it may do what you want within a limited context and with using the Arduino serial monitor for input. Take a look at the output.

enter image description here

Note that the serial monitor is set to "no line ending". The terminating character '/n' is provide by your input in the serial monitor. It will do what you want, but again, many advise you stay away from String.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.