knolleary / pubsubclient

A client library for the Arduino Ethernet Shield that provides support for MQTT.
http://pubsubclient.knolleary.net/
MIT License
3.79k stars 1.47k forks source link

W5500 Ethernet Module Sudden disconnection #759

Open kadirozdinc opened 4 years ago

kadirozdinc commented 4 years ago

Hello everyone, I desing a pcb (kind of PLC) that has arduino, w5500 mini ethernet module, relay and some other components. I test my pcb on my desk there is no problem, everything works perfectly. after that I place this pcb in a electrical enclosure that have some contactor and some curcuit breaker (fuse).I just connect 12v and ethernet cable to my card (without relay connection and input cable) Sometimes once contactor pulls and leave, My connection was broken and program branches into reconnect routine and reconnect successfully. What might be reason that cause this issue ? Codes are as follows : ``#include

include

include

include

include

define MSG_BUFFER_SIZE (50)

char msg[MSG_BUFFER_SIZE];

SoftwareSerial newPort(2, 3); // Rx:2 Tx:3

// Update these with values suitable for your network. byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; IPAddress ip(162,17,200,23); IPAddress server(162,17,200,22);

EthernetClient ethClient; PubSubClient client(ethClient);

const char clientName = "Eth"; //const char topic = ""; // Inputs and Outputs

int output_timer = 4; int output_rotate = 5; int output_water = 6 ; int output_power = 7;

int input_align = 8; int input_phase = 9; int input_water = A0; int input_move = A1; int input_pump = A2; int input_mode=A3;

// A4 A5 I2C için kullanılabilir A6 A7 boşta. I2C kullanılmayacaksa 4 tane boş pin var.

bool status_conn = false ;

volatile int sec=0;

String command_water; String command_power; String command_rotate; int command_tour; int command_speed_sec;

unsigned long oldTime=0; unsigned long newTime;

void callback(char topic, byte payload, unsigned int length) {

Serial.print(topic); String msg;

if (!(strcmp(topic,"eth/commands"))){

  for (int i=0;i<length;i++) {

msg+=(char)payload[i];

}

//Serial.println(msg); command_power = msg.substring(0,3); command_water = msg.substring(4,7); command_rotate = msg.substring(8,11); command_tour = msg.substring(12,13).toInt(); command_speed_sec = msg.substring(14,17).toInt(); command_speed_sec = 60 * command_speed_sec / 100;

//Serial.println(command_power); //Serial.println(command_water); //Serial.println(command_rotate); Serial.println(command_speed_sec);

//msg="";

}

Serial.println(); }

void reconnect() { Serial.print("State:"); Serial.println(client.state());

// Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect(clientName,"eth/will",1,true,"disconnected")) { Serial.println("connected");

status_conn = true;

  // Subscribe topics
  client.subscribe("eth/commands",1);

} else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" try again in 5 seconds");
  status_conn = false;
  // Wait 5 seconds before retrying
  delay(5000);
}

} }

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

pinMode(output_timer,OUTPUT); pinMode(output_rotate,OUTPUT); pinMode(output_water,OUTPUT); pinMode(output_power,OUTPUT);

digitalWrite(output_timer,HIGH); digitalWrite(output_rotate,HIGH); digitalWrite(output_water,HIGH); digitalWrite(output_power,HIGH);

pinMode(input_align,INPUT_PULLUP); pinMode(input_phase,INPUT_PULLUP); pinMode(input_water,INPUT_PULLUP); pinMode(input_move,INPUT_PULLUP); pinMode(input_pump,INPUT_PULLUP); pinMode(input_mode,INPUT_PULLUP);

client.setServer(server, 1883); client.setCallback(callback); Ethernet.begin(mac, ip);

//  Timer1 Ayarlanması

cli(); // tüm interruptlar dev dışı TCCR1A = 0;// TCCR1A register 0'lanıyor TCCR1B = 0;// TCCR1B register 0'lanıyor TCNT1 = 0;//sayac değeri 0'la // OCRxA karşılaştırma registeri 1Hz değer için ayarlanıyor //16 MHz osilatör,1Hz timer1 ın çalışma frekansı,1024 prescalar OCR1A = 15624;// = (1610^6) / (11024) - 1 (değer 65536 dan küçük) // CTC mod açılıyor. TCCR1B |= (1 << WGM12); // CS10 ve CS12 bitleri 1024 prescaler için ayarlanıyor TCCR1B |= (1 << CS12) | (1 << CS10);
// timer karşılaştırma interruptı aktifleştiriliyor TIMSK1 |= (1 << OCIE1A); sei();//Tüm interruptları çalıştır

delay(1500); newPort.begin(115200); }

// timer aktif olabilmesi için haberleşme,power,mod ve hiza kontrol edilir, herşey normal ise zamana göre timer çıkış verir. ISR(TIMER1_COMPA_vect) {

sec++; if(sec==60) sec=0;

if ( (sec < command_speed_sec) && (command_power.equals("pon")) && (status_conn == true) && (digitalRead(input_mode)== HIGH) && (digitalRead(input_align)== HIGH) ) digitalWrite(output_timer,LOW); else digitalWrite(output_timer,HIGH);

Serial.println(sec); // for debugging purpose Serial.println(status_conn); // for debugging purpose

}

void loop() { delay(60); // kontaktör çektiğinde ve bıraktığında anlık haberleşme kesilmesini önlemek için if (!client.connected()) { reconnect(); } client.loop();

newTime = millis(); if(newTime-oldTime > 1000){ // **** 1 sec events starts

String stat=""; char stats[20]; if (digitalRead(input_align)== HIGH) { stat+="on "; } else stat+="off ";

if (digitalRead(input_phase)== HIGH)

{ stat+="on "; } else stat+="off ";

if (digitalRead(input_water)== HIGH)

{ stat+="on "; } else stat+="off ";

if (digitalRead(input_move)== HIGH)

{ stat+="on "; } else stat+="off ";

if (digitalRead(input_pump)== HIGH)

{ stat+="on "; } else stat+="off ";

if (digitalRead(input_mode)== HIGH)

{ stat+="on "; } else stat+="off ";

stat.toCharArray(stats,20); client.publish("eth/status",stats); //Serial.println(stats); stat="";

 oldTime = newTime;

} // ***** 1 sec events ends

if (newPort.available()) { // send incoming azimuth degree from sensor on the collector to the broker String str=""; char strAzimuth[10]; for (int i=0 ; newPort.available() && i<3 ; i++ ){

   // strAzimuth[i] =(char)newPort.read() ;
  str += (char)newPort.read() ;
  }

  str.toCharArray(strAzimuth,10);

  //Serial.println(strAzimuth);
  client.publish("eth/val",strAzimuth);

} // Loop Starts

if (command_power.equals("pon") && (digitalRead(input_mode)== HIGH) && (digitalRead(input_align)== HIGH) ) digitalWrite(output_power,LOW); else digitalWrite(output_power,HIGH);

if (command_water.equals("won") && (digitalRead(input_mode)== HIGH) && (digitalRead(input_align)== HIGH) ) digitalWrite(output_water,LOW); else digitalWrite(output_water,HIGH);

if (command_rotate.equals("rig") && (digitalRead(input_mode)== HIGH)&& (digitalRead(input_align)== HIGH) ) digitalWrite(output_rotate,LOW); else digitalWrite(output_rotate,HIGH);

// Loop Ends }``

I realize something. When I add some delay at the top of loop, before if (!client.connected()), issue seems to be solved but this doesn't satisfy me. What happens if I control connection state every one seconds instead of in loop ?

baqwas commented 3 years ago

I've been using the Ethernet & PubSubClient libraries with the MKR ETH shield on MKR1000 since last June without any service interruption to a LAN broker that relays to a Node-RED and so on and so forth like the thousand other similar examples of telemetry logging & dashboards.

However when using a clone Nano (my self-inflicted newbie error) and the W5500io shield I've run into many problems stemming from my improper understanding of the constraints. So, I've resorted to basic stepwise refinement and found that the W5500io works fine with genuine Nano but not with the clone Nano (that, in 2020, uses a bootstrapper that was obsolete a decade ago). I followed instructions on converting the clone Nano to the newer bootloader but apparently failed. The upgrade worked as described in the "text books" but the Arduino IDE still recognizes the board a Nano that uses the old bootloader.