Processing incoming serial data without blocking

Posted by Chris Drum on Sun 23 Feb 2014 03:00 PM — 2 posts, 18,705 views.

#0
First I want to say thank you so much for your post about processing incoming serial data without blocking using a state machine. I built upon your example and am using that method to accept commands through the serial port to a atmega1284p microcontroller that I am using to control my 3 axis cnc.

I had made a slight change to your original code so that it could accept negative numbers.

Original post http://www.gammon.com.au/forum/?id=11425&reply=1#reply1


The following code is just a dumbed down version of what I used for my cnc. I tested and troubleshooted on my uno before using it in my cnc code. It also uses 32 bit signed and unsigned variables.
typedef enum {  NONE, C, D, F, H, O, R, S, X, Y, Z } states;
states state = NONE;
uint32_t currentValue;
bool negativeValue = 0;
bool messageposted = 0;
int32_t axisposition = 0;

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

void processC(const uint32_t value) {
  Serial.println("Cancel");
  messageposted = 0;
}

void processD(const uint32_t value) { 
  Serial.println("Enable/Disable Drives");
  messageposted = 0;
}

void processF (const uint32_t value) { 
  Serial.println("Feedrate");
  Serial.println(value);
  messageposted = 0;
}

void processH (const uint32_t value) {
  Serial.println("Home");
  messageposted = 0;
}

void processO(const uint32_t value) { 
  Serial.println("Offset");
  messageposted = 0;
}

void processR (const uint32_t value) { 
  Serial.println("Run");
  messageposted = 0;
}

void processS (const uint32_t value) { 
  Serial.println("Spindle Speed");
  Serial.println(value);
  messageposted = 0;
}

void processX (const uint32_t value, const bool negative) {
  Serial.println("X Axis");
  Serial.println(value);
  if (negative) {
    Serial.println("value is negative");
    axisposition = value * -1;
    Serial.println(axisposition);
  }
  else {
    Serial.println("value is positive");
    axisposition = value;
    Serial.println(axisposition);
  }
  messageposted = 0;
}

void processY (const uint32_t value, const bool negative) {
  Serial.println("Y Axis");
  Serial.println(value);
  if (negative) {
    Serial.println("value is negative");
    axisposition = value * -1;
    Serial.println(axisposition);
  }
  else {
    Serial.println("value is positive");
    axisposition = value;
    Serial.println(axisposition);
  }
  messageposted = 0;
}

void processZ (const uint32_t value, const bool negative) {
  Serial.println("Z Axis");
  Serial.println(value);
  if (negative) {
    Serial.println("value is negative");
    axisposition = value * -1;
    Serial.println(axisposition);
  }
  else {
    Serial.println("value is positive");
    axisposition = value;
    Serial.println(axisposition);
  }
  messageposted = 0;
}

void handlePreviousState () {

  switch (state)
  {
  case C:
    processD (currentValue);
    break;
  case D:
    processD (currentValue);
    break;
  case F:
    processF (currentValue);
    break;
  case H:
    processH (currentValue);
    break;
  case O:
    processO (currentValue);
    break;
  case R:
    processR (currentValue);
    break;
  case S:
    processS (currentValue);
    break;
  case X:
    processX (currentValue, negativeValue);
    break;
  case Y:
    processX (currentValue, negativeValue);
    break;
  case Z:
    processX (currentValue, negativeValue);
    break;
  }  // end of switch  

  currentValue = 0; 
  negativeValue = 0; 
}  // end of handlePreviousState

void processIncomingByte (const byte c)  {
  
  if ((c == '-') | (isdigit (c)))  {
    if (c == '-')
      negativeValue = 1;
    if (isdigit (c)) {
      currentValue *= 10;
      currentValue += c - '0';
    }  // end of digit
  }
  else {
    // The end of the number signals a state change
    handlePreviousState ();

    // set the new state, if we recognize it
    switch (c) {
    case 'C':
      state = C;
      break;
    case 'D':
      state = D;
      break;
    case 'F':
      state = F;
      break;
    case 'H':
      state = H;
      break;
    case 'O':
      state = O;
      break;
    case 'R':
      state = R;
      break;
    case 'S':
      state = S;
      break;
    case 'X':
      state = X;
      break;
    case 'Y':
      state = Y;
      break;
    case 'Z':
      state = Z;
      break;
    default:
      state = NONE;
      break;
    }  // end of switch on incoming byte
  } // end of not digit  
  
} // end of processIncomingByte

void loop() {

  if (!messageposted) {    //if we are already posting message, don't post again
    Serial.println("Enter 'H' to perform a homing routine");
    Serial.println("Enter letter of Axis AND Position");
    Serial.println("Or Enter 'S' AND Speed Setpoint for spindle");
    Serial.println("Or Enter 'F' AND value for Feedrate");
    Serial.println("Or Enter 'O' to enalbe/disable zero offset");
    Serial.println("Or Enter 'D' to disable drives");
    messageposted = 1;
  }
  if (Serial.available())
    processIncomingByte (Serial.read ());
}
Amended on Sun 23 Feb 2014 04:17 PM by Chris Drum
Australia Forum Administrator #1
Template:Arduino
Please post Arduino-related questions to the Arduino Forum or to StackExchange: Arduino. This saves splitting questions and answers between this forum and the Arduino ones.