Arduino constantly "screams" ARP broadcast

Hi everyone,

Since I bought me an Arduino 2560 with a W5100 Ethernet-Shield to measure stuff for my Home-Automation, my network has become totally laggy and unstable.

I have used wireshark to look what is going on there and figured out that the Arduino is “yelling” ARP 192.168.1.248 in a fixed intervall.
This device is my Homematic-Control-Unit, which provides the connection to my server.

When the Arduino is disconnected from the network, all my devices answer pretty fast (<10ms) to a ping request. After it is powered, this goes up to random devices not showing up or as well answering after 200ms.

In my opinion the broadcasts are the source of this problem.
The overall network does contain two wifi-AP’s, two switches and a firewall and a ton more of components.

So my question is - since the Arduino gets its IP by DHCP reservation as well as the device with the a.m. ip (…248) - how can I teach the Arduino the mac-address of the Homematic-device OR use the ARP-table.

From some other posts, I have seen than using the ARP-table might be a problem with the w5100 shield.

Any ideas how to solve this?
Regards,
Maeffjus

BTW: Here is the code I use:
(only the first few lines should be interesting for my problem, CCU is the Homematic-Device)

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>      // Comes with Arduino IDE
#include <OneWire.h>   //für Temperatursensoren DS18B20 http://www.hacktronics.com/code/OneWire.zip
#include <NewPing.h>   //für Ultraschallsensoren SR04 https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip
#include "DHT.h"       //für Temperatursensoren SHT22 https://github.com/adafruit/DHT-sensor-library/archive/master.zip
#include <AS_BH1750.h> //für I2C-Luxmeter https://github.com/hexenmeister/AS_BH1750/archive/master.zip
#include <SFE_BMP180.h>//für I2C-Barometer https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
#include <LCD.h>
#include <LiquidCrystal_I2C.h>


#define I2C_ADDR    0x27 // Define I2C Address where the PCF8574A is
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

int n = 1;

LiquidCrystal_I2C	lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

byte ccu[] = { 192, 168, 1, 248 };                   //das ist die IP der CCU                                    <<user-eingabe<< 
byte mac[] = { 0xAC, 0xCC, 0xBC, 0xCC, 0xCC, 0xCC };  //muss nur bei mehreren homeduinos geändert werden !        <<user-eingabe<<
byte homeduino[] = { 192, 168, 1, 250 };             //das ist die feste IP des Homeduino, wenn DHCP versagt     <<user-eingabe<< 
const byte board = 54;       //"14" = UNO/Duemilanove;  "54" = MEGA2560                                           <<user-eingabe<< 
String homeduino_nummer = "x";  // indiv. Bezeichnung für diese homeduino-box                                     <<user-eingabe<< 
String hm_systemvariable = "homeduino_" + homeduino_nummer +"_";
 
//Input-Kennung: hier wird die Funktion der Eingänge D0 bis D9 festgelegt 
byte iomodus_D[10] = {0, 0, 
                      0,   //D2  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall; "2" = Infrarot;  <<user-eingabe<< 
                      0,   //D3  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall; "2" = 433Mhz-Rx; <<user-eingabe<< 
                      4,   //D4  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      3,   //D5  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      0,   //D6  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      0,   //D7  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      0,   //D8  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                      0    //D9  :"0" = digital_in; "1" = 1wire; "3" = SHTxx; "4" = Ultraschall;                  <<user-eingabe<< 
                       };                                       
 
byte iomodus_baro  = 1;   //"0" = N.C.;  "1" = BMP180                     <<user-eingabe<< 
byte iomodus_lux  = 1;   //"0" = N.C.; "1" = BH1750;                      <<user-eingabe<< 
 
 
 
//hier werden die zuletzt gesendeten sytemvariablen gespeichert
boolean last_digitalin_value_D[10];
float last_digital_value_D[10];
boolean last_digitalin_value_A[6];
float last_analogin_value_A[6];
float last_IR_value;
float last_RF_value;
float last_lux_value;
double last_baro_value;
double last_baroT_value;
 
boolean complete_loop =1;  // wenn 1, dann einmal komplett durchlaufen
 
boolean value;
String befehl;
String I;
int analogwert;
 
float tempNTC;
float B_wert = 3950;
float Tn = 298.15; 
float Rv = 10000;
float Rn = 10000;
float Rt ; 
float temp_tur;
float humidity;
 
float delta_onewire = 0.4;
float delta_sht = 0.2;     
float delta_us = 2;
float delta_analog = 2;
float delta_ntc = 0.2;
float delta_lux = 20;
double delta_baro = 0.2;
double delta_baroT = 0.5;
 
long duration, cm;
 
unsigned long next_full_loop = 0;
unsigned long delta_time = 1800000;
unsigned long delta_tx = 500;  
unsigned long next_tx = 0;
//*********************************  
EthernetClient client;  // Initialize the Ethernet client library
 
AS_BH1750 sensor;   //Initialize BH1750 Luxmeter library
 
#define ALTITUDE 299.0 // seehoehe in metern
SFE_BMP180 pressure;
char status;
double T,P,p0;
 
 
void setup() 
{Serial.begin(9600); // start the Ethernet connection:
 if (Ethernet.begin(mac) == 0) 
   {Serial.println("Failed to configure Ethernet using DHCP"); Ethernet.begin(mac, homeduino);}
 delay(1000);// give the Ethernet shield a second to initialize:
 Serial.println("connecting..."); // if you get a connection, report back via serial:
 if (client.connect(ccu, 8181)) {}
   else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop(); 
 char myIpString[24];  //IP auslesen
 IPAddress myIp = Ethernet.localIP();
 sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]);   
 I = myIpString;
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "IP" + "').State('" + I + "')";
 set_sysvar();
   lcd.begin (16,2);
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home ();                   // go home
 Wire.begin ();
  TWBR = 72;  
  TWSR |= bit (TWPS0);
}
 
//*************** 
void loop()
{if (millis() > next_full_loop)     //mindestens jede Stunde eine komplette Aktualisierung
   {complete_loop = 1; next_full_loop = millis() + delta_time; 
    if (next_full_loop < millis()) {complete_loop = 0;}  
   } 
 //***************  
 for (int i = 2; i < 10; i++)  //behandlung digitaleingänge D2 bis D9
   {if (iomodus_D[i] == 0)
     {pinMode(i, INPUT); 
      value =digitalRead(i);
      if ((!value == last_digitalin_value_D[i]) || complete_loop) 
        {I = String(i);
         befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + value + ")";
         set_sysvar();
         last_digitalin_value_D[i] = value;
        } 
     } 
  }

//******************
 complete_loop = 0;
}
//##############
// subroutine HTTP request absetzen:
void set_sysvar() 
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;
 if (client.connect(ccu, 8181)) 
   {Serial.println(befehl);
    client.println(befehl);
    client.println();
    client.stop();
   }
}

The ethernet shield doesn’t “scream”.

The ethernet shield doesn’t store any ARP settings, so every time it attempts a connection, it does an ARP broadcast. This is the reason in your code:

void set_sysvar() 
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;

// Here is the reason
 if (client.connect(ccu, 8181)) 
   {Serial.println(befehl);
    client.println(befehl);
    client.println();
    client.stop();
   }
}

SurferTim:
The ethernet shield doesn’t “scream”.

The ethernet shield doesn’t store any ARP settings, so every time it attempts a connection, it does an ARP broadcast. This is the reason in your code:

void set_sysvar() 

{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
next_tx = millis() +delta_tx;

// Here is the reason
if (client.connect(ccu, 8181))
  {Serial.println(befehl);
    client.println(befehl);
    client.println();
    client.stop();
  }
}

Thank you!
Now just the problem for me (i just started with the Aduino and coding its language as well):

How can I fix this?
I assume it is somehow related to the client.stop command.
But how would you change this?

Regards,
Maeffjus

I would install that time feature that you commented out, so it only attempts that connection at a preset interval instead of every call to that function.

You might want to look at the "blink without delay" example included with the IDE.

Okay, in general I understand your point, you mean that I should write it periodically?

Since the writing is triggered by either a specific delta or after a certain time, this should stay the same.

Don't you see an option to just avoid the ARP broadcast?

It did not came out clear to me if the w5100 can not use ARP cache by any means or just by something I wrote in the code.
Maybe I can give the mac (which i know) of the HomeMatic-device to the shield with any command in the code?

There is no ARP cache in the w5100. The only way to avoid the ARP broadcasts is to avoid attempting a connection.

So, that means in fact that the W5100 will broadcast the ARP request everytime it connects to any ip?

And my second idea (however this could work - you are the expert(s)), to supply the mac-address in advance - so in fact (in human language) say to the w5100:

Contact 192.168.1.248, it has the mac-address ab-cd-ef-12...

So, that means in fact that the W5100 will broadcast the ARP request everytime it connects to any ip?

Yes.

I don't know of a way to specify the mac address in advance.

That sounds not too good - since it is connected on a switch (but with a broadcast that also doesn't matter - even a hub would not do anything else) together with a control for my central heating oil-burner (Buderus KM200) this often renders some communication to the KM200 invalid.

On the other hand the arduino detects stuff like the environmental brightness - if I only update the variables based on a fixed timer, during the morning time when the brightness increases quickly, this might makes the recorded data much more "rough" rather than updating it along with a certain "delta".

Since I searched like crazy, I found this thread (also from you and not too long ago):

As previously mentioned, it seems that in the w5100 library there is anything that gives a certain mac-address from a command - would it not be possible to write this mac into the variable which connects to a specific ip?

Again I'd like to state out that my coding knowledge isn't good enough to re-engineer the code in the a.m. link but this might be the only option.

Another (and so I guess my final) option would be to use any shield that can use ARP cache - but I have not found anything so far.

EDIT: found another thing which might helps or deliver the function I searched for...?
https://github.com/mysensors/Arduino/blob/master/libraries/UIPEthernet/utility/uip_arp.c