Arduino nano + Ethernet + MQTT

La combinaison Arduino Nano avec un module Ethernet pour utiliser la librairie MQTT Pubsubclient  = c’est pas terrible (ou même, c’est de la M***DE). Un bête sketch qui se connecte en DCHP, s’abonne à un topic MQTT et vérifie les messages qui arrivent (1 = j’allume, 0= j’éteins), est incapable de tourner quelques jours sans crasher lamentablement.

J’ai simplifié mon code au maximum. Enlevé toutes les variables inutiles. Mon code n’utilise que 1011 octets de mémoire et laisse plus de la moitié disponible pour l’exécution du code… rien n’y fait. J’ai même cherché des fuites de mémoires dans le code, forcé l’arduino à faire un ping toutes les 30secondes, … après quelques heures, ça plante et je n’ai pas réussi à trouver pourquoi ! Et j’avais la flemme d’aller vérifier les bibliothèques externes utilisées (à mon avis c’est plutôt du côté de PubSubClient qu’il faut creuser)

J’ai même changé de Ethernet, passé d’un chip ENC28J60 à un WIZnet W5500 supposé être plus robuste. Kedal ! Les temps d’uptime sont quasi les même.

Alors j’ai craqué. J’ai pris mon code et je l’ai installé sur un arduino Mega 2560 avec le ethernet shield « officiel » qui traînait sur mon bureau (non, en fait, c’était le matos qui était destiné à faire tourner OpenEnergyMonitor, qui sera un peu retardé du coup). Et là, rien, pas de plantage, tout roule (le sketch optimisé ne prend que 11% de la mémoire cette fois).

Et on ne peut pas dire que mon code est pourri à ce point, enfin, je ne pense pas

#include <PubSubClient.h>
#include <Ethernet.h>
byte MAC_ADDRESS[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x31, 0xB8 };
PubSubClient client;
EthernetClient ethClient;

#define CHAUDIERE 4
#define MQTT_CONSIGNE "/chaudiere/consigne"
#define MQTT_STATUS "/chaudiere/statut"
#define MQTT_PING "/chaudiere/statut/ping"

unsigned long time;

void callback(char* topic, byte* payload, unsigned int length) {
   String topicStr = topic;
   if (topicStr == MQTT_CONSIGNE){
      if(payload[0] == '1'){
         Serial.println(F("Allumage chaudiere"));
         Serial.println(F("ON"));
         digitalWrite(CHAUDIERE,HIGH);
         client.publish(MQTT_STATUS,"ON",true);
      }
      else{
         Serial.println(F("Exctinction chaudiere"));
         digitalWrite(CHAUDIERE,LOW);
         Serial.println(F("OFF"));
         client.publish(MQTT_STATUS,"OFF",true);
      }
   }
}

void setup() {
   Serial.begin(9600);
   pinMode(CHAUDIERE, OUTPUT);
   digitalWrite(CHAUDIERE,LOW);

   if (Ethernet.begin(MAC_ADDRESS) == 0)
   {
      Serial.println(F("Failed to configure Ethernet using DHCP"));
      return;
   }
   client = PubSubClient(MQTT_SERVER, 1883, callback,ethClient);
}

void loop() {
   if (!client.connected()) {
      client.connect("chaudiere", MQTT_USERNAME, MQTT_PASSWORD);
      client.publish(MQTT_STATUS,"Connected");
      client.subscribe(MQTT_CONSIGNE);
   }
   if (millis() > (time + 30000)) {
      time = millis();
      client.publish(MQTT_PING, "ping");
   }

   client.loop();
}

Bref, pour vos systèmes qui doivent utiliser une connectivité Ethernet et communiquer en MQTT, ne faites pas les radins comme moi. Prenez directement un Arduino Mega2560 et pas un Arduino Nano (je n’ai pas tenté l’Arduino Uno, vu que c’est les mêmes fonctionnalités mais packagées différemment).

On verra si ca plante dans les jours qui viennent 🙂

N’hésitez pas à laisser vos commentaires. Avez-vu eu les même soucis ?

Si cet article vous a plu, inscrivez-vous à la newsletter pour être informé de la publication d'autres articles.

Vous pouvez aussi partager cet article sur les réseaux sociaux

Laisser un commentaire