Using IRRemote library inside a class

Hey guys,

I'm having trouble using IrRecv inside a class. I get some redefinition errors. Is there something I'm missing?

// Classe Climatisation
// gère un moteur DC branché un pin PWM et une DEL
// possède un DHT11 pour le contrôle de la température
// Tâche : Le moteur et la DEL s'active lorsque la température est supérieure à 23°C
// Tâche : Le moteur et la DEL s'arrête lorsque la température est inférieure à 22°C
// Tâche : Le moteur est sur Pause si la valeur de l'attribue onPause est à true

#pragma once

#include <Arduino.h>
#include <DHT.h>

#include <IRremote.hpp>


#define TEMP_INTERVAL 5000
#define DHTTYPE DHT11

// Énumération pour les états du moteur soit ON, OFF et PAUSE
enum MotorState { ON, OFF, PAUSE };


class Climatisation {
  public:
    // Constructeur
    Climatisation(int pinMotor, int pinLed, int pinDht, int pinIR);

    // Méthodes
    void update();
    void setOnPause(bool value) { _onPause = value; };
    bool getOnPause() { return _onPause; };
    float getTemperature() { return _temperature; };
    float getHumidity() { return _humidity; };
    void setLowTemp(int value) { _lowTemp = value; };
    void setHighTemp(int value) { _highTemp = value; };

    // Méthode pour ajouter un callback
    void setCallback(void (*callback)(bool, String)) { 
      this->callback = callback; 
    }

private:
    int _pinMotor;
    int _pinLed;
    int _pinDht;
    int _pinIR = -1;
    DHT _dht;
    IRrecv _irRecv;

    bool _onPause;
    float _temperature;
    float _humidity;
    unsigned long _currentTime;
    int _lowTemp = 22;
    int _highTemp = 23;
    

    MotorState _motorState = OFF;

    void onState();
    void offState();
    void pauseState();

    void readDht();

    // Callback, état et nom de l'événement
    void (*callback)(bool, String);
    
    void sendEvent(bool);
};
#include "Climatisation.h"

// Constructeur

Climatisation::Climatisation(int pinMotor, int pinLed, int pinDht, int pinIR)
  : _pinMotor(pinMotor), _pinLed(pinLed), _pinDht(pinDht), _pinIR(pinIR), _dht(_pinDht, DHTTYPE), _irRecv(pinIR){
  _dht.begin();

  if (_pinIR != -1) {
    //IrReceiver.begin(_pinIR, false);  // Assurez-vous que _pinIR est initialisé correctement
  }

  _onPause = false;
  _temperature = 0;
  _humidity = 0;
  _currentTime = 0;
}

// Lecture du DHT à l'intervalle TEMP_INTERVAL
void Climatisation::readDht() {
  static unsigned long _dhtPrevious = 0;

  if (_currentTime - _dhtPrevious < TEMP_INTERVAL) return;

  _dhtPrevious = _currentTime;

  _humidity = _dht.readHumidity();
  _temperature = _dht.readTemperature();
}

// Méthode update
void Climatisation::update() {
  _currentTime = millis();

  readDht();

  switch (_motorState) {
    case ON:
      onState();
      break;
    case OFF:
      offState();
      break;
    case PAUSE:
      pauseState();
      break;
    default:
      break;
  }
}

// Méthode onState
void Climatisation::onState() {
  if (_onPause) {
    _motorState = PAUSE;
    sendEvent(false);
    return;
  }
  if (_temperature <= _lowTemp) {
    _motorState = OFF;
    sendEvent(false);
    return;
  }
  digitalWrite(_pinMotor, 255);
  digitalWrite(_pinLed, HIGH);
}

// Méthode offState
void Climatisation::offState() {
  if (_temperature >= _highTemp) {
    _motorState = ON;
    sendEvent(true);
    return;
  }
  digitalWrite(_pinMotor, 0);
  digitalWrite(_pinLed, LOW);
}

// Méthode pauseState
void Climatisation::pauseState() {
  if (!_onPause) {
    _motorState = ON;
    sendEvent(true);
    return;
  }
  digitalWrite(_pinMotor, 0);
}

void Climatisation::sendEvent(bool state) {
  if (callback == NULL) return;

  callback(state, "Climatisation");
}

Errors

private/var/folders/lb/hq1157px7h73_45gyzmw2kch0000gn/T/arduino/sketches/16E98FAD8F09B8B800C32B1CCB7D490F/sketch/prj_maison_pair.ino.cpp.o (symbol from plugin): In function `evenemement(bool, String)':
(.text+0x0): multiple definition of `irparams'
/private/var/folders/lb/hq1157px7h73_45gyzmw2kch0000gn/T/arduino/sketches/16E98FAD8F09B8B800C32B1CCB7D490F/sketch/Climatisation.cpp.o (symbol from plugin):(.text+0x0): first defined here
/private/var/folders/lb/hq1157px7h73_45gyzmw2kch0000gn/T/arduino/sketches/16E98FAD8F09B8B800C32B1CCB7D490F/sketch/prj_maison_pair.ino.cpp.o (symbol from plugin): In function `evenemement(bool, String)':
(.text+0x0): multiple definition of `timerEnableReceiveInterrupt()'

and so on...

Thanks in advance

do you have this as well in your main ino file?


also in the new way to use the library, there is a global receiver instance ready for you.

and note that Multiple instantiation is not supported

Look at GitHub - Arduino-IRremote/Arduino-IRremote: Infrared remote library for Arduino: send and receive infrared signals with multiple protocols

Hi guys,

The intent is to develop an independant system which includes a motor (MOSFET), an indicator led, a DHT11 and the remote to control it.

Here's the prj_maison_pair.ino

#include "Climatisation.h"

unsigned long currentTime = 0;

Climatisation climatisation(8, 9, 10, 26);

void evenemement(bool etat, String nom) {
  Serial.print(nom);
  Serial.print(" : ");
  Serial.println(etat);
}

void setup() {
  Serial.begin(9600);
  climatisation.setCallback(evenemement);
}

void loop() {
  currentTime = millis();
  // put your main code here, to run repeatedly:

  climatisation.update();

}

Ok, I'm getting to something.

I have deleted the content of the "Climatisation.cpp" file. The errors go away. As soon as I include "IRremote.cpp", the redefinition errors start to pops.

I've put #pragma once at the beginning of my file. What am I doing wrong?

Did you include a .cpp file?

Did you read this in @J-M-L answer?

A typo, I meant "IRremote.h".

If it's a singleton, I would have expected something like a "getInstance()" method.

There's an example called "IRremoteExtensionTest", but I can't even build it for the Mega. Are you guys able to build?

There is a substantial difference between what you do with creating a new instance variable of type IRRecv

versus what they do in the example which is a pointer

you pass to the constructor

and they reuse the single instance provided by the library

when creating their custom class.


I just tried opening IRremoteExtensionTest.ino from the library's example in the IDE and it compiled with lots of warnings like

warning: type 'struct IRData' violates the C++ One Definition Rule [-Wodr]
or
note: a different type is defined in another translation unit

so not really well written.


These are warnings?!?! Damn! I thought that red was an international color for error. Yellow is for warnings. Bad UX design!


I'm reading you well, but I'm surely missing something. Usually, when there's a singleton, I should be able to get the instance from the class, but I can't find where it is.

What would be the minimal class code to encapsulate an IRrecv object without injection except the pin number? With that I could be able to close the discussion.

@J-M-L : Merci en passant pour ton aide!

Ok, I hate myself for this...

IRremote.hpp, must be included in the .cpp client class and BEFORE the header!

// Main.ino
#include "ClientClass.h"

//...
// ---------------------

// Client.h
#define USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE
#include <IRremote.hpp>

//...

// ---------------------
// Client.cpp
// IMPORTANT!! Include IRemote.hpp in the Client.cpp even if it's already in the .h
#include <IRremote.hpp>
#include "Climatisation.h"

// ...

Is that in the doc somewhere?

listed above already

so they don't use a singleton, they just instantiate their variable and this is what you need to use.


they talk about why .hpp

see GitHub - Arduino-IRremote/Arduino-IRremote: Infrared remote library for Arduino: send and receive infrared signals with multiple protocols

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.