program flow

Writing a program that reads from the serial port and spits out the numbers. i have it broken up as

void loop()
{
  GetFromSerial();
  GetDeltaX();
  //move x

}

where GetFromSerial(); reads the port one byte at a time puts them into a variable (while loop) that GetDeltaX(); uses.

It seems like GetDeltaX(); is occasionally (1 in 10ish) happening while GetFromSerial(); is still populating the variables (I'm getting the first few digits).

Does that make sense? I'll post the whole code if anyone wants to see it all.

Yes, we need to see the whole code (are you using Serial.available before reading?).

You mean you might need an "if (Serial.available()) { }" clause?

Here is the code:

#include <Stepper.h>  //call stepper.h library
#define STEPS 48  // change this to the number of steps on your motor


Stepper stepperX(STEPS, 6, 7, 4, 5);  // create an instance of the stepper class, specifying the number of steps of the motor and the pins it's attached to
Stepper stepperY(STEPS, 8, 9, 10, 11);

// make variables
const int minbutton = 2; //sensor for min button
const int maxbutton = 3; //sensor for max button

int minstate = 0; 
int maxstate = 0;

int newposX = 0;
int oldposX = 0;
int deltaX =0;

int newposY = 0;
int oldposY = 0;
int deltaY =0;

int newposZ = 0;
int oldposZ = 0;
int deltaZ =0;

int val=0;
int tempval=0;
char axis;
int xval=0;
int yval=0;
int zval=0;

void setup()
{
  pinMode(minbutton, INPUT);  //make input   
  pinMode(maxbutton, INPUT);  //make input
  Serial.begin(9600);   // initialize serial communication:
  Serial.println("Serial Communication started");
  stepperX.setSpeed(50);  // set the speed of the motor to 50 RPMs
  stepperY.setSpeed(50);
  teststepX();//test the stepper setup
  teststepY();
  //GoToBegining();

  Serial.println("x123y123z123 for movement");
  Serial.println("s for status of buttons");
  Serial.println("p for latest positions");
}

void loop()
{
  GetFromSerial();
  delay(250);
  GetDeltaX();
   stepperX.step(deltaX);
  GetDeltaY();
   stepperY.step(deltaY);
  GetDeltaZ();
    //define stepper z
    
  if ((deltaX !=0) || (deltaY!=0) || (deltaZ!=0)){
    Serial.println("Done");
    deltaX=0;
    deltaY=0;
    deltaZ=0;  
  }
  //Serial.println("Loop");
}

void GetFromSerial()
{
  while(Serial.available() > 0)
  {
    tempval=Serial.read();
    if (tempval=='x' || tempval == 'X')    {
      axis='x';
      val=0;
    }
    else if (tempval >='0' && tempval <= '9')    {
      val=val * 10;
      val=val + (tempval - '0');

      if (axis=='x'){
        xval=val;
      }
      else if (axis=='y'){
        yval=val;
      }
      else if (axis=='z'){
        zval=val;
      }
    }
    else if (tempval=='y' || tempval == 'Y')    {
      axis='y';
      val=0;
    }
    else if (tempval=='z' || tempval == 'Z')    {
      axis='z';
      val=0;
    }
    else if (tempval=='s' || tempval == 'S')    {
      PrintState();
      tempval='/0';  //set as null so it wont repeat
    }
    else if (tempval==10)    {
      //Serial.println("nl sent");
      tempval='/0';
    }
    else if (tempval=='p' || tempval == 'P')    {
      Serial.print("val is: ");
      Serial.print(val);
      Serial.print(" xval is: ");
      Serial.print(xval);
      Serial.print(" yval is: ");
      Serial.print(yval);
      Serial.print(" zval is: ");
      Serial.println(zval);
      tempval='/0';  //set as null so it wont repeat
    }
    else    {
      Serial.println("tempval is other");
    }
  }  //end of input in serial buffer

}

void PrintState()
{
  //get values for end sensors
  minstate = digitalRead(minbutton);
  maxstate = digitalRead(maxbutton);

  //display value of end sensors
  Serial.print(minstate);
  Serial.print(" - ");
  Serial.println(maxstate);
}

void teststepX()
{
  Serial.println("Test X Foward");  
  stepperX.step(10);
  delay(250);
  Serial.println("Test X Backward");  
  stepperX.step(-10);
  delay(250);
}

void teststepY()
{
  Serial.println("Test Y Foward");  
  stepperY.step(10);
  delay(250);
  Serial.println("Test Y Backward");  
  stepperY.step(-10);
  delay(250);
}

void GoToBegining()
{
  minstate = digitalRead(minbutton);
  while (minstate !=1)
  {
    stepperX.step(-5);
    Serial.println("step back");
    minstate = digitalRead(minbutton);
  }
}

void GoToEnd()
{
  maxstate = digitalRead(maxbutton);
  while (maxstate !=1)
  {
    stepperX.step(5);
    Serial.println("step foward");
    maxstate = digitalRead(maxbutton);
  }
}

void GetDeltaX()
{
  newposX = xval;
  deltaX=newposX-oldposX;
  if(newposX!=oldposX){
    Serial.print("newposX = ");
    Serial.print(newposX);
    Serial.print(" oldposX = ");
    Serial.print(oldposX);
    Serial.print(" deltaX = ");
    Serial.println(deltaX);
    oldposX=newposX;  
  }
}

void GetDeltaY()
{
  newposY = yval;
  deltaY=newposY-oldposY;
  if(newposY!=oldposY){
    Serial.print("newposY = ");
    Serial.print(newposY);
    Serial.print(" oldposY = ");
    Serial.print(oldposY);
    Serial.print(" deltaY = ");
    Serial.println(deltaY);
    oldposY=newposY;  
  }
}

void GetDeltaZ()
{
  newposZ = zval;
  deltaZ=newposZ-oldposZ;
  if(newposZ!=oldposZ){
    Serial.print("newposZ = ");
    Serial.print(newposZ);
    Serial.print(" oldposZ = ");
    Serial.print(oldposZ);
    Serial.print(" deltaZ = ");
    Serial.println(deltaZ);
    oldposZ=newposZ;
  }
}

as i mentioned, GetDetlaX() (or y or z) sometimes happen while i'm still receiving code.

I will get something like below when i send it X100Y200Z200 and it misreads it.

newposY = 20 oldposY = 200 deltaY = -180 <=premature code execution?
Done
newposY = 200 oldposY = 20 deltaY = 180 <=200 is the value i sent
Done

again, this only happens sometimes, so i'm all sorts of confused.

I had a similar problem doing a similar thing (in my case a CNC mill). Basically you can't use Serial.available() to tell you when the end of the input line is - the serial connection can't send the data fast enough. That's why the loop ends prematurely.

Instead you have to use an end-of-line character. I used '#' to start off with, ie you'd send the string X100Y200Z200# and alter the while loop to keep looping and waiting for input until you receive the '#'.

heh... never thought i would have the problem of my pc being to slow for my microprocessor...

thanks a bunch.

got any pictures of your CNC?

It's not the PC that's too slow, it's the serial port. It's generally good practice to confirm data has arrived rather than assume it is there.

So i spoke to soon. How do i modify my code to read until it sees a # sign?

void GetFromSerial()
{
  while(Serial.available() > 0))
  {
    tempval=Serial.read();
  }  //end of input in serial buffer
}

I trimmed the code down to the important part... basically i want it to keep reading the port until it sees #, then tempval will equal '35'.

Here's the relevant section from my own code, hope it helps.

int i;char t;
char cmd[128];

i=0;
 while(i<127)
  {
    while(Serial.available() <= 0);
    t=Serial.read();
    if(t=='\n' || t=='#') break;
    cmd[i]=t;
    i++;
  }
  cmd[i]=0;

Why not use the CR or LF as the terminating character, then a println at the sending end will append that automatically.

the character isnt important, its just another ascii code, but LF will probably be what i use.

my problem is the rest of the code, not sure i understand how to code it.

Ok so I solved it. It was rather simple, I think my brain was jelly last night as I was working on it.

void GetFromSerial()
{
while(tempval!="#")
  {
  while(Serial.available() > 0))
  {
    tempval=Serial.read();
  }  //end of input in serial buffer
 }
tempval=1;
}

thanks again all.

If the serial buffer contains several characters, such as 1, 4, #, 3, 5, your code will not stop at the #. In that function, tempval is (presumably) not "#" to start with. The 1st while says to do some stuff until tempval is "#". If it isn't to start with, the inner while is entered, which only exits when there is no more serial data to read, regardless of whether a '#' was encountered, or not.

The outer while's conditional test should involve '#', not "#", by the way.

There was sample code posted earlier that handled reading up to the # sign. Why not just use that?

I'm sure you're aware that you are discarding everything but the last character read. If the serial buffer contains '1', '3', '7', '#', when this function ends, tempval will contain '#', and the rest of the data will have been discarded. The point of this function, then, escapes me.

The code i'm using works, it stops when it sees the # and discards anything after that. Maybe the code at the bottom will explain better then i can.

I didn't use the sample code given b.c I didn't fully understand it. the concept i pulled was that it needs a while loop.

I was sniping the code to only the important part, here is the full version. That's the same reason it says "#" rather then '#', typo.

//v1 Moves stepper foward and backwards
//v2 Now connects to a maxbutton and minbutton
//v3 goes back and forth
//v4 added second stepper
//v5 cleaned code, goes home and waits
//v6 asks for new location and goes there
//v6_5 responds after movement
//v7 Solved 5000 problem on VB input
//v8 take 3 inputs and move
//v8_5 cleaned up, removed pong
//V8_5Test testing new serial reading
//V9 New input from serial, adding servo movement, changed direction of x
//V10 Addend end of line character

#include <Stepper.h>  //call stepper.h library
#define STEPS 48  // change this to the number of steps on your motor


Stepper stepperX(STEPS, 6, 7, 4, 5);  // create an instance of the stepper class, specifying the number of steps of the motor and the pins it's attached to
Stepper stepperY(STEPS, 8, 9, 10, 11);

// make variables
const int Xbutton = 2; //sensor for min button
const int Ybutton = 3; //sensor for max button
//const int Zbutton = []; //sensor for max button

int ZeroX = 0; 
int ZeroY = 0;
int ZeroZ = 0;

int newposX = 0;
int oldposX = 0;
int deltaX =0;

int newposY = 0;
int oldposY = 0;
int deltaY =0;

int newposZ = 0;
int oldposZ = 0;
int deltaZ =0;

int val=0;
int tempval=0;
char axis;
int xval=0;
int yval=0;
int zval=0;

char pass=0;
char password='Q';

void setup()
{
  pinMode(Xbutton, INPUT);  //make input   
  pinMode(Ybutton, INPUT);  //make input
  Serial.begin(9600);   // initialize serial communication:
  Serial.println("Serial Communication started");
  stepperX.setSpeed(50);  // set the speed of the motor to 50 RPMs
  stepperY.setSpeed(50);

  Serial.println("Whats the password?");
  while (pass!='Q')  //this is so it doesnt zero the machine everytime it looses power
  {
    while(Serial.available() > 0)
    {
      pass=Serial.read();
    }
  }

  teststepX();//test the stepper setup
  teststepY();
  GoToBegining();

  Serial.println("x123y123z123# for movement");
  Serial.println("s for status of buttons");
  Serial.println("p for latest positions");
}

void loop()
{

  GetFromSerial();
  GetDeltaX();
  stepperX.step(deltaX);
  GetDeltaY();
  stepperY.step(deltaY);
  GetDeltaZ();
  //define stepper z

  if ((deltaX !=0) || (deltaY!=0) || (deltaZ!=0)){
    Serial.println("Done");
    deltaX=0;
    deltaY=0;
    deltaZ=0;  
  }
  //Serial.println("Loop");
}

void GetFromSerial()
{
  while (tempval!='#')
  {
    while(Serial.available() > 0)
    {
      //Serial.println("serial avalible");
      tempval=Serial.read();
      if (tempval=='x' || tempval == 'X')    {
        //Serial.println("axis = x");
        axis='x';
        val=0;
      }
      else if (tempval=='y' || tempval == 'Y')    {
        //Serial.println("axis = y");
        axis='y';
        val=0;
      }
      else if (tempval=='z' || tempval == 'Z')    {
        //Serial.println("axis = z");
        axis='z';
        val=0;
      }
      else if (tempval >='0' && tempval <= '9')    {
        //Serial.println("tempval = number");
        val=val * 10;
        val=val + (tempval - '0');

        if (axis=='x'){
          xval=val;
        }
        else if (axis=='y'){
          yval=val;
        }
        else if (axis=='z'){
          zval=val;
        }
      }

      else if (tempval=='s' || tempval == 'S')    {
        PrintState();
        tempval='/0';  //set as null so it wont repeat
        //Serial.println("tempval = s");
      }
      else if (tempval==10)    {
        //Serial.println("tempval = nl (10)");
        tempval='/0';
      }
      else if (tempval=='p' || tempval == 'P')    {
        Serial.print(" xval is: ");
        Serial.print(xval);
        Serial.print(" yval is: ");
        Serial.print(yval);
        Serial.print(" zval is: ");
        Serial.println(zval);
        tempval='/0';  //set as null so it wont repeat
      }
      else    {
        //Serial.print("tempval is other ");
        //Serial.println(tempval);
      }

    }  //end of input in serial buffer
  }
  tempval=1;
}

void PrintState()
{
  //get values for end sensors
  ZeroX = digitalRead(Xbutton);
  ZeroY = digitalRead(Ybutton);
  //ZeroZ =

  //display value of end sensors
  Serial.print(ZeroX);
  Serial.print(" - ");
  Serial.println(ZeroY);
}

void teststepX()
{
  Serial.println("Test X Foward");  
  stepperX.step(10);
  delay(250);
  Serial.println("Test X Backward");  
  stepperX.step(-10);
  delay(250);
}

void teststepY()
{
  Serial.println("Test Y Foward");  
  stepperY.step(10);
  delay(250);
  Serial.println("Test Y Backward");  
  stepperY.step(-10);
  delay(250);
}

void GoToBegining()
{
  ZeroX = digitalRead(Xbutton);
  while (ZeroX !=1)
  {
    stepperX.step(-5);
    Serial.println("step back Z");
    ZeroX = digitalRead(Xbutton);
  }

  ZeroY = digitalRead(Ybutton);
  while (ZeroY !=1)
  {
    stepperY.step(-5);
    Serial.println("step back Y");
    ZeroY = digitalRead(Ybutton);
  }
}

void GetDeltaX()
{
  newposX = xval;
  deltaX=newposX-oldposX;
  if(newposX!=oldposX){
    Serial.print("newposX = ");
    Serial.print(newposX);
    Serial.print(" oldposX = ");
    Serial.print(oldposX);
    Serial.print(" deltaX = ");
    Serial.println(deltaX);
    oldposX=newposX;  
  }
}

void GetDeltaY()
{
  newposY = yval;
  deltaY=newposY-oldposY;
  if(newposY!=oldposY){
    Serial.print("newposY = ");
    Serial.print(newposY);
    Serial.print(" oldposY = ");
    Serial.print(oldposY);
    Serial.print(" deltaY = ");
    Serial.println(deltaY);
    oldposY=newposY;  
  }
}

void GetDeltaZ()
{
  newposZ = zval;
  deltaZ=newposZ-oldposZ;
  if(newposZ!=oldposZ){
    Serial.print("newposZ = ");
    Serial.print(newposZ);
    Serial.print(" oldposZ = ");
    Serial.print(oldposZ);
    Serial.print(" deltaZ = ");
    Serial.println(deltaZ);
    oldposZ=newposZ;
  }
}

You could do this, and it would be clearer:

void GetFromSerial()
{
   while(Serial.available() > 0)
   {
       tempval = Serial.read();
       if(tempval == '#') break; // Break out of the while loop even of there is
                                      // serial data still in the buffer
       // Do the rest of the stuff...
   }
}