Combining DS18B20 and relay..



  • Hi there,

    I am new to the world of domotica, but so far everything works fine....UNTIL..I tried to combine sensors to make me use as less nano's as possible.

    I tries to combine DS18B20 (2 pieces) and a relay, I searched on this forum, I did find some information wich helped me further in this project. The situation is now:

    1. Domoticz sees every child, so I see 1 relay an two DS18B20.
    2. but he puts the temperature value in the relay child.
    3. When I look in the device I see 2 temperature sensors and one relay, all three work fine

    the only thing is, that he present the values in the wrong child, see printscreen:

    https://drive.google.com/file/d/1p8q0QlZt-uMx12mS0Vxm8XHJBV40KrIK/view?usp=sharing

    this is the the code:

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik Ekblad
     *
     * DESCRIPTION
     * Example sketch showing how to control physical relays.
     * This example will remember relay state after power failure.
     * http://www.mysensors.org/build/relay
     */
    
    #define MY_NODE_ID 12
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
    #define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected 
    #define MAX_ATTACHED_DS18B20 16
    
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
    float lastTemperature[MAX_ATTACHED_DS18B20];
    int numSensors=0;
    bool receivedConfig = false;
    bool metric = true;
    // Initialize temperature message
    MyMessage msg(0,V_TEMP);
    
    #define RELAY_PIN 6  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 1 // Total number of attached relays
    #define RELAY_ON 1  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
    
    void before()
    {
      for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
        // Set relay to last known state (using eeprom storage)
        digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
      }
    
      // Startup up the OneWire library
      sensors.begin();
      
    }
    
    void setup()
    {
    // requestTemperatures() will not block current thread
      sensors.setWaitForConversion(false);
    }
    
    void presentation()
    {
       // Send the sketch version information to the gateway and Controller
      sendSketchInfo("VloerverwarmingAansturing", "1.6");
    
      // Fetch the number of attached temperature sensors  
      numSensors = sensors.getDeviceCount();
    
      // Present all sensors to controller
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i+5, S_TEMP);
      }
    
      for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_BINARY);
      }
    
    
    
    }
    
    
    void loop()
    {
       // Fetch temperatures from Dallas sensors
      sensors.requestTemperatures();
    
      // query conversion time and sleep until conversion completed
      int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
      // sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
      sleep(conversionTime);
    
      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
     
        // Fetch and round temperature to one decimal
        float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
     
        // Only send data if temperature has changed and no error
        #if COMPARE_TEMP == 1
        if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
        #else
        if (temperature != -127.00 && temperature != 85.00) {
        #endif
     
          // Send in the new temperature
          send(msg.setSensor(i).set(temperature,1));
          // Save new temperatures for next compare
          lastTemperature[i]=temperature;
        }
      }
      //sleep(SLEEP_TIME);
    
    }
    
    void receive(const MyMessage &message)
    {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_STATUS) {
        // Change relay state
        digitalWrite(message.sensor-1+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
        // Store state in eeprom
        saveState(message.sensor, message.getBool());
        // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.print(message.sensor);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
    }
    

    It is clear that I am doing something wrong, but I don't see it at this moment with the knowledge that I have (0,0) about debugging sketches. The hardware is ok, I tested everything seprately and works fine.


  • Mod

    @mela you probably want to set numSensors to 2?



  • @mela You are presenting the devices as Relay Child 1, and Temperature sensors as Child Ids 5 and 6.

    But when sending you are sending the temperatures as Child Ids 0 and 1

    Change the following send line

          // Send in the new temperature
          send(msg.setSensor(i).set(temperature,1));
    

    to

          // Send in the new temperature
          send(msg.setSensor(i+5).set(temperature,1));
    

    so the send function matches the presentation values.



  • @mfalkvidd said in Combining DS18B20 and relay..:

    @mela you probably want to set numSensors to 2?

    The sketches wich I have combined works with those values seprately without errors, thats why I didn't chage it, so maybe you have a point to set this value to 2 because I don't use more than 2 temp. sensors, thanks for your thinking.



  • @hard-shovel said in Combining DS18B20 and relay..:

    @mela You are presenting the devices as Relay Child 1, and Temperature sensors as Child Ids 5 and 6.

    But when sending you are sending the temperatures as Child Ids 0 and 1

    Change the following send line

          // Send in the new temperature
          send(msg.setSensor(i).set(temperature,1));
    

    to

          // Send in the new temperature
          send(msg.setSensor(i+5).set(temperature,1));
    

    so the send function matches the presentation values.

    🙂 I think this is the problem, I will change it a soon as possible and wil give an update here. Thank you 🙂



  • @hard-shovel problem solved thanks to you, great man....

    Now every child gives the correct value:

    https://drive.google.com/file/d/1juxdKk4ljZBUxzQWDp-3hGJC4PHqm1WQ/view?usp=sharing

    for people who need the working sketch:

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik Ekblad
     *
     * DESCRIPTION
     * Example sketch showing how to control physical relays.
     * This example will remember relay state after power failure.
     * http://www.mysensors.org/build/relay
     */
    
    #define MY_NODE_ID 12
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
    #define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected 
    #define MAX_ATTACHED_DS18B20 16
    
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
    float lastTemperature[MAX_ATTACHED_DS18B20];
    int numSensors=0;
    bool receivedConfig = false;
    bool metric = true;
    // Initialize temperature message
    MyMessage msg(0,V_TEMP);
    
    #define RELAY_PIN 6  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 1 // Total number of attached relays
    #define RELAY_ON 1  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
    
    void before()
    {
      for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);
        // Set relay to last known state (using eeprom storage)
        digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
      }
    
      // Startup up the OneWire library
      sensors.begin();
      
    }
    
    void setup()
    {
    // requestTemperatures() will not block current thread
      sensors.setWaitForConversion(false);
    }
    
    void presentation()
    {
       // Send the sketch version information to the gateway and Controller
      sendSketchInfo("VloerverwarmingAansturing", "1.7");
    
      // Fetch the number of attached temperature sensors  
      numSensors = sensors.getDeviceCount();
    
      // Present all sensors to controller
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i+5, S_TEMP);
      }
    
      for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_BINARY);
      }
    
    
    
    }
    
    
    void loop()
    {
       // Fetch temperatures from Dallas sensors
      sensors.requestTemperatures();
    
      // query conversion time and sleep until conversion completed
      int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
      // sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
      sleep(conversionTime);
    
      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
     
        // Fetch and round temperature to one decimal
        float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
     
        // Only send data if temperature has changed and no error
        #if COMPARE_TEMP == 1
        if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
        #else
        if (temperature != -127.00 && temperature != 85.00) {
        #endif
     
          // Send in the new temperature
          send(msg.setSensor(i+5).set(temperature,1));
          // Save new temperatures for next compare
          lastTemperature[i]=temperature;
        }
      }
      
    
    }
    
    void receive(const MyMessage &message)
    {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_STATUS) {
        // Change relay state
        digitalWrite(message.sensor-1+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
        // Store state in eeprom
        saveState(message.sensor, message.getBool());
        // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.print(message.sensor);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
      }
      sleep(SLEEP_TIME);
    }
    


  • Hi, not long ago I did the same.

    Looking at your code I notice you got 16 DS18B20's. When using so many it is probably better to also fix the ID's otherwise when a DS18B20 is not responding the order of the sensors is shifted. See for code to get the ID's: https://forum.mysensors.org/topic/4143/about-ds18b20-onewire

    I also changed the pin assignment for the relay's a tiny bit.

    My sketch:

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    const int PINS[] = {4, 5, 6, 7, 8, 14, 15}; // I/O pins 4, 5, 6, 7, 8, A0, A1 for the relays 
    #define NUMBER_OF_RELAYS 7 // Total number of attached relays
    #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
    
    #define COMPARE_TEMP 0 // Send temperature only if changed? 1 = Yes 0 = No
    
    #define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected 
    #define MAX_ATTACHED_DS18B20 5
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    // Generally, you should use "unsigned long" for variables that hold time
    // The value will quickly become too large for an int to store
    unsigned long previousMillis = 0;        // will store last time LED was updated
    
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
    
    byte D[5][8] = {
    { 0x28, 0xF2, 0xAB, 0x0F, 0x07, 0x00, 0x00, 0xA1 },
    { 0x28, 0x23, 0x29, 0xDB, 0x05, 0x00, 0x00, 0x5A },
    { 0x28, 0xAB, 0x2A, 0xDB, 0x05, 0x00, 0x00, 0x5F },
    { 0x28, 0x49, 0xAF, 0x0F, 0x07, 0x00, 0x00, 0x41 },
    { 0x28, 0x1D, 0x2F, 0x10, 0x07, 0x00, 0x00, 0xDA }
    };
    
    float lastTemperature[MAX_ATTACHED_DS18B20];
    int numSensors=0;
    bool receivedConfig = false;
    bool metric = true;
    // Initialize temperature message
    MyMessage msg(0,V_TEMP);
    
    void before()
    {
        for (int sensor=1; sensor<=NUMBER_OF_RELAYS; sensor++) {
            // Then set relay pins in output mode
            pinMode(PINS[sensor-1], OUTPUT);
            // Set relay to last known state (using eeprom storage)
            digitalWrite(PINS[sensor-1], loadState(sensor)?RELAY_ON:RELAY_OFF);     
        }
        
        // Startup up the OneWire library
        sensors.begin();
    }
    
    void setup()  
    { 
      // requestTemperatures() will not block current thread
      sensors.setWaitForConversion(false);
    }
    
    void presentation()
    {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("Relay and Temp", "1.0");
    
        for (int sensor=1; sensor<=NUMBER_OF_RELAYS+MAX_ATTACHED_DS18B20; sensor++) {
            // Register all sensors to gw (they will be created as child devices)
    
            if (sensor<=NUMBER_OF_RELAYS){  
              present(sensor, S_BINARY);       
            }
            else {
              present(sensor, S_TEMP);          
            }
        }
    }
    
    void loop()     
    {     
      unsigned long currentMillis = millis();
    
      if (currentMillis - previousMillis >= SLEEP_TIME) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;
    
        // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();
      
        // query conversion time and sleep until conversion completed
        int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
        // sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
        sleep(conversionTime);
      
        // Read temperatures and send them to controller 
        for (int i=0; i<MAX_ATTACHED_DS18B20; i++) {
      
          // Fetch and round temperature to one decimal
          // float temperature = static_cast<float>(static_cast<int>((getConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
          float temperature = sensors.getTempC(D[i]);
          
          // Only send data if temperature has changed and no error
          if (COMPARE_TEMP == 1) {
            if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
                // Send in the new temperature
                send(msg.setSensor(i+NUMBER_OF_RELAYS+1).set(temperature,1));
                // Save new temperatures for next compare
                lastTemperature[i]=temperature;
            }
          }
          else {
            if (temperature != -127.00 && temperature != 85.00) {
                // Send in the new temperature
                send(msg.setSensor(i+NUMBER_OF_RELAYS+1).set(temperature,1));
                // Save new temperatures for next compare
                lastTemperature[i]=temperature;
            }
          }
        }
      }
    }
    
    void receive(const MyMessage &message)
    {
        // We only expect one type of message from controller. But we better check anyway.
        if (message.type==V_STATUS) {
            // Change relay state
            digitalWrite(PINS[message.sensor-1], message.getBool()?RELAY_ON:RELAY_OFF);
            // Store state in eeprom
            saveState(message.sensor, message.getBool());
            // Write some debug info
            Serial.print("Incoming change for sensor:");
            Serial.print(message.sensor);
            Serial.print(", New status: ");
            Serial.println(message.getBool());
        }
    }
    


  • @woeka Yeah you are right, i should change the code to 2 DS18B20's with eachone its own ID, thanks for the advise, also thanks for sharing your sketch.


Log in to reply
 

Suggested Topics

  • 3
  • 3
  • 2
  • 4
  • 1
  • 2

0
Online

11.2k
Users

11.1k
Topics

112.5k
Posts