Control Robot Over Ethernet

Hi all

I have built a hobby rover robot that I want to control over a ethernet cable. I can do the basic programming stuff but i am still a beginner :smiley: I did the code for controlling the rover direct with one arduino and breadboard. Its was just controlling 8 DC motors.

I want to send me rover to uncharted territory now 100 meters away and wifi will not work for what i want to do and where i want to go :’( I also want to add a POE camera to see where i am going.

I have decided Ethernet with PEO is the best way to go.

I have two options

  1. Control rover from my laptop (not sure how to do this) i will probably have to program a user interface and dont know how to let that talk to the arduino real time.

Control camera from my laptop over ethernet with standard camera software

  1. Control rover from another arduino + ethernet + joystick input

Control camera from laptop over ethernet with standard camera software

any ideas or suggestions around this setup. i have attached a diagram for option 2 above.

I will also appreciate any code contributions as i am clueless with networking code. I am also not working in the it industry so i am not very familiar with networks to start with.

i want to power everything with poe. i found a injector that can supply 48v after 100 meters and then a switch that van supply 24 volts thought each of its 5 ports.
thank you

I want to send me rover to uncharted territory now 100 meters away and wifi will not work for what i want to do and where i want to go

Is your rover going to drag 100 metres of Ethernet cable behind it ?

Umbilicals are generally only useful in underwater or very controlled environments e.g. pipe inspection. If you discover that the cable is a problem, have a look at xBee - likely the high powered ones to get the range you need.

UKHeliBob:

I want to send me rover to uncharted territory now 100 meters away and wifi will not work for what i want to do and where i want to go

Is your rover going to drag 100 metres of Ethernet cable behind it ?

yes its a heavy unit.

wildbill: Umbilicals are generally only useful in underwater or very controlled environments e.g. pipe inspection. If you discover that the cable is a problem, have a look at xBee - likely the high powered ones to get the range you need.

its going underground so wireless wont work :(

I use UDP for this. I am presently using a Mega/Ethernet shield on the remote end and a RPi/Python with a PC-type joystick on the control end.

UDP is really fast and reliable if both devices are the only traffic on the localnet. The UDP.endPacket() call returns a value that indicates delivery success/fail on a localnet. I get 10 packets per second bidirectional, which is plenty for my application.

I use a modified version of the UdpNtpClient example, where the Mega is the client and the RPi is the server.

SurferTim: I use UDP for this. I am presently using a Mega/Ethernet shield on the remote end and a RPi/Python with a PC-type joystick on the control end.

UDP is really fast and reliable if both devices are the only traffic on the localnet. The UDP.endPacket() call returns a value that indicates delivery success/fail on a localnet. I get 10 packets per second bidirectional, which is plenty for my application.

I use a modified version of the UdpNtpClient example, where the Mega is the client and the RPi is the server.

that sounds exactly like what i need.

can you please send more info. lots more info :) including programming and pics :)

can you please send more info. lots more info :slight_smile: including programming and pics :slight_smile:

I can’t provide much more info except maybe some basic examples. I’m working on a project for another company, and it would be unwise of me to give away programming that I am charging someone else for.

Let me see what I can provide for you in the form of a basic example.

SurferTim:

can you please send more info. lots more info :) including programming and pics :)

I can't provide much more info except maybe some basic examples. I'm working on a project for another company, and it would be unwise of me to give away programming that I am charging someone else for.

Let me see what I can provide for you in the form of a basic example.

ok cool i understand. any help will be appreciated :)

Here is the Arduino UDP client sketch. Change the UDPServer setting to the IP of the server running the UDP server code.

#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress ip(192,168,2,2);
IPAddress gateway(192,168,2,1);
IPAddress subnet(255,255,255,0);

unsigned int UDPport = 5005;      // local port to listen for UDP packets

IPAddress UDPServer(xx,xx,xx,xx); // UDP server

const int UDP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ UDP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 

unsigned int noChange = 0;

// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

unsigned long currentTime;
unsigned long secondTime;

unsigned long msPerSecond = 1000UL;

int UDPCount = 0;

void setup() 
{
  Serial.begin(115200);

  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

//  pinMode(10,OUTPUT);
//  digitalWrite(10,HIGH);

// start Ethernet and UDP
  Serial.print(F("Starting w5100..."));
//  Ethernet.begin(mac,ip,gateway,gateway,subnet);

  while(!Ethernet.begin(mac)) {
    Serial.println(F("failed. Retrying in 5 seconds."));
    delay(5000);
    Serial.print(F("Starting w5100..."));
  }

  Serial.println(Ethernet.localIP());
  
  Udp.begin(UDPport);

  delay(2000);

  currentTime=millis();
  secondTime = currentTime;
  
  Serial.println("Ready");
}

void loop()
{
  currentTime = millis();

  getUDPpacket();


  if(currentTime - secondTime > msPerSecond) {
      byte rtnVal = Ethernet.maintain();
      switch(rtnVal) {
        case 1: Serial.println(F("\r\nDHCP renew fail"));        
                break;
        case 2: Serial.println(F("\r\nDHCP renew ok"));        
                break;
        case 3: Serial.println(F("\r\nDHCP rebind fail"));        
                break;
        case 4: Serial.println(F("\r\nDHCP rebind ok"));        
                break;
                
      }
      
          
      Serial.println(F("\r\nUDP send"));
      sendUDPpacket(UDPServer); // send an NTP packet to a time server
      secondTime += msPerSecond;
  }
}

unsigned int udpCount = 0;

// send an NTP request to the time server at the given address 
unsigned long sendUDPpacket(IPAddress& address)
{
  udpCount++;
  
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, UDP_PACKET_SIZE); 


  sprintf((char*)packetBuffer,"Arduino count %u",udpCount);

  Udp.beginPacket(address, UDPport); //NTP requests are to port 123
  Udp.write(packetBuffer,UDP_PACKET_SIZE);
  Udp.endPacket(); 
}


void getUDPpacket() {
  if ( Udp.parsePacket() ) {  
    // We've received a packet, read the data from it

    if(Udp.remoteIP() == UDPServer) {
      Serial.print(F("UDP IP OK  "));
    }
    else {
      Serial.println(F("UDP IP Bad"));
      return;
    }
    if(Udp.remotePort() == UDPport) {
      Serial.println(F("Port OK"));
    }
    else {
      Serial.println(F("Port Bad"));
      return;
    }

    
    Udp.read(packetBuffer,UDP_PACKET_SIZE);  // read the packet into the buffer

    Serial.print(F("Received: "));
    Serial.println((char*)packetBuffer);
  }
}

Here is the UDP server code written in C for a Linux OS. I can’t post the Python code because it has too much confidential stuff in it to modify quickly to interface with this basic Arduino code.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int sock, n, nr;
    socklen_t fromlen;
    struct sockaddr_in server;
    struct sockaddr_in from;
    
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
     printf("Can not create socket in server\n");
 
    memset(&server, 0, sizeof(struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_port = htons(5005);
    server.sin_addr.s_addr = INADDR_ANY;
 
    if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
      printf("Can not bind in server!\n");
    memset(&from, 0, sizeof(struct sockaddr_in));
    fromlen = sizeof(struct sockaddr_in);
    
    
    while(1) {
        int n, l1;
    unsigned char tBuf[48];
    unsigned char outBuf[48];
    
    
    fflush(stdout);

    n = recvfrom(sock, tBuf, sizeof(tBuf), 0, (struct sockaddr*) &from, &fromlen);
        if (n < 0) {
            printf("Can not receive in server!\n");
        }
        if (n == sizeof(nr)) printf("\n\nSuccess\n\n");
//        l1 = ntohl(l1);

    printf("%s from IP:%s, Port:%hu\r\n",&tBuf[0],inet_ntoa(from.sin_addr), ntohs(from.sin_port));

    sprintf(outBuf,"Server: %s\0",tBuf);
    socklen_t length = sizeof(struct sockaddr_in);    

    n = sendto(sock, outBuf, 48, 0, (const struct sockaddr *)&from, fromlen);
    if(n < 0) {
      printf("Can not send from client");
    }
    }
}