Retrieving numbers from the serial communication

I am programming a basic G-code interpreter, and am currently working through the serial parsing for G0 and the x, y, and z coordinates. The coordinates that follow x, y, and z can be of multiple decimals and characters, so i created a loop that adds them all into one double variable. Which works perfectly for numbers like 385, but when I send 5.6 for example it only sends back 5.00. Even though i know that the part of my code where the value is updated runs.

else if(c == 'X') {
      //Serial.println("x");
      multiplier = 1;
      dec_found = false;
      x_co = 0;
          
      while(true) {
            
        c = Serial.read();
   
        if(isWhitespace(c) || c == '\n') break; //End of G command 
            
        else if(isPunct(c)) {    //If punctuation is found 
          Serial.println("dec");
          multiplier = 0.1;
          dec_found = true;
        }
        else if(isDigit(c)) { 
          if(dec_found == true) {  
            Serial.println("dec found");
            Serial.println(c);
            c -= 48;
            c = c * multiplier;
            x_co = x_co + c;
            multiplier = multiplier * 0.1;
          }
          else {
            Serial.println(c);
            c -= 48;
            x_co = x_co * multiplier;
            x_co = x_co + c; 
            multiplier = 10;
          }
        }
      }
      Serial.print("X is ");
      Serial.println(x_co);
    }

I think the problem has to do with what type of variables I am using, 'c' is a char, while x_co and multiplier are doubles. The end game of this code is to use the number stored in x_co for more arithmetic, which will be the number of steps of a motor.

If anybody can figure out a solution to it not printing the decimals that would really be appreciated, thank you.

You've left out a lot of code, but I'm going to guess "inappropriate use of integers"

I guess the solution depends on the stream of data, and what you may expect.

One approach would be to receive the entire (new-line terminated) message and then parse it looking for the X, Y and Z values in the message...

Something like this:

#define MAX_MESSAGE_LENGTH 32

struct XYZ{
  XYZ() {
    x = 0;
    y = 0;
    z = 0;
  }
  double x;
  double y;
  double z;
};

void setup() 
{
  Serial.begin(9600);
  Serial.println("go");
}

void loop() 
{
  if (const char* newMessage = checkForNewMessage(Serial, '\n'))
  {
    XYZ incomingCoordinates;
    char buffer[16];
    if (strstr(newMessage, "X"))
    {
      strcpy(buffer, strchr(newMessage, 'X') + 1);
      incomingCoordinates.x = atof(buffer);
    }
    if (strstr(newMessage, "Y"))
    {
      strcpy(buffer, strchr(newMessage, 'Y') + 1);
      incomingCoordinates.y = atof(buffer);
    }
    if (strstr(newMessage, "Z"))
    {
      strcpy(buffer, strchr(newMessage, 'Z') + 1);
      incomingCoordinates.z = atof(buffer);
    }
    doSomethingWithXYZ(incomingCoordinates);
  }
}

void doSomethingWithXYZ(XYZ& xyz)
{
  Serial.println(F("new value!"));
  Serial.print(F("X\t"));
  Serial.println(xyz.x, 4);
  Serial.print(F("Y\t"));
  Serial.println(xyz.y, 4);
  Serial.print(F("Z\t"));
  Serial.println(xyz.z, 4);
}

const char* checkForNewMessage(Stream& stream, const char endMarker)
{
  static char incomingMessage[MAX_MESSAGE_LENGTH] = "";
  static byte idx = 0;
  if(stream.available())
  {
    incomingMessage[idx] = stream.read();
    if(incomingMessage[idx] == endMarker)
    {
      incomingMessage[idx] = '\0';
      idx = 0;
      return incomingMessage;
    }
    else
    {
      idx++;
      if(idx > MAX_MESSAGE_LENGTH - 1)
      {
        //stream.print(F("{\"error\":\"message too long\"}\n"));  //you can send an error to sender here
        idx = 0;
        incomingMessage[idx] = '\0';
      }
    }
  }
  return nullptr;
}

entered:

X 12.34 Y 34.45 Z 45.67

outputs:

new value!
X 12.3400
Y 34.4500
Z 45.6700

BulldogLowell: One approach would be to receive the entire (new-line terminated) message and then parse it looking for the X, Y and Z values in the message...

Looks like a fancy version of Serial Input Basics :)

And, as a completely separate comment, it seems to me a great deal more sensible to interpret the GCode on a PC. I have never understood why people do that on an Arduino.

...R

Robin2: Looks like a fancy version of Serial Input Basics :)

Right, but with one or two more lessons tacked on...