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
lrtsenarL

lrtsenar

@lrtsenar
About
Posts
18
Topics
7
Shares
0
Groups
0
Followers
0
Following
0

Posts

Recent Best Controversial

  • Serial Gateway connect problem ttyAMA0
    lrtsenarL lrtsenar

    @kimot
    After folowing your link, dmesg displays :

    0_1486335983940_upload-d22dbac5-5ecd-4d50-9b44-ee70b7d64dd1

    And :
    0_1486336890405_upload-4226c005-294c-4c8d-9de7-27e26a6467bb

    Now, sems console uses only tty1 but problem persists :-(

    Domoticz

  • Serial Gateway connect problem ttyAMA0
    lrtsenarL lrtsenar

    This :
    0_1486332218660_upload-dc9673dc-b693-48f4-871c-5fbca09aa933

    But I'm not using USB to serial converter, I'm only using native serial GPIO Tx/Rx pins like I said in my 1st post.

    Domoticz

  • Serial Gateway connect problem ttyAMA0
    lrtsenarL lrtsenar

    Hi all,

    Using Mysensors 2.11, latest version of Domoticz (3.58.77), Arduino pro mini 5V directly connected to RPI2 through Tx/Rx connection (having carefully made a voltage divider for 3.3 V Rx on RPI2), have compiled SerialGateway with following parameters :
    0_1486163187143_upload-a7d023e6-ec73-428a-9a00-0936a051df99

    No connection to Serial Gateway (even after waiting for hours ) :
    0_1486163349709_upload-81bdad53-aa16-4e69-9907-b07e369c64dc

    So I tried to lock the ttyAMA0 in order to see if Domoticz is really tries to connect to ttyAMA0, so have locked ttyAMA0 :
    0_1486163122930_upload-3121397d-a0a6-4c8b-a944-573e869ad493

    And Domoticz is happy with this (as after a restart of Dmz service) !
    0_1486163299460_upload-c5703d3c-8d71-4a9e-9775-39c8b9f6e452
    No error seen...

    I suspect Domoticz doesn't try to connect to ttyAMA0. I already fully disabled the serial boot ability and log on ttyAMA0 in RPI (systemctrl diasble,sudo systemctl stop getty.target, /boot/cmdline.txt does'nt contain any ttyAMA0 reference, disable serial-getty@ttyAMA0.service, ...)
    The same hardware is fully functional with my old SD Card (Rasbian/Mysensors installed 1 year ago) !

    Is anybody knows what's wrong

    Domoticz

  • What are these bad practices ?
    lrtsenarL lrtsenar

    I have found my problem. Please have a look at the link in mine (1st) post ;-)

    Development

  • Compilation problem under Arduino 1.8.1
    lrtsenarL lrtsenar

    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 ;-)

    Troubleshooting

  • What are these bad practices ?
    lrtsenarL lrtsenar

    Hello,

    My previous post is only a review of the MySensors library, not what I do in my code.
    Anyway, thanks for the answer.
    I will continue searching for my compilation problem.
    May I ask you with which environment you compile your sketches (Linux, Arduino IDE, ... ) ?

    Development

  • Combining MySensors examples
    lrtsenarL lrtsenar

    Hello,

    Sorry but I've already done the job here :
    Please have a look at "RelayActuatorLrt.ino" in order to know how to use it, it's simple.

    [https://forum.mysensors.org/topic/2537/device-library](link url)

    Is it possible to integrate it in a future release of MySensors ?

    Development

  • What are these bad practices ?
    lrtsenarL lrtsenar

    Hello,

    I tried to compile the MySensors v2.11 library with a code which was compiling and running perfectly with Mysensors v1.42 and Arduino 1.6.5 IDE.
    I saw in this new library a lot of bad practices like including "cpp" files by the following ways (#include should only include header files) :

    #include "core/MyHwESP8266.cpp"
    

    or including directly relatives path in #include (pathes should be managed by make file) :

    #include "drivers/AVR/DigitalWriteFast/digitalWriteFast.h"
    

    I saw this too (wh'y don't declare directly the relevant type like: "const uint8_t NODE_SENSOR_ID=255" because 'C' casts are from the previous century, no ?)

    #define NODE_SENSOR_ID			((uint8_t)255)
    

    I would like to point out that I am a professional C ++ developer since about 20 years.
    I post this because i've got a LOT of errors trying compiling my code in the new library. I'd already wrote a post to expose my problem but nobody is able to understand what happens and I already spent a lot of hours trying to solve the problem.

    As soon as I add a #include of custom header file, the compiler told me "multiple definition of" :

    [https://forum.mysensors.org/topic/5928/compilation-problem-under-arduino-1-8-1](link url)

    Maybe I'm wrong and sorry for the bad review but I'm so frustrated :-(
    If anyone could help...

    Development

  • Compilation problem under Arduino 1.8.1
    lrtsenarL lrtsenar

    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;
    };
    
    Troubleshooting

  • No dallas temp sensor in domoticz devices !
    lrtsenarL lrtsenar

    Ok, you were right. I was missing something. In my code, I forgot to read relevant dallas device. I was reading getTempCByIndex(id+i) instead of reading getTempCByIndex(i).

    Thanks for your usefull help.

    Domoticz

  • No dallas temp sensor in domoticz devices !
    lrtsenarL lrtsenar

    Hi all,

    I have built several sensors (relay, button) and they work perfectely. I have recently built a new one with a Dallas 18b20 by following the instructions in this website. The problem is this temperature device is seen in Domoticz hardware :
    upload-e71d5191-f181-4a22-844f-d0e70f43f924

    But not in devices list :
    upload-87b6d063-7498-435d-b1f8-7640ba8c703d

    Just in case you want to help me ;-), here is the Domoticz log:

    2016-01-10 23:39:31.002 New sensors allowed for 5 minutes...
    2016-01-10 23:39:44.631 MySensors: Node: 3, Sketch Name: Generic Device
    2016-01-10 23:39:44.632 MySensors: Node: 3, Sketch Version: 1.43
    2016-01-10 23:39:54.173 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:40:00.170 Error: EventSystem: Lua script error (Blockly), Name: Heater room kids_1 => [string "result = 0; weekday = os.date('*t')['wday']; ..."]:1: unexpected symbol near ')'
    2016-01-10 23:40:24.261 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:40:54.350 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:41:00.205 Error: EventSystem: Lua script error (Blockly), Name: Heater room kids_1 => [string "result = 0; weekday = os.date('*t')['wday']; ..."]:1: unexpected symbol near ')'
    2016-01-10 23:41:24.439 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:41:54.528 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:42:00.238 Error: EventSystem: Lua script error (Blockly), Name: Heater room kids_1 => [string "result = 0; weekday = os.date('*t')['wday']; ..."]:1: unexpected symbol near ')'
    2016-01-10 23:42:24.617 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:42:54.705 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:43:00.269 Error: EventSystem: Lua script error (Blockly), Name: Heater room kids_1 => [string "result = 0; weekday = os.date('*t')['wday']; ..."]:1: unexpected symbol near ')'
    2016-01-10 23:43:24.795 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:43:54.884 Hardware Monitor: Fetching data (System sensors)
    2016-01-10 23:44:00.301 Error: EventSystem: Lua script error (Blockly), Name: Heater room kids_1 => [string "result = 0; weekday = os.date('*t')['wday']; ..."]

    Do you know why my dallas temperature sensor is not seen as a physiscal "device" in Domoticz ?
    Thanks

    Domoticz

  • Sketch Generator
    lrtsenarL lrtsenar

    If you are interested, here is my beginning of work :

    http://forum.mysensors.org/topic/2537/device-library

    Feature Requests

  • Best IDE to use for MySensors projects
    lrtsenarL lrtsenar

    Hi,

    I use Source Insight. Sure it's not free but it's a full featured tools never equaled (like Visual Assist plug in for Visual Studio).

    Development atmel studio eclipse debug visualmicro ide

  • Device library
    lrtsenarL lrtsenar

    Hi all,

    In order to create devices (relay, button, dallas temperature, and more in the future) in a simple way, I have developped objects. My library compiles fine but I have not yet tested it because i'm waiting from China my Ardino pro mini order :-(

    I have added a preprocessor definition called "MAP" in order to use or not the standard STL C++ library. It grows the code around 5% but you can decide to not use it (which is the default choice).
    Let me share my work and tell me what do you think about it.

    Device.h

    #pragma once
    
    //#define MAP
    #ifdef MAP
    #include <StandardCplusplus.h>
    #include <map>
    #endif
    // CButton
    #include <MyMessage.h>
    #include <Bounce2.h>
    // Dallas temperature
    #include <DallasTemperature.h>
    #include <OneWire.h>
    #include "ElapsedTime.h"
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #define RELAY_ON 0      // GPIO value to write to turn on attached relay
    #define RELAY_OFF 1     // GPIO value to write to turn off attached relay
    
    MySensor* g_pGW;
    #define TheSensor g_pGW
    
    class CDevice;
    #ifdef MAP
    typedef std::map<uint8_t/* id */, CDevice*> MapOfDevice;
    MapOfDevice g_deviceMap;
    #else
    #define DECLARE_NBOFDEVICE(nb) CDevice* g_deviceMap[nb];
    extern CDevice* g_deviceMap[];
    #endif
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    class CDevice
    {
    public:
        CDevice(uint8_t id, uint8_t pin, int state=0)
            : m_id(id)
            , m_pin(pin)
            , m_state(state)
        {
            g_deviceMap[m_id] = this;
    #ifdef DEBUG
            Serial.print("CDevice() id="); Serial.print(m_id);
    #endif
        }
        virtual bool getState() { return m_state; }                 // generic behavior
        virtual void setState(bool bState) { m_state = bState; }    // generic behavior
        virtual void checkChange() {};                              // used in some devices
    
    protected:
        uint8_t     m_id;
        uint8_t     m_pin;
        int         m_state;
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    class CRelay : public CDevice
    {
    public:
        CRelay(uint8_t id, uint8_t pin, bool bActiveAtStart, bool bPersistent)
            : CDevice(id, pin, RELAY_OFF)
            , m_bPersistent(bPersistent)
        {
            g_pGW->present(m_id, S_LIGHT);
            digitalWrite(m_pin, bActiveAtStart ? RELAY_ON : RELAY_OFF);  // force value to be written before setting pin mode
            pinMode(m_pin, OUTPUT);
            if (m_bPersistent)
            {
                m_state = g_pGW->loadState(m_id);   // last known state from previous run
                digitalWrite(m_pin, m_state);
            }
        }
    
        void setState(bool bOn)
        {
            m_state = bOn ? RELAY_ON : RELAY_OFF;
            digitalWrite(m_pin, m_state);
            if (m_bPersistent)
            {
                g_pGW->saveState(m_id, m_state);
            }
    #ifdef DEBUG
            Serial.print("CRelay::set id="); Serial.print(m_id);
            Serial.print(", new status=");   Serial.println(m_state);
    #endif
        }
    
        bool getState() { return m_state ? RELAY_ON : RELAY_OFF; }
    
    protected:
        bool        m_bPersistent;
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    class CButton : public CDevice, public MyMessage, public Bounce
    {
    public:
        CButton(uint8_t id, uint8_t pin, uint8_t linkedId/*relayId*/)
            : CDevice(id, pin)
            , MyMessage(linkedId, V_LIGHT)
            , m_linkedId(linkedId)
        {
            pinMode(m_pin, INPUT);
            digitalWrite(m_pin, HIGH);  // internal pull-up
            attach(m_pin);              // Bounce class
            interval(5);                // Bounce class
        };
    
        // should be called periodically in order to check if button is pressed
        virtual void checkChange()
        {
            update();                   // Bounce class
            int iVal = read();          // Bounce class
            if (iVal != m_state)
            {
                g_pGW->send(set(g_deviceMap[m_linkedId]->getState() ? false : true), true);    // change value
                m_state = iVal;
            }
        }
    
    protected:
        uint8_t m_linkedId; // Id with which device (button) is associated
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    class CDallasT : public CDevice, public MyMessage
    {
    public:
        // period : minimum allowed time between two request of temperature
        CDallasT(uint8_t id, uint8_t pin, uint32_t period)
            : CDevice(id, pin)
            , MyMessage(id, V_TEMP)
            , m_oneWire(pin)
            , m_dallasT(NULL)
            , m_etRequest(period)
            , m_etRetrieve(0, false, false) // don't care 2nd param, object started disabled
        {
            m_dallasT.setOneWire(&m_oneWire);
            m_dallasT.setWaitForConversion(false);  // requestTemperatures() will not block current thread
            g_pGW->present(m_id, S_TEMP);
    
            int16_t conversionTime = m_dallasT.millisToWaitForConversion(m_dallasT.getResolution());
            m_etRetrieve.setDelay(conversionTime);
        }
    
        // shoud be called periodically in order to check if temperature has to be measured
        virtual void checkChange()
        {
            if (m_etRequest.isElapsed())
            {
                m_dallasT.requestTemperatures();    // request temperature from Dallas sensor
                m_etRetrieve.start();               // 'wait' for end of temperature sampling
                m_etRequest.start();                // 'wait' for next request
            }
    
            if (m_etRetrieve.isElapsed())             // wait for end of conversion
            {
                // fetch and round temperature to one decimal
                float tp = g_pGW->getConfig().isMetric
                         ? m_dallasT.getTempCByIndex(m_id) : m_dallasT.getTempFByIndex(m_id);
                tp = static_cast<float>(static_cast<int>(tp * 10.)) / 10.;
    
                if ((tp != m_fTempPrev) && (tp != -127.00) && (tp != 85.00))
                {
                    g_pGW->send(setSensor(m_id).set(tp, 1));
                    m_fTempPrev = tp;                     // Save new temperature for next compare
                }
                m_etRetrieve.disable(); // once temperature is retrieved, wait for next request to retrieve again
            }
        }
    
    protected:
        OneWire             m_oneWire;
        DallasTemperature   m_dallasT;
        float               m_fTempPrev;
        CElapsedTime        m_etRequest;
        CElapsedTime        m_etRetrieve;
    };
    
    

    ElapsedTime.h

    #pragma once
    
    // used to check if set time is elapsed
    // limitation : 'isElased' method MUST be called at least 1 time every 49.71 days in order to work properly ;-)
    class CElapsedTime
    {
    public:
        // bWait1stTime means ignore timems value the very 1st call to 'isElapsed'
        CElapsedTime(uint32_t timems=0, bool bWait1stTime=false, bool bEnabled=true)
            : m_delay(timems)
            , m_bEnabled(bEnabled)
        {
            start(bWait1stTime ? timems : 0);
        };
        ~CElapsedTime() {};
    
        // start to count requested 'wait' time
        void start(uint32_t timems=0)
        {
            m_tNow = millis();
            m_tEnd = m_tNow + (timems == 0) ? m_delay : timems;
            m_bWrapped = (m_tEnd < m_tNow);
            m_bEnabled = true;
        }
    
        void disable() { m_bEnabled = false; }
    
        void setDelay(uint32_t delay) { m_delay = delay; }
    
        // check if requested time is elapsed since previous call of 'start' method
        bool isElapsed()
        {
            m_tNow = millis();
            if (m_bWrapped && (m_tNow < 0x7FFFFFFF))
            {
                m_bWrapped = false;
            }
            return m_bEnabled && !m_bWrapped && (m_tNow > m_tEnd);
        }
    
    protected:
        uint32_t m_tNow;    // current 'time'
        uint32_t m_tEnd;    // computed end of 'time'
        uint32_t m_delay;   // used to memorize value provided in constructor
        bool m_bWrapped;    // overflow management (every around 0xFFFFFFFF/1000/3600/24 = 49.71 days)
        bool m_bEnabled;    // used to know if Elpser is enabled
    };
    
    

    RelayActuatorLrt.ino

    // History Lrt
    // 2015-12-03 v1.0 code understanding, set output pin to off at start
    // 2015-12-04 v1.1 button added
    #define WBUTTON
    // 2015-12-04 v1.2 dallas temp added
    #define WDALLASTEMP
    // 2015-12-07 v1.3 relay and button class
    // 2015-12-08 v1.4 dallas temperature device
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #include <MySigningNone.h>
    #include <MyTransportNRF24.h>
    #include <MyTransportRFM69.h>
    #include <MyHwATMega328.h>
    #include <MySensor.h>
    #include <SPI.h>
    #include "Devices.h"
    
    // NRFRF24L01 radio driver (set low transmit power by default)
    MyTransportNRF24 radio(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
    //MyTransportRFM69 radio;
    // Message signing driver (none default)
    //MySigningNone signer;
    // Select AtMega328 hardware profile
    MyHwATMega328 hw;
    // Construct MySensors library
    MySensor gw(radio, hw);
    
    #ifndef MAP
    const int NBOFDEVICE=3;
    DECLARE_NBOFDEVICE(NBOFDEVICE+1);   // index 0 is not used
    #endif
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    void setup()
    {
      gw.begin(incomingMessage, AUTO/*, true*/);    // Initialize library and add callback for incoming messages
    
      gw.sendSketchInfo("Lrt Device R+B+T", "1.4"); // Send the sketch version information to the gateway and Controller
    
      TheSensor = &gw; // gives MySensor library to Device library
    
      CRelay(1, 3, false, true); // relay where id=1, pin=3, off at start, pesistent
    
    #ifdef WBUTTON
      CButton(2, 4, 1);          // button where id=2, pin=4 and associated relayid=1
    #endif
    
    #ifdef WDALLASTEMP
      CDallasT(3, 5, 60000);     // Dallas temp where id=3, pin=5 and period temperature retrieve is 1 min.
    //  CDallasT(4, 6, 60000);     // internal module temperature
    #endif
    }
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    void loop()
    {
      gw.process();     // Alway process incoming messages whenever possible
    
    #if defined WBUTTON || defined WDALLASTEMP
      // parse all devices in order to know if change occurs
    #ifdef MAP
      MapOfDevice::iterator it = g_deviceMap.begin();
      for(; it != g_deviceMap.end(); ++it)
      {
        it->second->checkChange();
      }
    #else
      for(int i=1; i<=NBOFDEVICE; i++)
      {
        g_deviceMap[i]->checkChange();
      }
    #endif
    #endif
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    void incomingMessage(const MyMessage &message) {
    #ifdef DEBUG
      if (message.isAck())
      {
        Serial.print("This is an ack from GW");
      }
    #endif
      if (message.type == V_LIGHT)  // relay request from GW
      {
        g_deviceMap[message.sensor]->setState(message.getBool());
      }
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    
    Development

  • Safe In-Wall AC to DC Transformers??
    lrtsenarL lrtsenar

    What do you think about this ? 1.79$ 5V @ 700mA dim: 3cm x 2cm x 1.8cm :
    http://www.ebay.fr/itm/321846469504?_trksid=p2060353.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT

    Hardware

  • Arduino "Pro Mini" instead of "Nano" as SerialGateway w/ Domoticz on Rasspberry PI
    lrtsenarL lrtsenar

    Hello All,

    On Domoticz (and so on RaspberryPI), I have disable the serial port to log any data and disable it to prevent incoming login connexion (I use SSH instead). Next, I upload "SerialGateway.ino" project into my Arduino Pro Mini. I use a 1/3 2/3 resistor bridge between ProMini Tx and RPI Rx line to go from 5V to 3.3V, and so, serial com is works between ProMini and RPI. I added in Domoticz a MySensors GW which opens ttyAMA0 com port.

    1. Why adding a serial to USB adaptor in RPI and use a Nano to make a Serial Gateway while a Pro Mini is enough and cheaper (Nano vs ProMini and due to not needed USB->TTL adapter) ?

    2. When I start my RPI with the Gateway connected, no version of gateway is seen in list of hardware (a "?" still present). The Domoticz log only tell me that MySensor GW is connected to ttyAMA0. Do you know why version of Mysensors library version is not displayed and how to know if my GW is working ?

    Thanks

    Edit1: Concerning point 2), finally after powered on a Node, all appears in Domoticz, version and Node childs ! Cool ! However, as mentionned in point 1), "Nano" is useless for Gateway and "Pro Mini" could perfectly be used ! Anyway, thanks very much to this FANTASTIC website ;-)

    General Discussion

  • Arduino Pro mini + RF 433 MHz as Gateway
    lrtsenarL lrtsenar

    Hi All,

    I wish to use Arduino Pro mini + 433 MHz Emitter + Receiver as a Gateway to communicate with Domoticz. The Nodes I wish to use are Arduino Pro mini + 433 Emit+Recv, the same as Gateway but with different software of course.
    I read on MySensors website that Gateway should be Arduino Nano + 2.4 GHz radio module but I would like to know if I can easily do it with Pro mini + 433 MHz radio.
    Can anyone told me if it's possible and help me to do it ?
    Many thanks in advance.

    General Discussion arduino 433 pro mini mhz
  • Login

  • Don't have an account? Register

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