I need cnc machine to run as smooth as possible.
It receives commands like this "M_XY 10.233 20.123".
If i send command by command there is a slight delay between commands and its noticeable. I set serial timeout to 5 ms.
I tried to send n commands and store them on arduino, but arduino cant store much in ram. There is a huge delay while sending n commands.
I was thinking about converting letters (machine writes letters) to bezier and sending arc by arc or letter by letter in arcs. Can atmega328p interpolate bezier fast enough?
Would it be faster if i send numbers in bytes instead of strings? That would be 4 bytes per float and merge with union on arduino.
Is there any better way of doing this i don't know of?
Edit: This is how string commands are processed.
void addCommByte(const byte b){
if(commID == MAX_COMM+1){
commID = 0;
Serial.println("TOO LONG COMMAND");
Serial.flush();
return;
}
if(b == '\n'){
comm[commID] = '\n';
commID = 0;
processCommand();
}
else if(b == '\r')
{
commID = 0;
}
else
{
comm[commID++] = b;
}
}
void loop() {
Serial.flush();
while(Serial.available() > 0) {
addCommByte(Serial.read());
}
}
Edit. Way better way.
C# side. Check for endianness in c#. Arduino is little endian.
public void MOV_X(float mm)
{
SendCharAsByte("q"[0]);
SendFloatAsBytes(mm);
}
public void SendFloatAsBytes(float f)
{
byte[] vOut = BitConverter.GetBytes(f);
serialPort.Write(vOut, 0, 4);
}
public void SendShortAsBytes(short f)
{
byte[] vOut = BitConverter.GetBytes(f);
serialPort.Write(vOut, 0, 2);
}
public void SendCharAsByte(char c)
{
byte[] aaa = new byte[1];
aaa[0] = (byte)c;
serialPort.Write(aaa, 0, 1);
}
Arduino side.
void loop() {
while(Serial.available() > 0) {
processV2(Serial.read());
}
}
// from processV2
if(byt == 'q'){ // mov x
float mm = readFloat();
if(X_DIR == 1) mm *= -1.0;
stepperXY.moveXForMMSync(mm);
Serial.println("p");
return;
}
// merge bytes
union u_tag {
byte b[4];
float fval;
} u;
float readFloat(){
Serial.readBytes(u.b, 4);
return u.fval;
}
There is no need to flush serial.
1 Answer 1
If you have an existing CNC, you may have to abide by its comm protocol. Otherwise, if the Arduino is part of a CNC you are building, and it is supposed to accept commands from a host computer, the first thing to do is make sure your baud rate is set higher than the default. I have found 115200 to be a good choice for stability. Next, you should avoid sending TTY-type text strings, and send binary values instead. You'd send an initial byte or word to specify the command type, followed by the data. In my open-source DaqPort sketch for high-speed data acquisition https://www.daqarta.com/dw_rraa.htm I use the high nybble of the command to specify the general type, and the low nybble to specify more detail like channel number. The sketch uses a big loop with if(Serial.available() > 0) to read the first byte, and a switch/case to determine what to do. The the specific command reads the proper number of bytes and does whatever. This is way faster than having to parse text and convert to binary.
String
as that will cause your system to crash randomly.