[NOOB] Sensors values to MQTT with Ethernet shield ... Compilation error :(

Hi !!

I managed to send sensors values to my MQTT server using JSON & Serial connection.

I bought a W5100 shield and tried to adapt the code to send it using PubSubClient library and it fails …

I’m sure it’s a beginner’s mistake but can’t figure it out so far …

Help appreciated :slight_smile:

Exact error message is :

ccWmM6Bs.ltrans0.ltrans.o: In function `PubSubClient::PubSubClient(IPAddress, unsigned int, void ()(char, unsigned char*, unsigned int), Client&) [clone .constprop.42]’:

:(.text.startup+0x66): undefined reference to `callback(char*, unsigned char*, unsigned int)’

:(.text.startup+0x68): undefined reference to `callback(char*, unsigned char*, unsigned int)’

collect2.exe: error: ld returned 1 exit status

Here’s the code :

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
byte mac[]    = {  0xED, 0xDE, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 50, 211);
IPAddress server(192, 168, 50, 210);

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

//mq-2 capteur de fumées
int mq2_1 = A4;
int mq2Thres = 400;

#include <EmonLib.h>
EnergyMonitor emon1;
int tension = 230.0;
int pin_sct = 2;

//YF-S201_1
volatile int  flow_frequency_1;  // Measures flow meter pulses
unsigned int  l_min_1;          // Calculated litres/hour                      
unsigned char flowmeter_1 = 2;  // digital PIN 2
unsigned long currentTime;
unsigned long cloopTime;

//LCD
//#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
//LiquidCrystal_I2C lcd(0x27,15, 2);

//DHT22
#include "dht.h"
#define dht_apin_1 A0 // Analog Pin sensor is connected to
dht DHT_1;

//PIR
int pirPin_1 = 52;    //the digital pin connected to the PIR sensor's output
int pir_1;    //valeur (0/1) renvoyée à Node Red

//fonction YF-S201_1
void flow_1 ()                  // Interrupt function
{ 
   flow_frequency_1++;
} 

void setup()
{
  //Demarrage du port série
  //Serial.begin(115200);
  
  //LCD
  //lcd.init();
  //lcd.backlight();

  //MQ-2
  pinMode(mq2_1, INPUT);
  
  //PIR
  pinMode(pirPin_1, INPUT);
  digitalWrite(pirPin_1, LOW);
  
  //YF-S201 (flow sensor)
  pinMode(flowmeter_1, INPUT); 
  attachInterrupt(0, flow_1, RISING);
  sei();
  currentTime = millis();
  cloopTime = currentTime;
  
  //AS-103 capteur de courant
  emon1.current(pin_sct,29);
} 

void loop ()    
{
  Ethernet.begin(mac, ip);
  if (client.connect("arduinoClient2")) {
   currentTime = millis();
   // Every second, calculate and print litres/hour + récupère la valeur des sondes
   if(currentTime >= (cloopTime + 1000))
   {     
      cloopTime = currentTime;              // Updates cloopTime
      //YF-S201 : Pulse frequency (Hz) = 7.5Q, Q is flow rate in L/min. (Results in +/- 3% range)
      l_min_1 = (flow_frequency_1 / 7.5); // (Pulse frequency x 60 min) / 7.5Q = flow rate in L/hour 
      flow_frequency_1 = 0;                   // Reset Counter
      //lecture DHT22
      int readData = DHT_1.read22(dht_apin_1);
      //variables DHT22
      float t_1 = DHT_1.temperature;
      float h_1 = DHT_1.humidity;
      //photoresistance
      int phR_1 = analogRead(A1);
  
     //PIR
     if(digitalRead(pirPin_1) == HIGH)
     {
        pir_1 = 1;
     }
 
     if(digitalRead(pirPin_1) == LOW)
     {
        pir_1 = 0;
     }
     double Irms = emon1.calcIrms(1480); //calcul du courant ?

      //MQ-2
      int mq2_1Value = analogRead(mq2_1);
        if (mq2_1Value > mq2Thres)
      {
        client.publish("MQ-2_1",'1'); //fumée détectée !!
      }
      else
      {
        client.publish("MQ-2_1",'0'); //pas de fumée
      }

    client.publish("DHT_T_1",(char)t_1);
    client.publish("DHT_H_1",(char)h_1);
    client.publish("PIR_1",pir_1);
    client.publish("phR_1",phR_1);
    client.publish("YF_S201_1",l_min_1);
    client.publish("AS_103_1",(char)Irms);
    
    /*
    //sortie JSON série
    //ouverture JSON
    Serial.print("{");
  
    //DHT22_1
    Serial.print("\"DHT_T_1\":");
    Serial.print(t_1);
    Serial.print(",\"DHT_H_1\":");
    Serial.print(h_1);
    //PIR_1
    Serial.print(",\"PIR_1\":");
    Serial.print(pir_1);
    //photo resistance
    Serial.print(",\"phR_1\":");
    Serial.print(phR_1);  
    Serial.print(",\"YF_S201_1\":");
    Serial.print(l_min_1, DEC); //litres par minute  
    Serial.print(",\"AS_103_1\":");
    Serial.print(Irms);
    //fermeture JSON
    Serial.println("}");
  */
  
  //affichage LCD
  //lcd.setCursor(0, 0);
  //lcd.print(t);
  //lcd.setCursor(0, 1);
  //lcd.print(h);
   }
  }
}

Thanks a lot !!

You initialized your pubsubclient with a function called callback, that I assume it's supposed to call when it has traffic for you. You even created a prototype for it, but the function itself isn't defined anywhere so the linker barfs, giving you that slightly cryptic error message.

Rather than the prototype you have, actually define a function called callback.

Thank you for you answer (and time).

As mentioned, I'm quite new to this and don't master it (yet?) :slight_smile:

Could you please be more descriptive (if possible ..) and/or correct the code ?

Thanks a lot !

isn't this defining the function ?

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

Actually, I used some code I havec used to suscribe to some MQTT topics to activate relays, which works well.

In the example I havec found, they were publishing some things too, which I didn't use (on another arduino). I thought that I could reuse that code to publish the sensors values .. and then came the error (other errors were fixed before this post .... I already tried lots of things :slight_smile: )

AlexandreRomain:
isn't this defining the function ?

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

No. That's a prototype. If you drop the semicolon and add an open and close curly brace, it'll be a function definition, albeit for a function that does nothing. It'll compile then.

Look at setup, there's a body enclosed in braces below the void setup() line that contains code. You need the same thing for your callback. What you have now just says that there will be a function called callback defined somewhere, but you never actually define it.

// Callback function header
void callback(char* topic, byte* payload, unsigned int length)
{}

It compiled !

It's not working (can't ping the arduino on LAN) but no more error.

I think I don't really need that 'callback' uhh .. thing as I just need to publish topics.

I will try to figure this out !

If you have any more advices, you're welcome :slight_smile: