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() {
}
2 Answers 2
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.
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.
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.
"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"cry*"
: it expects either"crx*"
or"clx*"
. 2. Re "The sketch should not print anything": It should. It has someSerial.println()
here and there. Let me ask again: what does it print to the serial port?"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. TheSerial.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 ondigital ports
2, 5 and 8 through theloops
.loops
only after thefirst command
is sent viaserial
. If I try asecond time
, nothing happens. It's as if theserial read
doesn't match any of the"crx*"
or"clx*"
conditions.