Problems talking to my CNC machine (Mega 2560p)

Hello

Wondered if someone could assist.
I am trying to retrieve the X/Y position of my CNC machine (which has a 2560p at it's heart).

When I request the co-ords (Using M114 which works), I only get the first 64 bytes of data?
The DataCounter stops at 63, therefore I miss the speed and other data reported after the X/Y co-ords are returned.

If I plug the CNC machine directly into my laptop and request M114 in the serial monitor, it returns all the data.

What am I missing?

char  TestChar_data[200];                       
byte  Test_data;                        
int   DataCount;

#define GetButton 12

void setup() {

Serial.begin(250000);
Serial1.begin(250000);  

pinMode(GetButton,INPUT);

}

void loop() {

      if (digitalRead (GetButton) == HIGH){

            Test_data=0;
            memset(TestChar_data,0,sizeof(TestChar_data));                          // Clear data from the array

            Serial1.println("M114"); 
            Serial.println("Request data from other Mega...");
            do{} while ((GetButton) == HIGH);    
      }
      

       if (Serial1.available()){                                        // If the data is available, then decode it
       
            do {
               char Test_data=Serial1.read();                           // Read the incoming raw data  
               TestChar_data[DataCount] = Test_data;
               DataCount++;

            } while (Serial1.available());

            Serial.print("DataCount= ");Serial.println(DataCount);
            Serial.println(TestChar_data);
            DataCount=0;
       }
                      
}

OK. Think it's the switch anti-bounce do/while that is killing it

What do you see if you print each character as it arrives rather than putting it in the array ?

The same. Never goes past DataCount=63.

Just tried this loop without anything between the request and the retrieval. Same result.

Also should mention I tried dropping the baud to 115200 on the CNC, but it made no difference.

char  TestChar_data[200];                       
byte  Test_data;                       
int   DataCount;


void setup() {

Serial.begin(250000);
Serial1.begin(250000); 


}

void loop() {

delay(3000);

Test_data=0;
memset(TestChar_data,0,sizeof(TestChar_data));                          // Clear data from the array

Serial1.println("M114");
     

if (Serial1.available()){                                        // If the data is available, then decode it
       
      do {
           char Test_data=Serial1.read();                           // Read the incoming raw data 
           TestChar_data[DataCount] = Test_data;
            DataCount++;

      } while (Serial1.available());

            Serial.print("DataCount= ");Serial.println(DataCount);
            Serial.println(TestChar_data);
            DataCount=0;
}

                     
}

The serial input buffer is 64 characters long. If it is full and you don't read the data quickly enough, any additional characters arriving are thrown away. It seems odd that your latest code can't keep up though.

In any event, try bringing the baud rate down to something farcical like 9600 and see if it makes a difference.

Just tried 9600. Thought I was being stupid. Same result.

The returned data from the CNC machine is usually short, and it doesn't have a problem with those. You can request a whole host of data using various commands and all that data returns fine - as long as they are not longer than 64 characters.

Seems very odd that it works from the Serial Monitor.

Hmm

Maybe try this: lose the delay. Use the blink without delay technique to send M114 every ten seconds or so. Then just read from the CNC serial port and print what you get to standard serial.

Just noticed that sometimes it misses the first character, which allows it to report one more at the end. A clue?

Not sure what you mean by blink without delay.
I will try using millis()

Actually, an easier test would be to send a single M114 in setup and have loop read and echo whatever comes from the CNC.

:o

This is worse!

Now I get garbled data, intermixed with random DataCount numbers. Nothing over 20 characters.

char  TestChar_data[250];                       
byte  Test_data;                        
int   DataCount;


void setup() {

Serial.begin(250000);
Serial1.begin(250000);  

Serial1.println("M119");

}

void loop() {

   
   if (Serial1.available()){                                        // If the data is available, then decode it
       
      do {
           char Test_data=Serial1.read();                           // Read the incoming raw data  
           TestChar_data[DataCount] = Test_data;
           DataCount++;

      } while (Serial1.available());

      Serial.print("DataCount= ");Serial.println(DataCount);
      Serial.println(TestChar_data);
      DataCount=0;
    }

}

Just echo what you're getting, nothing more.

Still too complicated. You need to crawl before you run:

void setup() {

Serial.begin(250000);
Serial1.begin(250000);
delay(1000);

Serial1.println("M119");
}

void loop() {
  while (Serial1.available()){
    char c= Serial1.read();
    Serial.print(c);
  }
}

OK gfvalvo. That works. So where is my code going screwy?

Am I putting the data into the array incorrectly?

I suspect (rightly or wrongly), that the line putting the data into the array during the retrieval loop is enough to let the data overflow.

If that is the case, how would I get over that?

I have already dropped the CNC down to 9600 (which it's can't stay at anyway - otherwise other equipment cannot talk to it).

Unfortunately, I don't think command M575 is implemented yet, which allows you to remotely adjust the baud rate of the comms over serial.

Usually the problem that code like yours gives is that it implicitly assumes that all the data will arrive in one lump. The Arduino is fast compared to serial and so it will often check serial.available to find that there is nothing there.

If that happens, you break out of the loop print and reset data count. Check your output - I'd expect to see all your data but spread over several lines.

You should null terminate the array before you print it too.

Ah. The data does arrive on multiple lines. So does a Null throw it out of the loop?

I just tried a different command - M114. This reports the endstop status.
Using my shoddy loop I should add.

You get:

Reporting endstop status
x_min: open
x2_min: open
y_min: open
y

The reset of the data is missing (>63).

Using gfvalvo's loop - all of it arrives.

So my question is, it appears to be ignoring the fact that it changes lines, so where do I go from here?

How do I get it to put all the returned data into that array?

How much is "all the data"? Is it always EXACTLY the same number characters? Does it have Start / End markers?

Have your read @Robin2's Serial Input Tutorial? There are probably some useful techniques in there.

You'll also want to implement at timeout in case a receive error causes characters to be dropped. If the timeout occurs, discard the whole buffer and try again.

I actually meant M117 in the previous post - That reports the end stops

Not sure what the entire length of the data is. Should be:

Reporting endstop status
x_min: open
x2_min: open
y_min: open
y2_min: open
z_min: open
z2_min: open

So I am getting most of the data, but I need all of it.

This has to be a timeout/full buffer thing. it cashing out at 64 is too much of a coincidence.

Yes- I have read the Serial link you provided

Could I simply set: Serial1.setTimeout(1000);?

You could use gfvalvo's code as a starting place. After reading a char into c, add it to your array and null terminate it. Don't reset your count variable.

Use millis to tell you when a second has elapsed and then print your array.