Send data to Arduino via Serial

My code is:

#include <Stepper.h>
#define ena 52
const int stepsPerRevolution = 1600;
Stepper motor1(stepsPerRevolution, 50, 51);

void setup() {
  motor1.setSpeed(370); //370 ES EL MAXIMO
  Serial.begin(115200);
  Serial.setTimeout(0);
  pinMode(ena, OUTPUT);
  Serial.println("Initialize control");
  digitalWrite(ena, HIGH);
}

void loop() {
  int inByte = Serial.read();
  
  switch (inByte) {
    
      case 'a':
        Serial.println("Derecha");
        while (inByte) {
          int x = Serial.read();
          if (x == '1') { 
            Serial.println("SALIR");
            break;
          }
          motor1.step(stepsPerRevolution);
        }
        break;

      case 'b':
        Serial.println("Izquierda");
        while (inByte) {
          int x = Serial.read();
          if (x == '1') {
            Serial.println("SALIR"); 
            break;
          }
          motor1.step(-stepsPerRevolution);
        }
        break;

      case 'c':
        digitalWrite(ena, HIGH);
        Serial.println("ON");
        break;

      case 'd':
        digitalWrite(ena, LOW);
        Serial.println("OFF");
        break;
       
   }
}

It is to control a Stepper Motor Via Serial. When I press “A”, the stepper motor starts on the right, when I procure “B” start to the left, I stop it with “1”. My problem is that it is not 1,600 steps of the constant “stepsPerRevolution”, it is infinite.

My 2nd problem is that I want to be able to introduce the amount of steps that I want the engine Stepper from the serial monitor.

I would suggest to study Serial Input Basics to handle this

My Multi-tasking in Arduino has a detailed stepper motor example controlled by user inputs.
My Arduino Software Solutions has a variety of complete sketches for reading user input from Serial, including parsing of numbers in a more reliable way then Serial Basic.

Honestly I still do not understand how to do it (apologize, I am relatively new with Arduino). In Python it is something similar to the following:

int x = Serial.read();
int y = Serial.read();
if (x == '1') { 
    Serial.println("EXIT");
    break;
}
motor1.step(y);

“y” it would be the number of steps you should travel. Is there any way to do it? That is, send two data and not only 1. Because the steps may be 200 for half turn or 400 for a full turn (or any other number).

That’s what I have in mind, I do not know if it existed another simplest and convenient way to do it.

How do you plan to send the number of steps? Ascii ?

I do not know what ASCII is, remember that I am a rookie with Arduino. But, I suppose that with an INT from the serial monitor.

Read and practice with the tutorial above and Google ASCII or use the built in readString() which comes with … strings attached

Alternatively turn off your brain and use canned solutions with bloated libraries that will offer to do that for you.

A Hint for you… If a human can read it, it’s probably ASCII. Stuff you read is made of text. Text is traditionally made with ASCII.

-jim lee

I started reading the documentation of Robin2 and I am trying with Example 2, but I still do not achieve it. The code that I have is as follows:

#include <Stepper.h>
int stepsPerRevolution = 0;
Stepper motor1(stepsPerRevolution, 50, 51);
const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

void setup() {
  Serial.begin(115200);
  motor1.setSpeed(200); //RPM - MAX: 370
  Serial.println("");
}

void loop() {
  recvWithEndMarker();
  showNewData();
  stepperControl();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

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

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    Serial.println(receivedChars);
    newData = false;
  }
}

void stepperControl() {
  if (receivedChars == '1') {
    Serial.println("Right");
    if (newData == true) {
      stepsPerRevolution = receivedChars;
      motor1.step(stepsPerRevolution);
      newData = false;
    }
  }
  else if (receivedChars == '2') {
    Serial.println("Left");
    if (newData == true) {
      stepsPerRevolution = receivedChars;
      motor1.step(-stepsPerRevolution);
      newData = false;
    }
  }
}

What I try is first to choose which of the two I want if == 1 or == 2, and then write the value “stepsPerRevolution = receivedChars;

But, my problem is that it does not work. Does not recognize receivedChars

You’re getting closer.
I think that you want to be sending and then parsing a message with both the direction and the number of steps.
For example “1,234\n”.

You can follow the Serial Input Basics example number 5 and use strtok, to separate the lead character of the message at the comma and use atoi to convert the remaining text to a number.

Alternatively, but less generically, you can easily determine the first character in the receivedChars character array which is at receivedChars[0] and then you use atoi on the receivedChars after the comma with atoi(&receivedChars[2])

#include <Stepper.h>
int stepsPerRevolution = 0;
Stepper motor1(stepsPerRevolution, 50, 51);
const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

void setup() {
  Serial.begin(115200);
  motor1.setSpeed(200); //RPM - MAX: 370
  Serial.println("");
}

void loop() {
  recvWithEndMarker();
  showNewData();
  stepperControl();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

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

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

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    Serial.println(receivedChars);
    //newData = false;
  }
}

void stepperControl(){
  if (newData == true)
  {
    if (receivedChars[0] == '1')
    {
      Serial.println("Right");
      stepsPerRevolution = atoi(&receivedChars[2]);
      Serial.print("stepsPerRevolution ...");
      Serial.println(stepsPerRevolution);
      motor1.step(stepsPerRevolution);
    }

    else if (receivedChars[0] == '2') {
      Serial.println("Left");
      stepsPerRevolution = atoi(&receivedChars[2]);
      Serial.print("-stepsPerRevolution...");
      Serial.println(-stepsPerRevolution);
      motor1.step(-stepsPerRevolution);
    }
    newData = false;
  }
}
1 Like

Thank you very much for your help. Everything works well from the serial monitor of Arduino. My other problem is when I try to do it from Python.

The Python code is: “ser.write (b’1,200 ')” or “ser.write (b’1,200\n’)”

Note: this Python code send the data correctly because the Arduino LED indicates it (besides you trying it with the code that I started at the beginning).

From the serial monitor it works, as I said before, but, I do not know why it does not recognize it when I send it from Python.

steps = b"800"
    
    x = input("Enter data: ")

    if x == "a":
        ser.write(b'1, %s' % steps)
        x = input("Enter data: ")

Double Check with your pySerial version of Python what write needs to send ascii text

Make sure that the right string is sent (and of course the right port needs to be open and you cannot have the arduino serial monitor opened at the same time)

1 Like

I follow the whole process correctly (in Python), I think the problem is in (I’m not sure):

else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }

receivedChars[ndx] = ‘\0’ Do not receive “rc”. But, when I change it by “rc”, it receives the data from Python, but only when I enter the serial monitor of Python and press ENTER, I do not know why it is not automatically sent.

Remerber, the code is:

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

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

Assuming this works without further encode

You still need the end marker to be sent , try

ser.write(b'1, %s\n' % steps)

( Python 3 introduced a new way to do string formatting that was also later back-ported to Python 2.7)

1 Like

A post was split to a new topic: Help with the Serial Library for APDE Processing

The code from Ribin2’s tutorial is rock solid. The problem is not there, especially true since the code works from the Serial monitor.

The issue must be on the python side. What version of python are you running? Please provide the complete python code showing the opening of the serial port.

1 Like

@J-M-L @cattledog Thank you very much, I already resolved my problem. I wish both successes.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.