IO interface with Arduino over Ethernet

06 Jan 2015 20:57 - 07 Jan 2015 01:14 #54655 by mariusl

I needed some extra functions on my mill but I did not want to go the USB route as I had enough problems with USB and Arduino before. So I decided to try the Ethernet interface instead. Well so far it looks great but I would like some other fellows to test it as well please.

You will need an Arduino Uno with an Ethernet shield. I used a second NIC in order to get the best possible performance.

What it gives:
1: 6 digital IO pins. You specify the number of outputs you want and the rest becomes input automatically. Pins used are (4,5,6,7,8,9)
2: 1 MPG encoder channel that makes use of pins 8 and 9. If you use the MPG then you can only specify 4 outputs maximum. Two counts are provided. The old one and the new one. No debounce in the code so you have to debounce with a resistor and cap.
3: 6 Analog inputs with scale factor and offset parameters.
4: 1 Analog output. A pwm signal that can be scaled and offset via parameters.

What to do:
Rename the udpio.txt to udpio and make sure that it is executable. Place it in your path somewhere.
Rename, compile and burn the udpcomms.txt file to an Arduino Uno.
Make sure that you have the IP of the NIC that you are going to use.
Look at the top of the file for some description of what you need to configure.

Please test and let me know how it goes.

File Attachment:

File Name: udpio.hal
File Size:1 KB

File Attachment:

File Name: udpcomms.txt
File Size:4 KB

File Attachment:

File Name: udpio.txt
File Size:8 KB
Last Edit: 07 Jan 2015 01:14 by mariusl.
The following user(s) said Thank You: DocStein99
06 Jan 2015 22:14 #54662 by cncbasher
looks good, testing here too
08 Feb 2015 06:29 - 08 Feb 2015 17:56 #55799 by nebelnoir
halcmd: loadusr -W /bin/udpio 8888 8888 1

('HOST = ', '')
('PORT = ', 8888)
('REMOTE = ', '')
('PORT = ', 8888)
('Number of digital outputs = ', 1)
Traceback (most recent call last):
File "/bin/udpio", line 129, in <module>
service.bind((HOST, H_PORT))
File "<string>", line 1, in bind
socket.error: [Errno 99] Cannot assign requested address
<stdin>:5: /bin/udpio exited without becoming ready

I've connected uno+EthSh to my router with adress
ping is ok,
linuxcnc ubuntu 10.04
(P.S. I tried to run test Arduino sketch with same adress ( ). It works good.)
Last Edit: 08 Feb 2015 17:56 by nebelnoir.
The following user(s) said Thank You: DocStein99
12 Feb 2015 13:56 - 12 Feb 2015 13:59 #55908 by mariusl
Sorry for taking so long to answer. I did not get a notification email to say that you posted.

The host IP should match the actual IP of your interface. I have two Ethernet interfaces so I force one of them to a known IP ( Also make sure that your DHCP on your router will allow the address range.

You have to ensure that the host IP actually exist before you load. For that reason I force the IP address in the network setup program for a specific interface.

Let me know if you still have problems.
Last Edit: 12 Feb 2015 13:59 by mariusl.
14 Feb 2015 20:18 #55975 by Rick G
Neat idea.

If set up for a mega 2560 would add even more pins.
Is there a reason you did not use debounce in the Arduino?

Rick G
20 Feb 2015 01:41 #56124 by mariusl
No reason in particular except maybe to not screw with the timing. If you use hardware de-bounce you only get interrupted once. I tried to get the best throughput of data per cycle.
In hind sight, the throughput is more that good enough and soft de-bounce could be used,
08 Mar 2015 15:06 - 08 Mar 2015 15:06 #56543 by mariusl
I discovered that the receive buffer on the PC side could get flooded due to the fact that the Arduino transmits data without handshaking. It would cause the user component to not be able to address all the messages in the allotted time that it has to compute. As a result of this you could get messages that are delayed for several seconds as they are waiting for the que to be emptied.

The solution is to make the Arduino code only answer when it has received something from the host.
void loop() 

	//encodeTx();  // Moved this from here

	// if there's data available, read a packet
	int packetSize = Udp.parsePacket();
		encodeTx(); // moved to here

	long newPosition =;
	if (newPosition != oldPosition) {
		counters[0] = oldPosition;
		counters[1] = newPosition;
		oldPosition = newPosition;


Last Edit: 08 Mar 2015 15:06 by mariusl.
The following user(s) said Thank You: DocStein99
27 Dec 2016 22:13 #84767 by M4MazakUser
i tried this out yesterday and it works really well. ill hook up an encoder tonight to see if it drops position.
one thing i found was you need to '#' out the following lines in the python code

#import serial
import os
import hal
import sys
import time
import socket # cant remember if i hashed this one as well.
# from gwibber.microblog.can import RECEIVE
# from _socket import SOL_SOCKET
# from IN import SO_BINDTODEVICE
it worked fine after this. -gwibber has been removed from the default debian package list.

please tell me if im doing somthing wierd. im setting up a lathe/ 3d printer/ plasma cutter for myself. and cant really afford the
high cost of mesa cards (aus ---> us exchange rate) ive used them before and they are excellent but uno's are $6 + $12 for an ethernet shield....
27 Dec 2016 23:17 #84775 by M4MazakUser
Well i tried my 5000ppr encoder on it as a test. And yup it aint fast enough. But my engineering friend who writes arduino code a plenty says it's more than adequate. So i geuss I'll go see him.
15 Feb 2017 04:30 #87981 by DocStein99
Hi. I found this while searching for a project to make my own WiFi MPG / hardware interface for LinuxCNC. Thank you for providing the information.

I am going over the Arduino code and am a little confused. Before I test the project, I wanted to modify it for my own needs and be certain the code was tidy. There are functions in the code that are a little inefficient, and some code that is executing that probably should not.
void encodeTx()
	Udp.beginPacket(ipRemote, portRemote);
	uint8_t v = 0;
	for(int c = 0; c < 6; c++)
		adcResult = analogRead(c);
		sprintf(ReplyBuffer,"%4d", adcResult);


		int dummy = c;

		if (c >= iOutputPins)
			int moredummy = c;
				v |= (1<<c);

This is reading only analog values from pins 0-5, and sends the data out. 1/2 way through the loop, it will read digital input values, and do nothing with them, storing to "V" which is never used.

The decodeRX function also wants to set the pin-modes, after the setup function each and every time it receives a UDP packet. Not sure what the purpose of that was, since it would take some pretty sophisticated hardware to process data that could swap input & output pins at runtime.

Just curious....
Time to create page: 0.152 seconds
Powered by Kunena Forum