Git Product home page Git Product logo

Comments (8)

JAndrassy avatar JAndrassy commented on July 26, 2024

maybe changing some settings could help.

there is not enough 'ticks' to handle the sending in time. try to add a few calls to Ethernet.maintain() after endPacket

from ethernetenc.

MBanucu avatar MBanucu commented on July 26, 2024

New code (using Ethernet.maintain()):

#include <Arduino.h>
#include <EthernetENC.h>

void sendPacket(EthernetUDP &Udp, IPAddress &remoteIP, uint16_t remotePort)
{
  auto endPacket = Udp.endPacket();
  Serial.println(String() + "endPacket = " + endPacket);
  delay(3000);
  auto beginPacket = Udp.beginPacket(remoteIP, remotePort);
  Serial.println(String() + "beginPacket = " + beginPacket);
  for (int i = 0; !beginPacket; i++)
  {
    Serial.println(String() + i + " " + micros() + ": maintain = " + Ethernet.maintain());
    beginPacket = Udp.beginPacket(remoteIP, remotePort);
    Serial.println(String() + i + " " + micros() + ": beginPacket = " + beginPacket);
  }
}

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  }
  delay(3000);
  // Enter a MAC address and IP address for your controller below.
  // The IP address will be dependent on your local network:
  byte mac[] = {
      0xA0, 0x36, 0xBC, 0x30, 0xC1, 0x16};
  IPAddress ip(169, 254, 116, 89);

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

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

  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(10);

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

  // 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
    }
  }

  // start UDP
  Udp.begin(localPort);

  IPAddress remoteIP(169, 254, 116, 90);
  uint16_t remotePort = 32769;

  Serial.println(String() + "beginPacket = " + Udp.beginPacket(remoteIP, remotePort));
  for (int i = 0; i < 10; i++)
  {
    Serial.println("next try");
    Serial.println(String() + "i = " + i);
    Serial.println();

    Serial.println(Udp.println(i));
    sendPacket(Udp, remoteIP, remotePort);
    Serial.println("---------------------------------");
  }
}

void loop()
{
}

New output (Serial):

beginPacket = 1
next try
i = 0

3
endPacket = 1
beginPacket = 0
0 6054004: maintain = 0
0 6055104: beginPacket = 0
1 6055784: maintain = 0
1 6056420: beginPacket = 0
2 6058780: maintain = 0
2 6060912: beginPacket = 0
3 6063284: maintain = 0
3 6065420: beginPacket = 0
4 6067788: maintain = 0
4 6069924: beginPacket = 0
5 6072296: maintain = 0
5 6074432: beginPacket = 0
6 6076800: maintain = 0
6 6078932: beginPacket = 0
7 6081304: maintain = 0
7 6083440: beginPacket = 0
8 6085808: maintain = 0
8 6087944: beginPacket = 0
9 6090316: maintain = 0
9 6092448: beginPacket = 0
10 6094820: maintain = 0
10 6097040: beginPacket = 0
11 6099492: maintain = 0
11 6101712: beginPacket = 0
12 6104168: maintain = 0
12 6106388: beginPacket = 0
13 6108844: maintain = 0
13 6111064: beginPacket = 0
14 6113520: maintain = 0
14 6115740: beginPacket = 0
15 6118196: maintain = 0
15 6120412: beginPacket = 0
16 6122868: maintain = 0
16 6125088: beginPacket = 0
17 6127544: maintain = 0
17 6129764: beginPacket = 0
18 6132220: maintain = 0
18 6134440: beginPacket = 0
19 6136896: maintain = 0
19 6139112: beginPacket = 0
20 6141568: maintain = 0
20 6143788: beginPacket = 0
21 6146244: maintain = 0
21 6148464: beginPacket = 0
22 6150920: maintain = 0
22 6153836: beginPacket = 1
---------------------------------
next try
i = 1

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 2

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 3

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 4

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 5

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 6

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 7

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 8

3
endPacket = 1
beginPacket = 1
---------------------------------
next try
i = 9

3
endPacket = 1
beginPacket = 1
---------------------------------

New output (terminal):

0
1
2
3
4
5
6
7
8
9

At i == 0 the 0 is appearing in the terminal when beginPacket == 1 for the next packet. The other times the number is appearing in the terminal when endPacket == 1 for the current packet as expected. So there has to be established a connection first and then everything works as expected.

I think it is worth mentioning this behavior in the Wiki, because it causes a lot of confusion, I believe.

And also it is worth providing this code as example to explain the UDP behavior of the library/chip.

from ethernetenc.

JAndrassy avatar JAndrassy commented on July 26, 2024

try to add in setup()

  if (Ethernet.linkStatus() == LinkOFF) {
    delay(500);
    if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
  }

from ethernetenc.

MBanucu avatar MBanucu commented on July 26, 2024

New code:

#include <Arduino.h>
#include <EthernetENC.h>

void beginPacket(EthernetUDP &Udp, IPAddress &remoteIP, uint16_t remotePort)
{
  auto beginPacket = Udp.beginPacket(remoteIP, remotePort);
  Serial.println(String() + "beginPacket = " + beginPacket);
  for (int i = 0; !beginPacket; i++)
  {
    Serial.println(String() + i + "\t" + micros() + "\tmaintain = " + Ethernet.maintain());
    beginPacket = Udp.beginPacket(remoteIP, remotePort);
    Serial.println(String() + i + "\t" + micros() + "\tbeginPacket = " + beginPacket);
  }
}
void endPacket(EthernetUDP &Udp)
{
  auto endPacket = Udp.endPacket();
  Serial.println(String() + "endPacket = " + endPacket);
}

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  }
  delay(3000);
  // Enter a MAC address and IP address for your controller below.
  // The IP address will be dependent on your local network:
  byte mac[] = {
      0xA0, 0x36, 0xBC, 0x30, 0xC1, 0x16};
  IPAddress ip(169, 254, 116, 89);

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

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

  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(10);

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

  // 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
    }
  }

  // start UDP
  Udp.begin(localPort);

  IPAddress remoteIP(169, 254, 116, 90);
  uint16_t remotePort = 32769;

  auto linkStatus = Ethernet.linkStatus();
  Serial.println(String() + micros() + "\tlinkStatus = " + linkStatus);
  while (linkStatus == LinkOFF)
  {
    linkStatus = Ethernet.linkStatus();
    Serial.println(String() + micros() + "\tlinkStatus = " + linkStatus);
  }

  Serial.println("---------------------------------");
  for (int i = 0; i < 10; i++)
  {
    Serial.println("next try");
    Serial.println(String() + "i = " + i);
    Serial.println();

    beginPacket(Udp, remoteIP, remotePort);
    auto stringToSend = String() + i + "\t" + micros();
    auto bytesSent = Udp.println(stringToSend);
    Serial.println(String() + "bytesSent = " + bytesSent + "\tstringToSend = \"" + stringToSend + "\"");
    endPacket(Udp);
    Serial.println("---------------------------------");
  }
}

void loop()
{
}

New output (Serial):

3051344 linkStatus = 2
3052124 linkStatus = 2
3052944 linkStatus = 2
3053752 linkStatus = 2
3054600 linkStatus = 2
3056636 linkStatus = 2
3058676 linkStatus = 2
3060716 linkStatus = 2
3062756 linkStatus = 1
---------------------------------
next try
i = 0

beginPacket = 1
bytesSent = 11  stringToSend = "0       3070548"
endPacket = 1
---------------------------------
next try
i = 1

beginPacket = 0
0       3081572 maintain = 0
0       3083588 beginPacket = 0
1       3085876 maintain = 0
1       3087924 beginPacket = 0
2       3090208 maintain = 0
2       3092260 beginPacket = 0
3       3094552 maintain = 0
3       3096600 beginPacket = 0
4       3098880 maintain = 0
4       3101648 beginPacket = 1
bytesSent = 11  stringToSend = "1       3103188"
endPacket = 1
---------------------------------
next try
i = 2

beginPacket = 1
bytesSent = 11  stringToSend = "2       3114152"
endPacket = 1
---------------------------------
next try
i = 3

beginPacket = 1
bytesSent = 11  stringToSend = "3       3125116"
endPacket = 1
---------------------------------
next try
i = 4

beginPacket = 1
bytesSent = 11  stringToSend = "4       3136084"
endPacket = 1
---------------------------------
next try
i = 5

beginPacket = 1
bytesSent = 11  stringToSend = "5       3147048"
endPacket = 1
---------------------------------
next try
i = 6

beginPacket = 1
bytesSent = 11  stringToSend = "6       3158012"
endPacket = 1
---------------------------------
next try
i = 7

beginPacket = 1
bytesSent = 11  stringToSend = "7       3168976"
endPacket = 1
---------------------------------
next try
i = 8

beginPacket = 1
bytesSent = 11  stringToSend = "8       3179944"
endPacket = 1
---------------------------------
next try
i = 9

beginPacket = 1
bytesSent = 11  stringToSend = "9       3190908"
endPacket = 1
---------------------------------

New bash line in Debian GNU/Linux 11 (bullseye):

nc -ul -p 32769 | while read -r line; do printf "%s\t%s\n" "$(date +"%T.%N")" "$line"; done

New output in terminal:

00:19:14.665008110	0	3070548
00:19:14.669857686	1	3103188
00:19:14.682479886	2	3114152
00:19:14.689398773	3	3125116
00:19:14.701770366	4	3136084
00:19:14.712442270	5	3147048
00:19:14.727768421	6	3158012
00:19:14.734423976	7	3168976
00:19:14.754557364	8	3179944
00:19:14.765623250	9	3190908

With these lines commented out

  // auto linkStatus = Ethernet.linkStatus();
  // Serial.println(String() + micros() + "\tlinkStatus = " + linkStatus);
  // while (linkStatus == LinkOFF)
  // {
  //   linkStatus = Ethernet.linkStatus();
  //   Serial.println(String() + micros() + "\tlinkStatus = " + linkStatus);
  // }

the output (Serial) is

---------------------------------
next try
i = 0

beginPacket = 1
bytesSent = 11  stringToSend = "0       3052052"
endPacket = 1
---------------------------------
next try
i = 1

beginPacket = 0
0       3062692 maintain = 0
0       3064708 beginPacket = 0
1       3066992 maintain = 0
1       3069044 beginPacket = 0
2       3071328 maintain = 0
2       3073376 beginPacket = 0
3       3075664 maintain = 0
3       3077712 beginPacket = 0
4       3080000 maintain = 0
4       3082048 beginPacket = 0
5       3084340 maintain = 0
5       3086388 beginPacket = 0
6       3088668 maintain = 0
6       3090716 beginPacket = 0
7       3093004 maintain = 0
7       3095052 beginPacket = 0
8       3097340 maintain = 0
8       3099388 beginPacket = 0
9       3102384 maintain = 0
9       3103780 beginPacket = 1
bytesSent = 11  stringToSend = "1       3105984"
endPacket = 1
---------------------------------
[...]

so here the first packet is sent to the ENC28J60 18 ms earlier (3052052 vs 3070548) but it is sent by the ENC28J60 to the Ethernet port approximately at the same time as before (3103780 vs 3101648). But also the time needed for the first packet to be sent changed from 100 ms in this post to 40 ms in the new code. I don't know. I will just use my custom beginPacket() function that spams Udp.beginPacket() and Ethernet.maintain() until it returns true or breaks if it takes more than 200 ms to begin the new packet.

from ethernetenc.

MBanucu avatar MBanucu commented on July 26, 2024

Maybe we can overload int UIPUDP::beginPacket(IPAddress ip, uint16_t port, unsigned long timeout) in the library?

from ethernetenc.

JAndrassy avatar JAndrassy commented on July 26, 2024

don't check the return value of maintain. it only returns true when DHCP was renewed. so if you would even use DHCP, it would be in a few hours.

try to uncomment in Eheternt.h #define UIPETHERNET_DEBUG_UDP

from ethernetenc.

MBanucu avatar MBanucu commented on July 26, 2024

I am using PlatformIO. The setting in the platformio.ini file is

build_flags = -D UIPETHERNET_DEBUG_UDP

to define a macro.

platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
monitor_speed = 115200
lib_deps = 
	; jandrassy/EthernetENC@^2.0.4
	https://github.com/JAndrassy/EthernetENC.git
build_flags = -D UIPETHERNET_DEBUG_UDP

src/main.cpp

#include <Arduino.h>
#include <EthernetENC.h>

// Start building up a packet to send to the remote host specific in ip and port
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
int beginPacket(EthernetUDP &Udp, IPAddress &remoteIP, uint16_t remotePort, unsigned long timeoutMillis)
{
  auto start = millis();
  auto beginPacket = Udp.beginPacket(remoteIP, remotePort);
  Serial.println(String() + "beginPacket = " + beginPacket);
  for (int i = 0; !beginPacket && millis() - start <= timeoutMillis; i++)
  {
    Serial.println(String() + i + "\t" + micros() + "\tmaintain = " + Ethernet.maintain());
    beginPacket = Udp.beginPacket(remoteIP, remotePort);
    Serial.println(String() + i + "\t" + micros() + "\tbeginPacket = " + beginPacket);
  }
  return beginPacket;
}
void endPacket(EthernetUDP &Udp)
{
  auto endPacket = Udp.endPacket();
  Serial.println(String() + "endPacket = " + endPacket);
}

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  }
  delay(3000);
  // Enter a MAC address and IP address for your controller below.
  // The IP address will be dependent on your local network:
  byte mac[] = {
      0xA0, 0x36, 0xBC, 0x30, 0xC1, 0x16};
  IPAddress ip(169, 254, 116, 89);

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

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

  // You can use Ethernet.init(pin) to configure the CS pin
  Ethernet.init(10);

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

  // 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
    }
  }

  // start UDP
  Udp.begin(localPort);

  IPAddress remoteIP(169, 254, 116, 90);
  uint16_t remotePort = 32769;

  // auto linkStatus = Ethernet.linkStatus();
  // Serial.println(String() + micros() + "\tlinkStatus = " + linkStatus);
  // while (linkStatus == LinkOFF)
  // {
  //   linkStatus = Ethernet.linkStatus();
  //   Serial.println(String() + micros() + "\tlinkStatus = " + linkStatus);
  // }

  Serial.println("---------------------------------");
  for (int i = 0; i < 10; i++)
  {
    Serial.println("next try");
    Serial.println(String() + "i = " + i);
    Serial.println();

    if (!beginPacket(Udp, remoteIP, remotePort, 200))
    {
      Serial.println("Error at \"beginPacket\".");
      break;
    }
    auto stringToSend = String() + i + "\t" + micros();
    auto bytesSent = Udp.println(stringToSend);
    Serial.println(String() + "bytesSent = " + bytesSent + "\tstringToSend = \"" + stringToSend + "\"");
    endPacket(Udp);
    Serial.println("---------------------------------");
  }
}

void loop()
{
}

output (Serial)

---------------------------------
next try
i = 0

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "0       3056000"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_poll results in ARP-packet
endPacket = 1
---------------------------------
next try
i = 1

udp beginPacket, rip: 169.254.116.90, port: 32769
previous packet on that connection not sent yet
beginPacket = 0
0       3083176 maintain = 0
udp beginPacket, rip: 169.254.116.90, port: 32769
previous packet on that connection not sent yet
0       3093648 beginPacket = 0
1       3095980 maintain = 0
udp beginPacket, rip: 169.254.116.90, port: 32769
previous packet on that connection not sent yet
1       3106484 beginPacket = 0
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
2       3115672 maintain = 0
udp beginPacket, rip: 169.254.116.90, port: 32769
2       3122052 beginPacket = 1
bytesSent = 11  stringToSend = "1       3124344"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 2

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "2       3146528"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 3

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "3       3168712"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 4

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "4       3190896"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 5

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "5       3213080"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 6

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "6       3235268"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 7

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "7       3257452"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 8

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "8       3279636"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------
next try
i = 9

udp beginPacket, rip: 169.254.116.90, port: 32769
beginPacket = 1
bytesSent = 11  stringToSend = "9       3301820"
udp, uip_poll preparing packet to send: 1, size: 61
udp, uip_packet to send: 0
endPacket = 1
---------------------------------

bash command

nc -ul -p 32769 | while read -r line; do printf "%s\t%s\n" "$(date +"%T.%N")" "$line"; done

output (terminal)

01:32:47.552072005	0	3056000
01:32:47.572464755	1	3124344
01:32:47.593342844	2	3146528
01:32:47.615048660	3	3168712
01:32:47.638821992	4	3190896
01:32:47.660478563	5	3213080
01:32:47.682470830	6	3235268
01:32:47.705098687	7	3257452
01:32:47.726660511	8	3279636
01:32:47.749267772	9	3301820

from ethernetenc.

JAndrassy avatar JAndrassy commented on July 26, 2024

ARP packet asks for the MAC address of the device at the iP address. until a response to ARP packet is not received, the UDP packet can't be send. the uIP library can only have one UDP packet processed at time. the ARP response is cached for some time so next UDP packet is sent immediately.

from ethernetenc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.