How can I send a file (.txt) to an Arduino?

Having played with the AccelStepper examples (it's rather nice, isn't it?) I would like to use two- or three steppers on a milling-machine.

In the past, I have used Mach2 software so I know the principles of G-codes etc., and can write appropriate files for the individual movements.
"(start at X146 Y 137 Z-100 [touching, centre])
g90 g0 x146 y137
(start at North)
g91 g0 x0 y137"

What I don't know is ....

How can I send a text-file via Com1 to the Arduino?

I envisage running a sketch on the board but I cannot guess how to put a pre-written file-of-moves out through the Monitor.
Once I have them, I believe that interpreting the G-codes should be simple enough - it will only be a sub-set of the full Monty.

Has anyone any suggestions, please?

Geoff

You'll need flow control of some sort. Or add a SD card slot and put the file on the SD.

I envisage running a sketch on the board but I cannot guess how to put a pre-written file-of-moves out through the Monitor.
Once I have them, I believe that interpreting the G-codes should be simple enough - it will only be a sub-set of the full Monty.

Has anyone any suggestions, please?

The arduino IDE serial monitor is very limited for this kind of application. What you need is a general purpose PC terminal program that supports file transmitting. You also probably need to implement some kind of handshacking between the arduino and the terminal program such as using Xon Xoff flow control, as the Arduino has to handle serial data one byte at a time and does not have enough storage memory to hold a large text file worth of data and then parse and execute the commands, but rather read and execute on the fly so to speak.

I use Brey terminal, it has many features you could utilize, it's free and is a standalone PC exe program, so no installation required.

Lefty

Thank you, both.
Lefty's comments are exactly along the lines I had in mind. The movements of the stepper-motors will be quite slow and time-consuming, so there will be plenty of time to fetch the next instruction on a sort-of Just-In-Time basis.

As I have never dealt with serial-transfer (which is pretty obvious from my dumb questions) do you have any suggestions how to implement Xon/Xoff ?

Also, would the Arduino have to know the file-name that is being sent? I would prefer to be able to name my files as e.g. widget.txt; middle_bearing.GC etc, without having to re-name each before use. (I know I won't be able to re-use most of my old G-code stuff because it is too complex. However, I shall be generating new files for new things from time to time.)

I have downloaded the terminal.exe, thanks for the link. Phew! Yet more learning - my brain hurts!

Does it 'grab' the com port away from Arduino0022 or can they 'share' it so I can make programming-corrections on the fly?

Geoff

geoff_p:
Thank you, both.
Lefty's comments are exactly along the lines I had in mind. The movements of the stepper-motors will be quite slow and time-consuming, so there will be plenty of time to fetch the next instruction on a sort-of Just-In-Time basis.

As I have never dealt with serial-transfer (which is pretty obvious from my dumb questions) do you have any suggestions how to implement Xon/Xoff ?

To enable Xon/Xoff is just a button selection on the Brey terminal program. The arduino sends the ASCII Xon and Xoff characters to control the flow of characters from the PC, so Xon and read a line of text, then send Xoff and excute the text instructions and when ready for more commands again send a Xon character to read another line of text. It may take a little more tuning on the arduino side to work correctly but it's a simple and effective way to control the serial traffic.

Also, would the Arduino have to know the file-name that is being sent?

No, not unless you want to send the name from the text file to the arduino for some purpose. It's just a stream of text data as far as the Arduino is concerned.

I would prefer to be able to name my files as e.g. widget.txt; middle_bearing.GC etc, without having to re-name each before use. (I know I won't be able to re-use most of my old G-code stuff because it is too complex. However, I shall be generating new files for new things from time to time.)

I have downloaded the terminal.exe, thanks for the link. Phew! Yet more learning - my brain hurts!

Does it 'grab' the com port away from Arduino0022 or can they 'share' it so I can make programming-corrections on the fly?

They sort of share. The Arduino IDE is well behaved as it doesn't try and open the comm port until you actual hit the upload button, and it disconnects from the comm port automatically when the upload is done. The terminal program has a connect/disconnect button in the upper left hand that you can manually diconnect without having to close the terminal program if you want to do a upload and then hit connect button to reattach. So if you wanted to upload a new modified sketch you would press disconnect on the terminal program, then upload on the arduino, and when finished press connect on the terminal program. So not fully automatic, but at least you don't have to close and reopen any programs.

Lefty

Geoff

Mr. retroLefty, honoured Sir, etc,

That is a brilliant description of how it works, and answers all my questions to boot! Thank you.

Just one thing: what ASCII (or otherwise) characters represents Xon and Xoff?

I've spent this afternoon sending a text file via Terminal.exe, and echoing it back, one character at a time, as they are received via Serial.println(). I've had to reduce the baud rate to 2400 (no problem) but also found that it all stops at about 130 bytes received. That shouldn't be a problem with my stepper-code - each line is only about a dozen characters - but I did wonder why it happening?

Geoff

I've spent this afternoon sending a text file via Terminal.exe, and echoing it back, one character at a time, as they are received via Serial.println(). I've had to reduce the baud rate to 2400 (no problem) but also found that it all stops at about 130 bytes received. That shouldn't be a problem with my stepper-code - each line is only about a dozen characters - but I did wonder why it happening?

That would allow you to send/receive up to 10 lines before locking up, unless you correct the problem. I think that this WOULD be a problem.

What code is running on the Arduino? You should be able (I am) to send very large files much faster than that. I'm sending whole files (100,000 bytes) to the Arduino at 115200 (using a C# application, not terminal).

Okey Doke, here is the sketch I knocked-up to test it:

int byteCounter = 0;
int incomingByte = 0;	// for incoming serial data

void setup() {
	Serial.begin(2400);	// opens serial port, sets data rate to 9600 bps
}

void loop() {

	// send data only when you receive data:
	if (Serial.available() > 0) {
		// read the incoming byte:
		incomingByte = Serial.read();

		// say what you got:
		Serial.print("I received: ");
		Serial.println(char(incomingByte));
		byteCounter ++;
		Serial.print("Bytes: ");
		Serial.println(byteCounter);
	}
}

And the text file:

Hello World
M98 P300 (cut location thing)
G0 X170 Y45
g0 z-90	(KILL)
M3 s1
g1 z-98 f100
g1 x350 f350
g0 z-90
g0 x200 y5
g1 z-98 f100
g1 y150 f350
M99
H
O300
G0 X200 Y45
g0 z-90	(ROY)
M3 s1
g1 z-97 f100
g1 x350 f200
g0 z-90
g0 x200 y45
g1 z-97 f100
g1 x195 y40
g0 z-90
g0 x200 y45
g1 z-97 f100
g1 y150 f350
M99
H
(WOZ HERE)
O20000
G90 G0 Z-90.00
M05
G90 G0 Z-70.00
G90 G0 X200 Y45
M99

The inane comments are so I have something obvious to look-for in the byte-by-byte echo at the Terminal.

You are dead right, Paul, it does in fact stop at the tenth line.

Geoff

You could use GoBetwino.

I has a function that allows your Arduino to ask GoBewtino for a line from a txt file.

	Serial.begin(2400);	// opens serial port, sets data rate to 9600 bps

No, it doesn't.

	if (Serial.available() > 0) {
		// read the incoming byte:
		incomingByte = Serial.read();

		// say what you got:
		Serial.print("I received: ");
		Serial.println(char(incomingByte));
		byteCounter ++;
		Serial.print("Bytes: ");
		Serial.println(byteCounter);

For each character the Arduino receives, it sends 12 + 2 + 6 + n + 2, where n is the number of digits in byteCounter. That sending of data takes time (a lot of time at 2400 baud). Meanwhile, the PC continues to pump out data. The Arduino serial receive buffer is limited to 128 characters. It appears that the buffer fills up, while the 22+ characters per character read are sent once or twice. Once the buffer is full, additional data is silently routed to the bit bucket.

Chop that code down to

 while (Serial.available() > 0)
 {
  // read the incoming byte:
  incomingByte = Serial.read();

  // say what you got:
  Serial.print(char(incomingByte));
  byteCounter ++;
 }
 Serial.print("Received ");
 Serial.print(byteCounter);
 Serial.println(" bytes...");

Thanks, Paul.
I have since deleted the Serial.println(byteCounter) stuff.

I hadn't realised the serial receive buffer could be filling-up, and thus limiting what I receive.

I've just now been messing with sending an Xoff command back to the terminal.

#define XON 17
#define XOFF 19

int byteCounter = 0;
int incomingByte = 0;	// for incoming serial data

void setup() {
	Serial.begin(2400);	// opens serial port, sets data rate to 2400 bps
}

void loop() {

	// send data only when you receive data:
	if (Serial.available() > 0) 
		{
		if(byteCounter > 20)
			{
				Serial.println(XOFF);
				byteCounter =0;
				delay(10000);
				Serial.println(XON);
			}
		else
			{
				// read the incoming byte:
				incomingByte = Serial.read();
				if( incomingByte == 13 || incomingByte == 32 || incomingByte >= 45)
					{
						// say what you got:
						Serial.print("I received: ");
						Serial.println(char(incomingByte));
						byteCounter ++;
		 			}
		 	}
	}
}

And I've corrected the comment in setup() to properly show I'm trying for 2400 baud.

I guess that next, I must clear the buffer after each 'batch' of data has been decoded into useful motor-movements. Is that a call to Serial.flush()?

Geoff

I guess that next, I must clear the buffer after each 'batch' of data has been decoded into useful motor-movements. Is that a call to Serial.flush()?

The buffer that you are reading from IS cleared by the Serial.read() function, one character at a time. Serial.flush() will dump any unread data. Not likely what you want to do.

				Serial.println(XOFF);

You should send this every time you receive a carriage return.

				Serial.println(XON);

You should send this when you are done dealing with the data that you read.

Sending them at random times, with long delays in between is not the correct way to use them.

						Serial.print("I received: ");
						Serial.println(char(incomingByte));

You are still sending 15 characters for every one received...

Further to all the above, and thanks especially to PaulS, I now have a 'working' (?) method to send-and-receive a file of G-codes, and decode it into stepper-motor movements for my milling machine.

On another thread, "How can I convert a string (of numbers) to an Integer-value?" I received help from zoomkat to abstract the numeric-part of e.g. G1234, which, together with Paul's advice on using serial.write(XOFF) as soon as an End-Of-Line (or CR) arrived, has enabled a so-far, so-good outcome.

I send the decoded commands to the stepper-motors via AccelStepper by Mike M at AccelStepper: AccelStepper Class Reference, which I find is rather nice!

Now the really hard work begins - debugging-and-tweaking it so as to accept a little more G-code.

Thanks to all of you,

Geoff