Go Down

Topic: UIPEthernet library - two way communication (Read 199 times) previous topic - next topic

west_is_best

So far I have successfully used both sketches UdpServer and UdpClient which are provided with the library UIPEthernet. One of them sends packets in regular intervals, the other only on request. I would like to combine both: a sketch that will send data in regular intervals, but also send additional data on request. I believe the sketch UdpClient can be used with some modification. Here it is in its original form:

Code: [Select]
/*
 * UIPEthernet UdpClient example.
 *
 * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based
 * Ethernet-shield.
 *
 * UIPEthernet uses the fine uIP stack by Adam Dunkels <adam@sics.se>
 *
 *      -----------------
 *
 * This UdpClient example tries to send a packet via udp to 192.168.0.1
 * on port 5000 every 5 seconds. After successfully sending the packet it
 * waits for up to 5 seconds for a response on the local port that has been
 * implicitly opened when sending the packet.
 *
 * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de)
 */

#if defined(__MBED__)
  #include <mbed.h>
  #include "mbed/millis.h"
  #define delay(x) wait_ms(x)
  #define PROGMEM
  #include "mbed/Print.h"
#endif

#include <UIPEthernet.h>
#include "utility/logging.h"

EthernetUDP udp;
unsigned long next;

#if defined(ARDUINO)
void setup() {
#endif 
#if defined(__MBED__)
int main() {
#endif
  #if ACTLOGLEVEL>LOG_NONE
    #if defined(ARDUINO)
      LogObject.begin(9600);
    #endif
    #if defined(__MBED__)
      Serial LogObject(SERIAL_TX,SERIAL_RX);
    #endif
  #endif

  uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};

  Ethernet.begin(mac,IPAddress(192,168,0,6));

  next = millis()+5000;
#if defined(ARDUINO)
}

void loop() {
#endif 

#if defined(__MBED__)
while(true) {
#endif
  int success;
  int len = 0;

  if (millis()>next)
    {
      do
        {
          success = udp.beginPacket(IPAddress(192,168,0,1),5000);
          #if ACTLOGLEVEL>=LOG_INFO
            LogObject.uart_send_str(F("beginPacket: "));
            LogObject.uart_send_strln(success ? "success" : "failed");
          #endif
          //beginPacket fails if remote ethaddr is unknown. In this case an
          //arp-request is send out first and beginPacket succeeds as soon
          //the arp-response is received.
          #if defined(ESP8266)
            wdt_reset();
          #endif
        }
      while (!success && (millis()<next));
      if (success)
        {
        success = udp.write("hello world from arduino");
        #if ACTLOGLEVEL>=LOG_INFO
          LogObject.uart_send_str(F("bytes written: "));
          LogObject.uart_send_decln(success);
        #endif
        success = udp.endPacket();
        #if ACTLOGLEVEL>=LOG_INFO
          LogObject.uart_send_str(F("endPacket: "));
          LogObject.uart_send_strln(success ? "success" : "failed");
        #endif
        do
          {
          //check for new udp-packet:
          success = udp.parsePacket();
          #if defined(ESP8266)
            wdt_reset();
          #endif
          }
        while (!success && (millis()<next));
        if (success)
          {
          #if ACTLOGLEVEL>=LOG_INFO
            LogObject.uart_send_str(F("received: '"));
          #endif
          do
            {
            char c = udp.read();
            #if ACTLOGLEVEL>=LOG_INFO
              #if defined(ARDUINO)
                LogObject.write(c);
              #endif
              #if defined(__MBED__)
                LogObject.printf("%c",&c);
              #endif
            #endif
            len++;
            }
          while ((success = udp.available())>0);
          #if ACTLOGLEVEL>=LOG_INFO
            LogObject.uart_send_str(F("', "));
            LogObject.uart_send_dec(len);
            LogObject.uart_send_strln(F(" bytes"));
          #endif
          //finish reading this packet:
          udp.flush();
          }
        }
      udp.stop();
      next = millis()+5000;
    }
}
#if defined(__MBED__)
}
#endif


OK, so it sends the message "hello world from arduino" every 5000 ms. As far as I understand, in the second half of the sketch there is a part which listens for incoming packets. I've been trying to add some code in this part which will send additional message when a packet is received, for example from Packet Sender or Wireshark. But nothing works. Has anyone managed to achieve this and can provide any hint? Thanks.

Juraj

#1
Apr 05, 2021, 07:56 pm Last Edit: Apr 05, 2021, 07:57 pm by Juraj
1) see the Ethernet library's UDPSendReceiveString example
2) for new projects please use EthernetENC library

btw: I maintain both libraries

west_is_best

#2
Apr 06, 2021, 08:24 pm Last Edit: Apr 06, 2021, 08:25 pm by west_is_best
Thanks a lot Juraj! I used UDPSendReceiveString, changed Ethernet.h to EthernetENC.h, a few other things, and it does exactly what I want. And the code is much more readable (intuitive) than it is in UIPEthernet sketches.

Juraj

Thanks a lot Juraj! I used UDPSendReceiveString, changed Ethernet.h to EthernetENC.h, a few other things, and it does exactly what I want. And the code is much more readable (intuitive) than it is in UIPEthernet sketches.
yes, sorry, the UIPEthernet examples are more like tests then examples. I didn't create the library, I only fix bugs.

west_is_best

#4
Apr 07, 2021, 10:01 pm Last Edit: Apr 07, 2021, 10:03 pm by west_is_best
Here is a little additional info, maybe it will be helpful to someone. Today I spent 3 hours trying to figure out why the same sketch that worked yesterday doesn't work today. I would often get the message "Ethernet cable is not connected", or no message at all in Serial Monitor. Everything went back to normal when I disconnected from my home LAN network one of the switches (5-port 100 Mbit switch, nothing special). Btw. this switch has some problems because, for some reason, its speed is 1/10 of the declared, but it still works and I use it anyway for "non essential consumers". :) Interestingly, the Arduino with which I was working today isn't connected through this switch, but somehow it was affected by it (or by something connected to it, I have an RPI and another Arduino plugged into it). I'll have to investigate more about it, but I wanted to let people know that you never know where problems may come from.

Juraj

#5
Apr 08, 2021, 06:57 am Last Edit: Apr 08, 2021, 06:58 am by Juraj
if you installed EthernetENC with Library Manager, please get the GitHub version. There are some fixes. I will publish a fixed version of the library soon.

west_is_best

#6
Apr 08, 2021, 08:16 pm Last Edit: Apr 08, 2021, 08:18 pm by west_is_best
I downloaded it from Github 2 days ago, so it is the latest one.

Here is the next issue: now I am trying to communicate from my PC with two Arduinos, let's call them A1 and A2. Each one has a different static IP and local port. If I send a message to A1 it responds and it will keep responding on successive messages. However, at the same time A2 doesn't seem to receive any messages which are sent to it, or it does but doesn't respond. It will begin to respond after some time, but at the same time A1 stops to respond. It seems that when a connection is established with one Arduino, there is no way to communicate with the other. These periods last approx. 20-40 seconds. Below is the sketch for A1, for A2 the only difference is that IP is 82 and port is 22000.

Code: [Select]
#include <EthernetENC.h>
#include <EthernetUdp.h>
#define UDP_TX_PACKET_MAX_SIZE 256

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 81);
unsigned int localPort = 21000;      // local port to listen on
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
EthernetUDP Udp;

/* Set up global variables. */
int AI07 = 0;
String strIP = "81";
String strAI07 = "0";
String strSend = "0";
/* End of global variables. */

void setup() {

/* Set up inputs, outputs and other parameters. */ 
  pinMode(A7, INPUT);
  analogReference(INTERNAL);
/* End of inputs, outputs and other parameters. */

  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  while (!Serial)
  {
    ;
  }
  if (Ethernet.hardwareStatus() == EthernetNoHardware)
  {
    while (true)
    {
      delay(1);
    }
  if (Ethernet.linkStatus() == LinkOFF) {
    delay(1000);
    } 
  }
  Udp.begin(localPort);
}

void loop()
{
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    IPAddress remote = Udp.remoteIP();
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);

/* After receiving the incoming message perform whatever action is required. */
    {
      AI07 = analogRead(A7);
      strAI07 = String(AI07);
      strSend = "*" + strIP + "-" + strAI07 + "#";
      Udp.beginPacket({192, 168, 1, 40}, {10000});
      Udp.print(strSend);
      Udp.endPacket();
    }   
/* End of required action. */

  }

  delay(10);
}

Juraj

#7
Apr 10, 2021, 07:28 pm Last Edit: Apr 10, 2021, 07:31 pm by Juraj
what is {192, 168, 1, 40}, {10000} ?

you can use the same port number on both, but  {10000} is not 21000 or 22000.

west_is_best

192.168.1.40 is the address of the computer with which Arduinos are communicating and 10000 is the port on this PC.

west_is_best

I changed the port so that PC and both Arduinos are on 10000, but the result is still the same.

Juraj

#10
Apr 11, 2021, 07:20 am Last Edit: Apr 11, 2021, 07:22 am by Juraj
I changed the port so that PC and both Arduinos are on 10000, but the result is still the same.
{10000} is an array. you pass the address of that array to the function as the port number. it works for IP because IPAddress has overloaded assignment from an array, but is is ugly.
 
see the UDP example of the Ethernet library on how to use beginPacket

west_is_best

#11
Today at 12:14 am Last Edit: Today at 12:15 am by west_is_best
OK, here is what I did. I took the original sketch and made minimal adjustments:

Code: [Select]
#include <EthernetENC.h>
#include <EthernetUdp.h>
#define UDP_TX_PACKET_MAX_SIZE 256

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 81);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged 81";        // a string to send back

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

void setup() {
  // You can use Ethernet.init(pin) to configure the CS pin
  //Ethernet.init(10);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet

  // start the Ethernet
  Ethernet.begin(mac, ip);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start UDP
  Udp.begin(localPort);
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i=0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}


Unfortunately, I still don't have the communication with two Arduinos at the same time. Would you be so kind to create the same experiment as I did and see if it works for you?

Go Up