Convert a program to work over Ethernet

Hi...

I am having a strange problem.

I have a Arduino connected to 2 DC motors and a laptop via USB.

The laptop has a Gamepad controller connected to another USB and we are able to operate the DC motors using the gamepad.

Stage 1: Setup as follows which is currently working:

Gamepad <--> PC <--> USB <---> Arduino Mega<--> DC Motors

Stage 2: Now I want it to be ported on Ethernet and make it work over Ethernet.

Gamepad <--> PC <--> Ethernet <---> Ethernet Shield on Arduino <- -> Arduino Mega<--> DC Motors

I am just unable to make the Stage 1 code which is working fine port to Stage 2.

Following is Stage 1 Code:

//---------------------------------------------------------------------------
//------------------------Output port-pin assignment------------------------
// Pin assignments for motor controller section Connector C1
// GND_M1dir-2_M1pwm-3_M2dir-4_M2pwm-5_M3dir-6_M3pwm-7_M4dir-8_M4pwm-9_+5V
//
// Pin details for digital input's Connector C5:
// GND_A15_A14_A13_A12_A11_A10_A9_A8_+5v (Analog pins are to be set as digital input)
//
// Pin details for analog input's Connector C6 (The connector is on patch-board of Ethernet shield ):
// GND_A0_A1_A2_A3_A4
//-----------------------------------------------------------------------------
char command ='S';
void setup() 
{
// initialize digital output pin Connector C1
pinMode(2,OUTPUT);pinMode(3,OUTPUT);pinMode(4,OUTPUT);pinMode(5,OUTPUT);
pinMode(6,OUTPUT);pinMode(7,OUTPUT);pinMode(8,OUTPUT);pinMode(9,OUTPUT);
// initialize digital output pin Connector C2
pinMode(23,OUTPUT);pinMode(25,OUTPUT);pinMode(27,OUTPUT);pinMode(29,OUTPUT);
pinMode(31,OUTPUT);pinMode(33,OUTPUT);pinMode(35,OUTPUT);pinMode(37,OUTPUT);
// initialize A8-A15 as digital input (Connector C5)
pinMode(A8,INPUT);pinMode(A9,INPUT);pinMode(A10,INPUT);pinMode(A11,INPUT);
pinMode(A12,INPUT);pinMode(A13,INPUT);pinMode(A14,INPUT);pinMode(A15,INPUT);
Serial.begin(9600);
}

void loop() 
{
if (Serial.available() > 0) {
  command = Serial.read();
    if (command == 'F') 
    {
      //motor1 motor2 clockwise
      digitalWrite(2, HIGH);
      digitalWrite(3, HIGH);

      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
    }
    else if (command == 'R')
    {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);

      digitalWrite(4, LOW);
      digitalWrite(5, HIGH);
    }
    else if (command == 'T')
    {
      digitalWrite(2, HIGH);
      digitalWrite(3, HIGH);

      digitalWrite(4, LOW);
      digitalWrite(5, HIGH);
    }
    else if (command == 'U')
    {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);

      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
    }
    else if (command == 'V')
    {
       digitalWrite(23, HIGH); // Sol-1 ON
    }
    else if(command == 'W')
    {
      digitalWrite(25, HIGH);
    }
    else if(command == 'Y')
    {
      digitalWrite(27, HIGH);
    }
    else if(command == 'Z')
    {
      digitalWrite(29, HIGH);
    }
    else if(command == 'A')
    {
      digitalWrite(31, HIGH);
    }
    else if(command == 'B')
    {
      digitalWrite(33, HIGH);
    }
    else if(command == 'C')
    {
      digitalWrite(35, HIGH);
    }
    else if(command == 'D')
    {
      digitalWrite(37, HIGH);
    }
    else
    {
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);

      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(23, LOW);
      digitalWrite(25, LOW);
      digitalWrite(27, LOW);
      digitalWrite(29, LOW);
      digitalWrite(31, LOW);
      digitalWrite(33, LOW);
      digitalWrite(35, LOW);
      digitalWrite(37, LOW);
    }

    
}
}

request help from the community on how can this code be modified to make it work over ethernet.

thanking everyone for their time!.

There are Ethernet based boxes that take a Serial input, transport the signal over TCP-IP, and restore the Serial signal on the other side.

That would mean zero modification to your code.

See RS-232 over Ethernet « MOXA NPort 5110 »

You’ll need a RS-232 to TTL converter on both sides.

(It’s not cheap though)


If you don’t go that route you’ll need to modify the code on the PC so that the actions on the gamepad controller are sent over Ethernet, add an Ethernet shield on your mega and deal with the incoming packets - whatever transport layer level you chose UDP packets or a full TCP-IP connection. (UDP is a connectionless, faster, and less reliable protocol with low overhead, while TCP/IP is connection-oriented, slower, and more reliable with higher overhead due to error-checking and flow control.) ➜ way cheaper but more coding required.

1 Like

What do you plan to use on the PC to read the Gamepad and generate messages via LAN?

What kind of messages will you send from the PC?
UDP?
TCP?
even HTTP?!?

Hi @saintofinternet ,

there is a tutorial available regarding Ethernet shield usage with Arduino:

https://docs.arduino.cc/hardware/ethernet-shield-rev2/#tutorials

Anyway you'll have to make up your mind about the protocol you want to use as already stated by @noiasca! The tutorial provides examples for different protocols. The Chat Server example may be a good start (finally depending on your PC solution!):

https://docs.arduino.cc/tutorials/ethernet-shield-rev2/chat-server/

I personally prefer to use an ESP32 instead of a Mega plus a shield. The ESP has internal WiFi, much more memory, is smaller and less expensive.

Good luck!
ec2021

I am looking at UDP to control the motors!

What do you plan to use on the PC to read the Gamepad and generate messages via LAN?

It is a robot control and the motors are controlled by the gamepad.

works when using USB.

need to make it work in AP <--> Station mode to control it remotely.

what do you intend to use as you controller (e.g. laptop)?

ok.
If you need more help provide that software and the documentation how to setup UDP messages in that software because most people here will not now what you have installed on your pc currently.

I think I will have to first make the following work.

DC Motors <--> Arduino Mega <--> Ethernet Shield <--> LAN Cable <--> Laptop <--> USB Gamepad

So moving my Gamepad control the DC Motors should react based on the code that I have posted in the first post.

I have given the code that is working without Ethernet Shield.

What else should I share?

I'm not sure you understand that I'm asking for the PC software.

However. Its not relevant for me any more. I'm out. Good luck with your project.

The question you fail to answer is this

DC Motors <--> Arduino Mega <--> Ethernet Shield <--> LAN Cable <--> Laptop <--> USB Gamepad
                                                                  ▲
                                                                  ║
                                                                  ║
                                                                  ║
                                                         what is running
                                                         on the laptop to
                                                         spit out the data
                                                         onto the LAN cable ?

Python Script on the laptop!

OK so you need to modify the script to send UDP packets

➜ instead of opening the Serial port to send data to your Arduino connected through USB, you need to open a socket knowing the right IP address and port used by the Mega + Ethernet shield and then use that socket to build and send UDP packets.

Can you share the Python script?

On the Mega side you need to join the network and open the necessary port and listen for incoming UDP packets.

So both sides need to be rewritten.

1 Like

please find the Python Script below:

import pygame
import socket
import time

# Initialize Pygame
pygame.init()
pygame.joystick.init()

# Connect to the Arduino via serial
#arduino = serial.Serial('COM4', 9600)  # Replace 'COM3' with your Arduino's COM port
#time.sleep(2)  # Allow time for Arduino to reset

# Arduino IP address and port
UDP_IP = "192.168.1.177"  # Replace with your Arduino's IP
UDP_PORT = 80  # Must match the port number in Arduino sketch

# Create a socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

if pygame.joystick.get_count() == 0:
    raise RuntimeError("No joystick detected!")
joystick = pygame.joystick.Joystick(0)
joystick.init()

def get_controller_input():
    button_command = {
        4: (b'F', "Motors Clockwise"),
        5: (b'R', "Motors Anticlockwise"),
        6: (b'T', "Motor 1 clockwise Motor 2 Anticlockwise"),
        7: (b'U', "Motor 1 Anticlockwise Motor 2 clockwise"),
        0: (b'V', "Solenoid 1 on"),
        1: (b'W', "Solenoid 2 on"),
        2: (b'Y', "Solenoid 3 on"),
        3: (b'Z', "Solenoid 4 on"),
    } 
        
    while True:
        pygame.event.pump()

        command_sent = False
        for button, (command, message) in button_command.items():
            if joystick.get_button(button):
                sock.sendto(command, (UDP_IP, UDP_PORT))
                print(message)
                command_sent = True
                break
                
       # Get the state of the hat (D-pad)
        hat_x, hat_y = joystick.get_hat(0)
        
        if hat_x == 0 and hat_y == 1:  # Hat up
            sock.sendto(b'A', (UDP_IP, UDP_PORT))  # Both motors forward
            print("Solenoid 5 on")
        elif hat_x == 0 and hat_y == -1:  # Hat down
            sock.sendto(b'C', (UDP_IP, UDP_PORT))  # Both motors reverse
            print("Solenoid 7 on")
        elif hat_x == -1 and hat_y == 0:  # Hat left
            sock.sendto(b'D', (UDP_IP, UDP_PORT))  # Motor 1 forward, Motor 2 reverse
            print("Solenoid 8 on")
        elif hat_x == 1 and hat_y == 0:  # Hat right
            sock.sendto(b'B', (UDP_IP, UDP_PORT))  # Motor 1 reverse, Motor 2 forward
            print("Solenoid 6 on")
        
        
        time.sleep(0.1)

        if not command_sent:
            sock.sendto(b'S', (UDP_IP, UDP_PORT))  # Send 'S' to Arduino to stop the motor
            sock.sendto(b'X', (UDP_IP, UDP_PORT))  # Sent 'X' to Arduino to stop the solenoid

    time.sleep(0.1)

if __name__ == "__main__":
    try:
        get_controller_input()
    except KeyboardInterrupt:
        sock.close()
        print("Program terminated.")



If you look at the Ethernet library and the Ethernet UDP class, there is a read() function and you’ll see sample code to get UDP packets. You could try to start from this code on the Arduino side.

On the Python code I noticed

Make sure you don’t flood the communication by sending too many messages

Noted both the response. will try to work accordingly!

That isn't all of it. You need to bind to an IP/port.

UDP_IP = ""
UDP_PORT = 5005

# Create a socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))

Edit: I use this in case the bind fails:

try:
   sock.bind((UDP_IP, UDP_PORT))
except:
   print("bind failed socket1")
   sys.exit(1)