Arduino Stepper Control via Serial Command

Hello, I have a very strange issue. I have an Arduino Leonardo, a L293D driver (but that can be anything), and a scrap 4 wire stepper motor.

I am trying to control the motor trough serial (I am using serial monitor for now). So, I am sending 3 variables: sens (direction), viteza (speed), pasi (steps) trough serial. I am reading it as a char array and then formating them and print them (and it's working this far). If I will send 060100 trough serial I will have 0 for direction, 60 for speed and 100 for steps. If I will send 130256 then: sens=1; viteza=30; pasi=256. So this is working. Then, I am trying to setSpeed(viteza) and make myStepper.step(pasi) if sens=0 or else myStepper.step(-pasi). This is the part that doesn't works.

It's very important to say that stepper_oneRevolution example (modified accordingly: myStepper(pasi, 7,8)) WORKS JUST FINE.

I have tried:

  • instead of pasi=0 at declaration, I've put pasi=200
  • make pasi a constant int and give it 200
  • put a myStepper.setSpeed(60) in the setup()
  • put the print and comand blocks outside the if(serial.available) block
  • somebody on irc told me I haven't allocated enough space for the temporary char arrays used for formating data, so I added them +1 buffer[7] vitezaArr[3] and pasiArr[4], though the program runned fined without this surplus
  • I have put myStepper.step(200) first line in the loop() AND STILL NO RESULT

This is becoming very frustrating. Please help ASAP, I guess it's a very minor bug that I can't probably see right now. Thanks in advance. Here is my full code: gist:5422506 · GitHub

edit: after the prints block there is a myStepper.step(pasi); line. Ignore it, it was only for testing.
edit2: corrected the number of wires of the stepper. 2 wires for Arduino: pin 7 and 8.

 while (Serial.available()) {
buffer[i++] = Serial.read();
buffer[i] = '\0';
}

Is not the way to read serial data. This is because it will read just the first byte and then it will be off before the others arrive.
You need to ether know how many bytes you are expecting or to have some way of indicating the end of a number.

a scrap 2 wire stepper motor.

A 2 wire stepping motor?? Never come across one of those, how do they work? Any more information on that.

It's very important to say that stepper_oneRevolution example (modified accordingly: myStepper(pasi, 7,8)) WORKS JUST FINE.

When referring to anything like that include a link. You might know where that tutorial is but many people do not.

As Grumpy_Mike says, you need some kind of end of packet marker to know when a packet has ended. I use this code:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

when sending serial data from an application. When sending data from the Serial Monitor, adding a start of packet marker can feel awkward, so you could remove SOP, started, and the related uses of each. You can NOT remove EOP, though you can change its value, or ended.

Thank you. I actually was thinking of how to send correctly data via serial. One more question on serial data: you can see that I have to send a boolean value (direction) a 0 -> 99 numeric value (speed) and a 0 -> 999 numeric value (steps). If direction and speed can be send and received as bytes, step cannot because it can be bigger than 255, maximum value of a byte. (I always tought that sending in bytes is ideal). That's why I have used the string approach: just send all data in one string (or char array) and sort it after. My questions is: did I did good? Or there is other better method?

And now, let's get to the issue. I have mentioned that reading the data works fine. I have send trough serial monitor strings like 060100 and got the correct results back: direction=0 speed=60 and steps=100. Not the serial communication is my issue. It's the stepper. It won't start.

My questions is: did I did good?

Yes, you did good. Applications can send binary data (bytes). People (using the Serial Monitor) can not. So, since you are using the Serial Monitor application to send the data, you have to send it as strings.

That doesn't mean, though, that you couldn't do better. For instance, looking at "160100" or "1,60,100" which looks easier to modify to change the range of speed to a three digit value? The strtok() function can be used to get the tokens from the second. Much more limited, and difficult to change, code is needed to parse the first.

 char vitezaArr[2];
vitezaArr[0] = buffer[1];
vitezaArr[1] = buffer[2];
vitezaArr[2] = '\0';

The value in the brackets on the declaration statement (2) is the number of elements, not the index of the last element. You are writing three values into an array that can hold 2. You just stepped on memory you don't own.

 char pasiArr[3];
pasiArr[0] = buffer[3];
pasiArr[1] = buffer[4];
pasiArr[2] = buffer[5];
pasiArr[3] = '\0';

And, you did it again.

 myStepper.step(pasi);
// partea de comanda
myStepper.setSpeed(viteza);

Get moving. When you are done, I'll tell you how fast I wanted you to do it. Well, OK. I guess.

Edit: only an idiot would have put the quote and code icons so close together...

Thank you both, especially to PaulS. This is my final code: gist:5423613 · GitHub

It's working great.

It's modified with both SOP EOP included. I will not include ',' between different data because it's unnecesary: speed and steps will never be bigger than, let's say, 999. So I can send 023 if I want only 23 steps; this way I will have a fixed 3 char length.

I have found out why stepper wouldn't start. It wasn't because memory overwriting at temporary char arrays declarations. It was because of memory overwriting at memset from the setup().

I will start building the c# application for sending the data. Any other help, hint and tips are welcome.

Thank you! And all have a good night tonight. It's 1:30 in the night for me right now.