Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. Compilation problem under Arduino 1.8.1

Compilation problem under Arduino 1.8.1

Scheduled Pinned Locked Moved Troubleshooting
2 Posts 1 Posters 1.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    lrtsenar
    wrote on last edited by lrtsenar
    #1

    Hello,

    I tried to compile following code (MyMaster 2.0.0 or same result with 2.1.1) with following error code. For info, it was perfectly working with MySensors 1.5 and Arduino 1.6.5 r5) :

    Linking everything together...
    "C:_myProgFiles\arduino-1.8.1\hardware\tools\avr/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -o "C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820/GenericDevices.ino.elf" "C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820\sketch\GenericDevices.ino.cpp.o" "C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820\libraries\SPI\SPI.cpp.o" "C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820\libraries\Bounce2\Bounce2.cpp.o" "C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820\libraries\DallasTemperature\DallasTemperature.cpp.o" "C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820\libraries\MAX31850_OneWire\OneWire.cpp.o" "C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820/core\core.a" "-LC:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820" -lm
    main.cpp.o (symbol from plugin): In function atexit': (.text+0x0): multiple definition of main'
    C:\Users\xxxxx\AppData\Local\Temp\arduino_build_741820\sketch\GenericDevices.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
    collect2.exe: error: ld returned 1 exit status

    Can anyone help me please ?
    Thx

    • GenericDevices.ino
    #define MY_RADIO_NRF24
    #define MY_RF24_PA_LEVEL RF24_PA_HIGH
    #include <MySensors.h>
    #include "Devices.h"
    
    DECLARE_ID(RELAY);
    DECLARE_ID(BUTTON);
    DECLARE_ID(DALLAST);
    
    void before()
    {
      DECLARE_RELAY(RELAY           // id / name (must be unique)
                  , 3               // pin
                  , bOff            // off at start
                  , true            // reverse output (some relay are active when 0v is present on pin and inactive at 5V)
                  , true);          // persistent
      // button to change the sate of previous declared relay
      DECLARE_BUTTON(BUTTON         // id / name
                   , 4              // pin
                   , RELAY          // linked device
                   , true);         // reverse state when button pushed
      DECLARE_DALLAST(DALLAST               // id / name
                    , 5                     // pin
                    , 30000);               // retrieve temperature every ...
    }
    void setup()
    {
    }
    
    void presentation()
    {
      sendSketchInfo("Generic Device", "2.11a");   // Send the sketch version information to the gateway and Controller
    
      for(int i=1; i<=NBOFDEVICES; i++)
      {
        if (DEVICEMAP[i] != NULL) { DEVICEMAP[i]->presentation(); }
      }
    }
    
    void loop()
    {
      // parse all devices in order to know if change occurs
      for(int i=1; i<=NBOFDEVICES; i++)
      {
          if (DEVICEMAP[i] != NULL) {  DEVICEMAP[i]->checkChange();  }
      }
    }
    
    void receive(const MyMessage &msg)
    {
        if (DEVICEMAP[msg.sensor] != NULL)
        {
          DEVICEMAP[msg.sensor]->setVal(msg);  // call corresponding sensor to take into account data coming from Controller
        }
    }
    
    • Device.h
    #pragma once
    #include <Bounce2.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    #include "ElapsedTime.h"
    
    uint8_t g_nbOfDevice = 0;
    #define NBOFDEVICES g_nbOfDevice
    #define DECLARE_ID(id) static const uint8_t id = ++g_nbOfDevice;
    #define DECLARE_RELAY(id,pin,initialVal,reverseOutput,persistent) \
        static CDOutput o##id(id,pin,#id,initialVal,reverseOutput,0,persistent)
    #define DECLARE_BUTTON(id,pin,linkedId,reverseLinkedId) \
        static CDInput o##id(id,pin,#id,linkedId,reverseLinkedId)
    #define DECLARE_DALLAST(id,pin,period) \
        static CDallasT o##id(id,pin,#id,period);
    #define NOTEWORTHY (reinterpret_cast<CDevice*>(0xDEADBEEF))
    CDevice* g_deviceMap[11] = {NOTEWORTHY};   // static map with maximum number of device declared by node is the number minus 1
    
    void initDeviceMap()
    {
        if (g_deviceMap[0] == NOTEWORTHY)
        {
            memset(g_deviceMap, 0/*NULL*/, sizeof(g_deviceMap));
        }
    };
    #define DEVICEMAP g_deviceMap
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    class CDevice
    {
    public:
        CDevice(uint8_t id, const char* sName, uint8_t pin, uint8_t val=0)
            : m_id(id)
            , m_sName(sName)
            , m_pin(pin)
            , m_val(val)
        {
    #ifdef DEBUG
            Serial.print("CDevice() name="); Serial.print(sName);
            Serial.print(" id="); Serial.println(m_id);
    #endif
            initDeviceMap();  // run only once, after all IDs has been declared with DECLARE_XXXX macro
            g_deviceMap[m_id] = this;
        }
        virtual void presentation() {}                                      // generic behavior
        virtual uint8_t  getVal() { return m_val; }                         // generic behavior
        virtual void setVal(const MyMessage &msg) { m_val = msg.getInt(); } // generic behavior
        virtual void checkChange() {};                                      // used in some devices
    
    protected:
        void save() { saveState(m_id, m_val); }
        void load() { m_val = loadState(m_id); }     // last known state from previous run
    
        uint8_t     m_id;       // device id
        const char* m_sName;    // device name
        uint8_t     m_pin;      // device associated pin
        uint8_t     m_val;      // device generic value
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    const uint8_t bOn  = 1;
    const uint8_t bOff = 0;
    class CDOutput : public CDevice
    {
    public:
        CDOutput(uint8_t id, uint8_t pin, const char* sName, bool bActiveAtStart, bool bReverseOutput, uint8_t linkedId=0, bool bPersistent=false, int sensorTypName=S_LIGHT)
            : CDevice(id, sName, pin, bActiveAtStart ? bOn : bOff)
            , m_linkedId(linkedId == 0 ? id : linkedId)
            , m_bReverseOutput(bReverseOutput)
            , m_bPersistent(bPersistent)
            , m_sensorTypName(sensorTypName)
        {
            pinMode(m_pin, OUTPUT);
            if (m_bPersistent) {  load();  }    // read and set previous state
            dWrite();
        }
    
        virtual void presentation()
        {
            if (m_linkedId == m_id)  // if not linked to other device, declare to GW
            {
                present(m_id, m_sensorTypName, m_sName);
            }
        }
    
        void setVal(const MyMessage &msg)
        {
            if (m_linkedId == m_id)    // if linked to this device
            {
                m_val = msg.getInt();
                dWrite();
                if (m_bPersistent) { save(); }
    #ifdef DEBUG
                Serial.print("CDOutput::setVal id="); Serial.print(m_id);
                Serial.print(", new val=");   Serial.println(m_val);
    #endif
            }
            else    // linked to other device so get value from it
            {
                checkChange();
            }
        }
    
        void dWrite() { digitalWrite(m_pin, m_bReverseOutput ? (m_val ? bOff : bOn) : (m_val ? bOn : bOff) ); }
    
        virtual void checkChange()
        {
            if (m_linkedId != m_id)    // if linked to other device
            {
                m_val = g_deviceMap[m_linkedId]->getVal();  // get value
                dWrite();
                if (m_bPersistent) { save(); }
            }
        }
    
    protected:
        uint8_t m_linkedId;
        bool    m_bReverseOutput;
        bool    m_bPersistent;
        int     m_sensorTypName;
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // used to know the state of digital input (button, state of anything on digital input)
    // TODO: a button should be associated to more than 1 device: a list of id should be managed
    // TODO: should be used to manage analog input too ?
    class CDInput : public CDevice, public MyMessage, public Bounce, public CElapsedTime
    {
    public:
        CDInput(uint8_t id, uint8_t pin, const char* sName, uint8_t linkedId=0, bool bReverse=false, uint32_t delay=0)
            : CDevice(id, sName, pin)
            , MyMessage((linkedId == 0) ? id : linkedId, V_LIGHT)
            , Bounce()
            , CElapsedTime(delay)   // used to send periodically state of this input. 0 = only when change
            , m_linkedId((linkedId == 0) ? id : linkedId)
            , m_bReverse(bReverse)
        {
            pinMode(m_pin, INPUT);
            digitalWrite(m_pin, HIGH);  // internal pull-up
            attach(m_pin);              // Bounce class
            interval(5);                // Bounce class
        };
    
        virtual void presentation()
        {
            if (m_linkedId == m_id)     // if not dedicated to linked id, declare this to GW
            {
                present(m_id, S_BINARY, m_sName);
            }
        }
    
        // should be called periodically in order to check pin state
        virtual void checkChange()
        {
            bool bSend = false;
            update();                   // Bounce class
            int iVal = read();          // Bounce class
    
            if (!m_bEnabled)            // status should not be sent periodically
            {
                bSend = (iVal != m_val) && ((m_linkedId != m_id) && (iVal == 0));
            }
            else if (isElapsed())       // status should be sent periodically
            {                           // in this case, always (not olny when change) send state to GW
                bSend = true;
                start();
            }
    
            if (bSend)
            {
                send(set(g_deviceMap[m_linkedId]->getVal() ? !m_bReverse : m_bReverse), true);
            }
            m_val = iVal;           //  memorize old value
    
        }
    
    protected:
        uint8_t      m_linkedId;  // Id with which device (button for instance) is associated
        bool         m_bReverse;  // used for button to invert state of attached relay for instance
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #define MAX_ATTACHED_DS18B20 16
    // (D)allas (T)emperature (S)tate automaton
    const uint8_t DTS_BEGIN=1;
    const uint8_t DTS_REQUEST=2;
    const uint8_t DTS_RETRIEVE=3;
    
    class CDallasT : public CDevice, public MyMessage, public CElapsedTime
    {
    public:
        // period : minimum allowed time between two request of temperature
        CDallasT(uint8_t id, uint8_t pin, const char* sName, uint32_t period)
            : CDevice(id, sName, pin)
            , MyMessage(id, V_TEMP)
            , CElapsedTime(ELAPSED_NOW) // at startup, time is elapsed
            , m_oneWire(pin)
            , m_dallasT(&m_oneWire)
            , m_state(DTS_BEGIN)  // 1st time, request should be done
            , m_requestPeriod(period)
        {
    // try       m_dallasT.setOneWire(&m_oneWire);
            m_dallasT.begin();
            m_dallasT.setWaitForConversion(false);      // requestTemperatures() will not block current thread
        }
    
        // shoud be called periodically in order to check if temperature has to be measured
        virtual void checkChange()
        {
    // TODO: ? check if this state works in constructor. If yes, DTS_BEGIN should be removed
            if (m_state == DTS_BEGIN)   // run only once (init)
            {
                m_nbOfSensors = m_dallasT.getDeviceCount(); // Fetch the number of attached temperature sensors
                for (int i=0; (i<m_nbOfSensors) && (i<MAX_ATTACHED_DS18B20); i++)
                {
                    present(m_id+i, S_TEMP, "DallasT");
                }
                m_conversionTime = m_dallasT.millisToWaitForConversion(m_dallasT.getResolution());
                m_state = DTS_REQUEST;
            }
            if (isElapsed())
            {
                if (m_state == DTS_REQUEST)
                {
                    m_dallasT.requestTemperatures();    // request temperature from Dallas sensor
                    m_state = DTS_RETRIEVE;             // next time, retrieve temperature will be done
                    start(m_conversionTime);            // 'wait' for end of temperature sampling
                }
                else if (m_state == DTS_RETRIEVE)
                {
                    // Read temperatures and send them to controller
                    for (int i=0; (i<m_nbOfSensors) && (i<MAX_ATTACHED_DS18B20); i++)
                    {
                        // fetch and round temperature to one decimal
                        float tp = getConfig().isMetric
    //                      float tp = getControllerConfig().isMetric
                                 ? m_dallasT.getTempCByIndex(i) : m_dallasT.getTempFByIndex(i);
                        tp = static_cast<float>(static_cast<int>(tp * 10.)) / 10.;
    
                        if ((tp != m_fTempPrev[i]) && (tp != -127.00) && (tp != 85.00))
                        {
                            send(setSensor(m_id+i).set(tp, 1));
                            m_fTempPrev[i] = tp;   // Save new temperature for next compare
                        }
                    }
                    m_state = DTS_REQUEST;      // next time, request temperature will be asked
                    start(m_requestPeriod);     // once temperature is retrieved, wait for next request to retrieve again
                }
            }
        }
    
    protected:
        OneWire             m_oneWire;
        DallasTemperature   m_dallasT;
        float               m_fTempPrev[MAX_ATTACHED_DS18B20];
        uint8_t             m_state;         // internal state to toggle between 1st init, request and retrieve temperature
        uint32_t            m_requestPeriod;
        uint32_t            m_conversionTime;
        int                 m_nbOfSensors;
    };
    
    
    • ElapsedTime.h
    #pragma once
    
    const uint32_t ELAPSED_NOW=1;
    
    // used to check if set time is elapsed
    class CElapsedTime
    {
    public:
        CElapsedTime(uint32_t delay=0)  // by default, this component is disabled (delay=0) because of using it in generic derivated object
        {
            m_delay = delay;
            start();
        }
        ~CElapsedTime() {};
    
        // start to count requested 'wait' time. If delay is 0, isElapsed() always returns 'false' (component disabled)
        void start(uint32_t delay=0)
        {
            m_tStart = millis();
            if (delay != 0) {  m_delay = delay;  }
            m_bEnabled = (m_delay != 0);
        }
    
        void disable() { m_bEnabled = false; }
    
        // check if requested time is elapsed since previous call of 'start' method
        bool isElapsed()
        {
            // overflow (every 49.71 days) is natively managed by unsigned var
            return m_bEnabled && ((millis() - m_tStart) > m_delay);
        }
    
    protected:
        uint32_t m_tStart;
        uint32_t m_delay;
        bool     m_bEnabled;
    };
    
    1 Reply Last reply
    0
    • L Offline
      L Offline
      lrtsenar
      wrote on last edited by
      #2

      What the f...... hell ! I have found the problem :-). It comes from the 'static' keyword while declaring the Device derivated object in Devices.h !
      I'm happy but I don't know why this new compiler forbids this...

      See you for next adventures ;-)

      1 Reply Last reply
      1

      Hello! It looks like you're interested in this conversation, but you don't have an account yet.

      Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

      With your input, this post could be even better 💗

      Register Login
      Reply
      • Reply as topic
      Log in to reply
      • Oldest to Newest
      • Newest to Oldest
      • Most Votes


      24

      Online

      12.0k

      Users

      11.2k

      Topics

      113.4k

      Posts


      Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
      • Login

      • Don't have an account? Register

      • Login or register to search.
      • First post
        Last post
      0
      • MySensors
      • OpenHardware.io
      • Categories
      • Recent
      • Tags
      • Popular