2 dallas temp + 4 relays



  • Has anyone had any progress on sensor node with mysensors + multiple dallas temp sensors and multiple relays combining the codes? Any help would be greatly appreciated. I have been playing with this for a little more than a week off and on. a push in the right direction would be great!
    Thanks

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    //#define MY_RF24_CE_PIN 49
    //#define MY_RF24_CS_PIN 53
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    #define MY_NODE_ID 6
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    // Wait times
    #define LONG_WAIT 500
    #define SHORT_WAIT 50
    
    #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_1  4  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 4 // 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
    
    
    
    void before()
    {
      for (int sensor=1, pin=RELAY_1; 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("Fireplace interface", "1.1");
      //wait(LONG_WAIT);
    
      // 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,"Fireplace Temp");
      //wait(SHORT_WAIT);
      }  
      for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
       // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_BINARY);
      //wait(SHORT_WAIT);
      }
    }
    
    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)
      wait(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_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());
      }
       wait(SLEEP_TIME);
    }```
    
    And here is my serial print
    
     
     __  __       ____
    |  \/  |_   _/ ___|  ___ _ __  ___  ___  _ __ ___
    | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
    | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
    |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
            |___/                      2.3.1
    
    16 MCO:BGN:INIT NODE,CP=RNNNA---,REL=255,VER=2.3.1
    26 MCO:BGN:BFR
    28 TSM:INIT
    29 TSF:WUR:MS=0
    36 TSM:INIT:TSP OK
    37 TSM:INIT:STATID=6
    44 TSF:SID:OK,ID=6
    45 TSM:FPAR
    81 TSF:MSG:SEND,6-6-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    780 TSF:MSG:READ,0-0-6,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    785 TSF:MSG:FPAR OK,ID=0,D=1
    2089 TSM:FPAR:OK
    2091 TSM:ID
    2092 TSM:ID:OK
    2094 TSM:UPL
    2097 TSF:MSG:SEND,6-6-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=OK:1
    2104 TSF:MSG:READ,0-0-6,s=255,c=3,t=25,pt=1,l=1,sg=0:1
    2109 TSF:MSG:PONG RECV,HP=1
    2111 TSM:UPL:OK
    2113 TSM:READY:ID=6,PAR=0,DIS=1
    2117 TSF:MSG:SEND,6-6-0-0,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    2125 TSF:MSG:READ,0-0-6,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    2132 TSF:MSG:SEND,6-6-0-0,s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=OK:2.3.1
    2142 TSF:MSG:SEND,6-6-0-0,s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=OK:0
    2158 TSF:MSG:READ,0-0-6,s=255,c=3,t=6,pt=0,l=1,sg=0:M
    2165 TSF:MSG:SEND,6-6-0-0,s=255,c=3,t=11,pt=0,l=19,sg=0,ft=0,st=OK:Fireplace interface
    2176 TSF:MSG:SEND,6-6-0-0,s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=OK:1.1
    2183 TSF:MSG:SEND,6-6-0-0,s=1,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2191 TSF:MSG:SEND,6-6-0-0,s=2,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2198 TSF:MSG:SEND,6-6-0-0,s=3,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2206 TSF:MSG:SEND,6-6-0-0,s=4,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2211 MCO:REG:REQ
    2215 TSF:MSG:SEND,6-6-0-0,s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=OK:2
    2222 TSF:MSG:READ,0-0-6,s=255,c=3,t=27,pt=1,l=1,sg=0:1
    2227 MCO:PIM:NODE REG=1
    2229 MCO:BGN:STP
    2231 MCO:BGN:INIT OK,TSP=1
    
    Re: [Combining relay and temperature sketch](/topic/6782/combining-relay-and-temperature-sketch)


  • @mghaff i had also that problem, i have 4 relay's and 9 dallas sensors.

    if you want to look at it, i made a post of it at https://forum.mysensors.org/topic/9915/plant-watering-node

    prehaps it can help you.



  • @mghaff: please avoid double postings. It would have been nice if you'd at least have made a link to this post in the other one you did on that topic here: https://forum.mysensors.org/post/95894.

    @both:
    Imo you should implement a "non-blocking" code, nut just add a sleep or wait at the end of loop or just delete that. Otherwise most likely either your DS18B20 will not deliver any meaningfull measurements or you will not be able to controll your relays...
    Please have a look at https://github.com/mysensors/MySensors/blob/master/examples/EnergyMeterPulseSensor/EnergyMeterPulseSensor.ino as a base example how to implement non-blocking code (path: sleepmode false) or have a look in the sketch I linked to in the answer to the other posting: https://forum.mysensors.org/post/95901



  • @mghaff my sketch is working good, dallas and moisture readings are good, and i can control my relays.



  • @dzjr Didn't test that to be honest, but nevertheless, imho it is not a state of the art code design to use wait() nor is it best practice to use much hard-coded steps to do the same thing over and over. Rather use millis() for non-blocking coding and for-loops over comparable stuff, write to and read results from arrays. This keeps coding much easier to read and understand once you got the idea how it works.
    But what in the end counts: It works...



  • @dzjr I tried to use your sketch to get mine to work and it does not. I might just rebuild it all with new everything and try it again.



  • Would this be my blocking loop?

    void presentation() {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Fireplace interface", "1.1");
      //wait(LONG_WAIT);
    
      // 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,"Fireplace Temp");
      //wait(SHORT_WAIT);
      }  
      for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
       // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_BINARY);
      //wait(SHORT_WAIT);
      }
    }
    


  • @mghaff Looks quite ok in the presentation() function.
    You do not need the "pin" variable in presentation, so you might shorten that to:

    for (int sensor=1; sensor<=NUMBER_OF_RELAYS; sensor++) {
       // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_BINARY);
     }
    

    The "pin++" is needed in case you want to switch also the relays to a specific state. If you also want a completely flexible pin-assignment see sketch in https://forum.mysensors.org/topic/4847/multi-button-relay-sketch/33# as a very good example. There also the corresponding PIN is read from an predefined array (has some quite interesting button features also).



  • I tried to combine a couple other sketches and the closest I got was this one. But it still does not give me values for my Dallas temp. if I try each sketch separate they work fine and present fine with readings. I am a newbie and have luck, yes i call it luck cause my other sensors work just fine.

    My debug is


    | / |_ / | ___ _ __ ___ ___ _ __ ___
    | |/| | | | _
    \ / _ \ _ \/ __|/ _ \|
    _/ __|
    | | | | |
    | || | / | | _ \ _ | | _
    |
    | |
    |_
    , |/ ___|| ||/_/|| |/
    |
    __/ 2.3.1

    16 MCO:BGN:INIT NODE,CP=RNNNA---,REL=255,VER=2.3.1
    26 MCO:BGN:BFR
    120 TSM:INIT
    121 TSF:WUR:MS=0
    129 TSM:INIT:TSP OK
    130 TSM:INIT:STATID=8
    136 TSF:SID:OK,ID=8
    138 TSM:FPAR
    174 TSF:MSG:SEND,8-8-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    448 TSF:MSG:READ,0-0-8,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    452 TSF:MSG:FPAR OK,ID=0,D=1
    2181 TSM:FPAR:OK
    2182 TSM:ID
    2183 TSM:ID:OK
    2185 TSM:UPL
    2188 TSF:MSG:SEND,8-8-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=OK:1
    2195 TSF:MSG:READ,0-0-8,s=255,c=3,t=25,pt=1,l=1,sg=0:1
    2200 TSF:MSG:PONG RECV,HP=1
    2203 TSM:UPL:OK
    2204 TSM:READY:ID=8,PAR=0,DIS=1
    2209 TSF:MSG:SEND,8-8-0-0,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    2217 TSF:MSG:READ,0-0-8,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    2225 TSF:MSG:SEND,8-8-0-0,s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=OK:2.3.1
    2233 TSF:MSG:SEND,8-8-0-0,s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=OK:0
    2250 TSF:MSG:READ,0-0-8,s=255,c=3,t=6,pt=0,l=1,sg=0:M
    2257 TSF:MSG:SEND,8-8-0-0,s=255,c=3,t=11,pt=0,l=18,sg=0,ft=0,st=OK:Temperature Sensor
    2268 TSF:MSG:SEND,8-8-0-0,s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=OK:1.2
    2276 TSF:MSG:SEND,8-8-0-0,s=1,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2283 TSF:MSG:SEND,8-8-0-0,s=21,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    2290 TSF:MSG:SEND,8-8-0-0,s=2,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2298 TSF:MSG:SEND,8-8-0-0,s=21,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    2306 TSF:MSG:SEND,8-8-0-0,s=3,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2314 TSF:MSG:SEND,8-8-0-0,s=21,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    2321 TSF:MSG:SEND,8-8-0-0,s=1,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2328 TSF:MSG:SEND,8-8-0-0,s=22,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    2336 TSF:MSG:SEND,8-8-0-0,s=2,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2343 TSF:MSG:SEND,8-8-0-0,s=22,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    2352 TSF:MSG:SEND,8-8-0-0,s=3,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=OK:
    2359 TSF:MSG:SEND,8-8-0-0,s=22,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    2365 MCO:REG:REQ
    2368 TSF:MSG:SEND,8-8-0-0,s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=OK:2
    2374 TSF:MSG:READ,0-0-8,s=255,c=3,t=27,pt=1,l=1,sg=0:1
    2379 MCO:PIM:NODE REG=1
    2382 MCO:BGN:STP
    Hello world, I am a sensor.
    2383 MCO:BGN:INIT OK,TSP=1
    Starting new measurement(s)
    Sensor #0 says it is -127.00 degrees
    Sensor #1 says it is -127.00 degrees
    zzzzZZZZzzzzZZZZzzzz

    /**
       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.
    
     *******************************
    
       DESCRIPTION
    
       Example sketch showing how to send in DS1820B OneWire temperature readings back to the controller
       http://www.mysensors.org/build/temp
    
       The cool thing about this temperature sensor (pun intended) is thay you can attach multiple Dallas temperature sensors outputs to the same arduino pin. They will all automatically be recognised as separate sensors.
    
       At the moment of writing (februari 2017) you need older versions of the Dallas and OneWire libraries. Please check the website or forum to see if this is still the case.
    
       Modifications by anonymous user so that it can now simultaneously function as a MySensors repeater.
    */
    
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24                            // A 2.4Ghz transmitter and receiver, often used with MySensors.
    //#define MY_RF24_PA_LEVEL RF24_PA_MIN              // This sets a low-power mode for the radio. Useful if you use the verison with the bigger antenna, but don' want to power that from a separate source. It can also fix problems with fake Chinese versions of the radio.
    //#define MY_RADIO_RFM69                          // 433Mhz transmitter and reveiver.
    #define MY_NODE_ID 8
    // Choose if you want this sensor to also be a repeater.
    // #define MY_REPEATER_FEATURE                    // Just remove the two slashes at the beginning of this line to also enable this sensor to act as a repeater for other sensors. If this node is on battery power, you probably shouldn't enable this.
    // Are you using this sensor on battery power?
    //#define BATTERY_POWERED                   // Just remove the two slashes at the beginning of this line if your node is battery powered. It will then go into deep sleep as much as possible. But when it' sleeping it can' work as a repeater.
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    
    // These defines and variables can be changed:
    #define COMPARE_TEMP 1                            // Send temperature only if changed? 1 = Yes 0 = No. Can save battery.
    #define ONE_WIRE_BUS 3                            // Pin where Dallas sensor(s) is/are connected.
    #define MAX_ATTACHED_DS18B20 16                   // Maximum amount of teperature sensors you can connect to this arduino (16).
    #define RELAY_PIN 4  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 3 // 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
    
    
    unsigned long measurementInterval = 30000;        // Time to wait between reads (in milliseconds).
    
    // You should not change these:
    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];      // creates an array to hold the previous temperature measurements for each possible sensor.
    int numSensors = 0;                               // variable to contain the number of found attached sensors.
    boolean metric = true;                            // old Mysensors??
    unsigned long measurementSleepTime = 0;           // variable to store the Sleep time if the node is battery powered.
    
    
    // Mysensors settings
    MyMessage msg(0, V_TEMP);                         // Sets up the message format that we'l be sending to the MySensors gateway later.
    
    
    void before()
    {
      sensors.begin();                              // Startup up the OneWire library. It allows multiple sensors to talk over one wire (one pin).
      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);
      }
    }
    void setup()
    {
      for (int i = 0; i < MAX_ATTACHED_DS18B20; i++) {
        lastTemperature[i] = 0;  //Pre-filling array with 0's.
      }
      sensors.setWaitForConversion(false);            // requestTemperatures() will not block current thread
    
    #ifdef BATTERY_POWERED
      measurementSleepTime = measurementInterval;
      measurementInterval = 1;                    // We'll let Sleep take over the scheduling. When the arduino is asleep, millis doesn't increment anymore (time stops as it were). To fix this, we'l set the measurement interval time to 1, so that when the arduino wakes up it will immediately try to measure again.
    #endif
    
      Serial.begin(115200);                           // for serial debugging.
      Serial.print("Hello world, I am a sensor. \n ");
    
    }
    
    void presentation()
    {
      sendSketchInfo("Temperature Sensor", "1.2");    // Send the sketch version information to the gateway and Controller
      numSensors = sensors.getDeviceCount();          // Fetch the number of attached temperature sensors
      for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++)
      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);
        present(i+21, S_TEMP);                          // Present all sensors to controller (16 maximum).
      }
    }
    
    void loop()
    {
    
      // You should not change these variables:
      static boolean isMeasuring = true;                // Used to indicate when the time is right for a new measurement to be made.
      static boolean isCalculating = false;                     // Used to bridge the time that is needed to calculate the temperature values by the Dallas library.
      static unsigned long currentMillis = 0;                   // The millisecond clock in the main loop.
      static unsigned long previousMeasurementMillis = 0;       // Used to remember the time of the last temperature measurement.
      static int16_t conversionTime = 0;                        // Used to store the time needed to calculate the temperature from measurements.
    
      currentMillis = millis(); // The time since the sensor started, counted in milliseconds. This script tries to avoid using the Sleep function, so that it could at the same time be a MySensors repeater.
    
      // Let's measure the temperature
      if (isMeasuring == true && currentMillis - previousMeasurementMillis >= measurementInterval) { // If we're not calculating, and enough time has passed, we'll start again.
        isMeasuring = false; // We're measuring, so let's take it off our to-do list.
        Serial.print("Starting new measurement(s)\n");
        previousMeasurementMillis = currentMillis; // Mark the time of the initialiation of this measurement.
    
        // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();
    
        // query conversion time. Apparently it takes a while to calculate.
        //CONVERSION_TIME = sensors.millisToWaitForConversion(sensors.getResolution());
        conversionTime = millisToWaitForConversion(sensors.getResolution());
        isCalculating = true; //Next step is to re-calculate the temperature again.
      }
    
    
      // Next, let's calculate and send the temperature
      if (isCalculating == true && currentMillis > previousMeasurementMillis + conversionTime ) {
        isCalculating = false; // check calculating off the to-do list too.
    
        for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) { // Loop through all the attached temperatur sensors.
          float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric ? sensors.getTempCByIndex(i) : sensors.getTempFByIndex(i)) * 10.)) / 10.; // Fetch and round temperature to one decimal
          Serial.print("Sensor #");
          Serial.print(i);
          Serial.print(" says it is ");
          Serial.print(temperature);
          Serial.print(" degrees\n");
          if (temperature != -127.00 && temperature != 85.00) { // avoid working with measurement errors.
            if (COMPARE_TEMP == 1 && lastTemperature[i] == temperature) {
              Serial.print("Not sending it though, because it's the same temperature as before.\n");
            } else {
              Serial.print("Sending the temperature to the gateway.\n");
              send(msg.setSensor(i).set(temperature, 1));
              lastTemperature[i] = temperature; // Save new temperatures to be able to compare in the next round.
            }
          }
        }
    
        // Both tasks are done. Time to wait until we should measure again.
        Serial.print("zzzzZZZZzzzzZZZZzzzz\n");
    
    #ifdef BATTERY_POWERED
        unsigned long quicktimecheck = millis(); // check how much time has passed during the measurement (can be up to 750 milliseconds), and then calculate from that how long to sleep until the next intended measuring time.
        unsigned long sleeptime = measurementSleepTime - (quicktimecheck - previousMeasurementMillis); //How much time has passed already during the calculating? Subtract that from the intended interval time.
        sleep (sleeptime);
    #endif
    
        isMeasuring = true;
      }
    }
    
    
    // This function helps to avoid a problem with the latest Dallas temperature library.
    int16_t millisToWaitForConversion(uint8_t bitResolution)
    {
      switch (bitResolution) {
        case 9:
          return 94;
        case 10:
          return 188;
        case 11:
          return 375;
        default:
          return 750;
      }
    }
    
    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());
      }
    }
    
    /*Last note : celsius/farenheit in dallatemperature lib is not handled by the metric variable. To get the conversion you need to use C or F functions as below. I've not checked how you handle this in sketch.
    
        // returns temperature in degrees C
        float getTempC(const uint8_t*);
    
        // returns temperature in degrees F
        float getTempF(const uint8_t*);
    
        // Get temperature for device index (slow)
        float getTempCByIndex(uint8_t);
    
        // Get temperature for device index (slow)
      float getTempFByIndex(uint8_t);
    */


  • Have a look at at least 2 things in the sketch:
    The for-loop(s) in presentation should be seperate ones for temp and relays.
    Imo you try to send out temperature using a different ChildID than in presentation().

    Additionally, -127 degrees indicates some wiring problems.



  • @rejoe2 said in 2 dallas temp + 4 relays:

    ost in the other on

    thank you for your tip to adjust the sketch, I am now working with a node for the water meter (partly based on your example of GITHUB) and I think I understand now what you mean.

    I will adjust the sketch of the example!

    I still have a wait (3000); in "void before" to start just after the gateway, because I use an RS-485 network.



  • @rejoe2

    To be honest I had to experiment a bit to get it working, but that is probably because I have little "experience" with Arduino code writing.

    But fortunately here at MySensors we get a lot of help and tips at this forum.



  • @mghaff

    in the Dallas temperature library there is also a test sketch, with that you can check of the Dallas sensors are working.

    My experience with multiple dallas sensors (more than 4) is that de 4K7 resistor not the right choise is, beter to use a 2K2 resisitor.

    maybe you can look at this forum post for that



  • @dzjr Good to hear your positive feedback, it's not always easy to decide whether to make some critical remarks or not.
    Imo, the wait() in before() might only be needed because of the transport-wait-flag, this is not related to RS485 as transport layer.
    I also use a 3.3kOhm resistor, the right value depends on some more variables than just the number of sensors.



  • This post is deleted!


  • @dzjr If i use the mysensors dallas temp that i use for my pool the sensors work just fine. If i use the relay sketch it works fine Alone. Whenever i combine these two sketches is when i have problems. I have been trying sketches that are working for others with no progress myself. I have even rewired twice. I am no programmer i took 2 classes in college but they r not helping me either.



  • @rejoe2 When i tried the for loops separate they don't show up at all in my serial. That was the only way to get them to present. I'm trying another sketch that looks more promising for me to build from but it as well doesn't show my temp. I get presentation but no reading.

    BTW thanks for the help.



  • @rejoe2

    I have again put a wait (500) in the loop, otherwise the sketch does not read any temperature .....
    between

    {
        //Dallas temperature sensoren
        // Fetch temperatures from Dallas sensors 
        sensors.requestTemperatures();
        // query conversion time and sleep until conversion completed
        int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
        
     
        wait(500);
    
        // Read temperatures and send them to controller 
        for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
    

  • Contest Winner

    You calculate the conversion time, but you don't use it. So it makes sense that you won't get any readings without a wait, because the sensors don't get anytime to read. You should wait for the conversionTime before you read the sensors. Which is I'm guessing shorter than 500 ms, but I don't use Dallas temp sensors. So no expert on that.



  • @theol said in 2 dallas temp + 4 relays:

    You calculate the conversion time, but you don't use it. So it makes sense that you won't get any readings without a wait, because the sensors don't get anytime to read. You should wait for the conversionTime before you read the sensors. Which is I'm guessing shorter than 500 ms, but I don't use Dallas temp sensors. So no expert on that.

    Absolutely right.
    Conversion time depends on resolution, max is 750ms according to data sheet.


  • Contest Winner

    @rejoe2 changing
    wait(500);

    to

    wait( millisToWaitForConversion );

    Should do the trick.
    But wait has an unsigned long as parameter and your conversionTime is a signed int16_t, you might need to cast it. Best to update the millisWaitForConversion to unsigned long as well.

    // This function helps to avoid a problem with the latest Dallas temperature library.
    unsigned long millisToWaitForConversion(uint8_t bitResolution)
    {
      switch (bitResolution) {
        case 9:
          return 94;
        case 10:
          return 188;
        case 11:
          return 375;
        default:
          return 750;
      }
    }
    

    But it's hard to help with only a fragment of the code. I'm guessing that the resolution doesn't change when your sketch is running. In that case I'd declare a global unsigned long conversionWaitDuration and initialize it in the setup. I honestly would never ever use a wait in a sketchs main loop though. I always use a none blocking wait which uses millis().

    But again hard to help with coding when you can only see a fragment of the code.



  • @theol

    i have uploaded the complete sketch at Github at here: link url)


  • Contest Winner

    @dzjr Would be so much easier to discuss it in Dutch 🙂

    What is the problem you encounter at the moment?

    I'm looking at the code, and just asking why you use so many unneeded blocks. e.g.

    { if (flow != oldflow) { // Theo <--- Removed the bracelet at the start of the line?
    ...

    That first starting bracelet ({) is not needed because the part that is being executed if the if statement evaluates to true is after the last bracelet. I'll see if I can clean up the code a bit for you. I'll add comments with what I've changed.


  • Contest Winner

    @dzjr here is the code with my comments. It compiles but I can't test it I use NRF24L01 and don't have any dallas temp sensors. I'll be cleaning up the code more like removing unused variables. Let's use that one for debugging purposes. Don't add anything else, because there's already a lot in it and it'll be harder to find the bug.

    /******************************************************************
      Created with PROGRAMINO IDE for Arduino - 28.12.2018 12:45:52
      Project     :MySensors Watermeter Node RS485
      Libraries   :MySensors, Dallas temp etc
      Author      :MySensors community & dzjr
      Description :Mysensors Watermeter node & leiding temperatuur
                  met lekkage detectie en optie voor waterdruk
    ******************************************************************/
    
    #define MY_DEBUG
    
    //RS 485 transport zaken
    #define MY_RS485                  //RS-485 transport
    #define MY_RS485_DE_PIN 11        //De DE pin benoemen, normaal is dit PIN-3
    #define MY_RS485_BAUD_RATE 9600
    //#define MY_RS485_MAX_MESSAGE_LENGTH 40
    //#define MY_RS485_SOH_COUNT 3 // gebruiken bij Collision op de bus
    
    //eerst wat administratie en dergelijk
    #define SN "PWN_Node" //Software Naam
    #define SV "1.01"      //Software versie
    #define MY_NODE_ID 20 //Node nummer
    #define MY_TRANSPORT_WAIT_READY_MS 3000    //wachten tot de gateway is opgestart
    
    
    //libaries activeren
    #include <MySensors.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    #include <Bounce2.h>
    
    //Dallas settings
    #define COMPARE_TEMP 0 // 1= zenden alleen bij verandering 0= direct zenden
    #define ONE_WIRE_BUS 7
    #define TEMPERATURE_PRECISION 10 // 10 = 0,25°C 
    #define MAX_ATTACHED_DS18B20 4
    unsigned long SLEEP_TIME = 3000; //slaaptijd tussen twee metingen in ms
    OneWire oneWire(ONE_WIRE_BUS); //Een oneWire-exemplaar instellen om te communiceren met alle OneWire-apparaten
    DallasTemperature sensors(&oneWire); //OneWire naar Dallas
    float lastTemperature[MAX_ATTACHED_DS18B20];
    int numSensors = 0;
    bool receivedConfig = false;
    //bool metric = true;
    
    DeviceAddress Probe03 = { 0x28, 0x80, 0x43, 0x77, 0x91, 0x0F, 0x02, 0x5A  }; // leiding temp
    DeviceAddress Probe02 = { 0x28, 0xFF, 0x64, 0x1D, 0xF9, 0x9D, 0xDC, 0x5E  }; // op print1
    DeviceAddress Probe01 = { 0x28, 0xFF, 0x64, 0x1D, 0xF8, 0x4F, 0x3A, 0x08  }; // op print2
    
    
    MyMessage msgTemp(0, V_TEMP);
    
    #define CHILD_ID_PWN 11                 //Child ID Sensor watermeter
    #define CHILD_ID_LEKKAGE 21             //Child ID Lekkage sensor
    #define CHILD_ID_DRUK 22                //Child ID Water druk sensor
    #define PWN_SENSOR 2                    //Pin waar sensor watermeter op is aangesloten
    #define LEKKAGE_PIN A0                  //Pin waarop de lekkage sensor op is aangesloten
    #define WATERDRUK_PIN A1                //Pin waarom de druksensor is aangesloten
    #define SENSOR_INTERRUPT PWN_SENSOR-2   //Usually the interrupt = pin -2 
    #define PULSE_FACTOR 1000               //Pulsen per m³ water 1000=één rotatie per 10 liter
    #define MAX_FLOW 60ul                     //flitert meetfouten eruit (40 van @RBisschops en 100 van @Rejoe) <-- Theo: ul toegevoegd hoef je niet te casten
    #define wachtTime 5000ul              // Theo: added ul which makes it an unsigned long also mixing dutch and english in names is very confusing. At least to me.
    
    MyMessage flowmsg (CHILD_ID_PWN, V_FLOW);
    MyMessage volumemsg (CHILD_ID_PWN, V_VOLUME);
    MyMessage lastcountermsg (CHILD_ID_PWN, V_VAR1);
    MyMessage lekmsg (CHILD_ID_LEKKAGE, V_TEXT);
    MyMessage drukmsg (CHILD_ID_DRUK, V_PRESSURE);
    
    
    //unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
    #define SEND_FREQUENCY 30000ul // Theo it's a constant 
    
    double ppl = ((double)PULSE_FACTOR) / 1000;      // Pulses per liter
    volatile unsigned long pulseCount = 0;
    volatile unsigned long lastBlink = 0;
    volatile double flow = 0;
    boolean pcReceived = false;
    unsigned long oldPulseCount = 0;
    unsigned long newBlink = 0;
    double oldflow = 0;
    double volume = 0;
    double oldvolume = 0;
    unsigned long lastSend = 0;
    unsigned long lastPulse = 0;
    #define SLEEP_MODE false        // Watt-value can only be reported when sleep mode is false.
    unsigned long maxTimeDryRun = 30000;
    unsigned long startTimeDryRun = 0;
    volatile unsigned long dryPulseCount = 0;
    
    int lastlekValue = 0;
    int lastdrukValue = 0;
    
    // lowest and highest sensor readings:
    const int sensorMin = 0;     // sensor minimum
    const int sensorMax = 600;  // sensor maximum
    
    
    void before() {
      wait(wachtTime); // Theo: Since this is only used one, a constant is not really needed. You can keep it for better readability
      sensors.begin(); // Theo: I always use meaningfull names. To me sensors is to vague, I'd use dallasSensors or temperatureSensors.
    }
    
    void setup() {
      sensors.setWaitForConversion(false);
      pinMode(PWN_SENSOR, INPUT_PULLUP);
      sensors.setResolution(TEMPERATURE_PRECISION);
      pulseCount = oldPulseCount = 0;
      attachInterrupt(SENSOR_INTERRUPT, onPulse , FALLING );
    }
    
    void presentation() {
      sendSketchInfo(SN, SV);
    
      numSensors = sensors.getDeviceCount();
    
      for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
        //  metric = getControllerConfig().isMetric;
        // Registreer alle sensors naar de Gateway
        present(i + 0, S_TEMP, "temp sensors");
        //present(i+1, S_TEMP, "MK Node temp");
        //present(i+2, S_TEMP, "PWN Leiding temp");
        present(CHILD_ID_PWN, S_WATER, "PWN_Meter");
        request(CHILD_ID_PWN, V_VAR1, "Req PWN data" );
        present(CHILD_ID_LEKKAGE, S_INFO, "Lekkage MK");
        present(CHILD_ID_DRUK, S_BARO, "PWN Waterdruk");
      }
    }
    
    unsigned long currentTime; // Theo: <--- removed declaration from loop. Not necessary but a good practice to make large variables global. That way heap gets less fragmented
    
    void loop() {
      currentTime = millis();
    
      //Watermeter sensor
      //WaterPulse counter
      // Only send values at a maximum frequency or woken up from sleep
      if (currentTime - lastSend > SEND_FREQUENCY) {
        lastSend = currentTime;
    
        if (flow != oldflow) { // Theo <--- Removed the bracelet at the start of the line?
          oldflow = flow;
    #ifdef MY_DEBUG_LOCAL
          Serial.print("l/min:");
          Serial.println(flow);
    #endif
          // Check that we dont get unresonable large flow value.
          // could hapen when long wraps or false interrupt triggered
          if (flow < MAX_FLOW ) { // Theo: <-- cast (unsigned long) removed. No longer needed constant defined is ul (unsigned long) saves a bit of cpu time.
            send(flowmsg.set(flow, 2 ) ); // Send flow value to gw
          }
        }
    
        // No Pulse count received in 2min
        if (currentTime - lastPulse > 120000) {
          flow = 0;
        }
    
        // Pulse count has changed
        if (pulseCount != oldPulseCount) {
          oldPulseCount = pulseCount;
    #ifdef MY_DEBUG
          Serial.print(F("pulsecnt:"));
          Serial.println(pulseCount);
    #endif
          if (!pcReceived) {
            request(CHILD_ID_PWN, V_VAR1);
          }
          send(flowmsg.set(pulseCount));                  // Send  pulsecount value to gw in VAR1
    
          double volume = ((double)pulseCount / ((double)PULSE_FACTOR));
          if (volume != oldvolume) {
            oldvolume = volume;
    #ifdef MY_DEBUG
            Serial.print(F("vol:"));
            Serial.println(volume, 3);
    #endif
            send(volumemsg.set(volume, 3));               // Send volume value to gw
          }
        }
    
    
        //    { Theo
        //Waterdruk meten
        int Waterdruk = (analogRead(WATERDRUK_PIN)) * 10;
        if (Waterdruk != lastdrukValue) {
          send (drukmsg.set(Waterdruk));
          lastdrukValue = Waterdruk;
        }
    
    
        //waterlekkage sensor
        int lekLevel = map(analogRead(LEKKAGE_PIN), sensorMin, sensorMax, 0, 3);
    
        switch (lekLevel) {
          case 0:    // Sensor is droog
            send(lekmsg.set("Geen lekkage"));
            break;
          case 1:    // Sensor raakt nat
            send(lekmsg.set("Vochtig"));
            break;
          case 2:   // Sensor is volledig bedekt met water
            send(lekmsg.set("Lekkage"));
            break;
        }
        //    } Theo
    
        //    } Theo
    
    
    
    
    
    
    
        //    { Theo
        //Dallas temperature sensoren
        // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();
        // query conversion time and sleep until conversion completed
    //    int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
    
    
    //    wait(500);
    
        wait( sensors.millisToWaitForConversion( sensors.getResolution() ) );
    
        // 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.;
          float temperature;
          // voor geadreseerde sensoren
          switch (i)  {
            case 0:
              temperature = sensors.getTempC(Probe01);
              break;
            case 1:
              temperature = sensors.getTempC(Probe02);
              break;
            case 2:
              temperature = sensors.getTempC(Probe03);
              break;
            default:
              temperature = sensors.getTempCByIndex(Probe03);
              break;
          }
    
    
          // 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) { // Theo: COMPARE_TEMP looks like a constant with value 0 so the #if looks unneeded to me.??
            //#endif
    
            // Send in the new temperature
            send( msgTemp.setSensor( i ).set( temperature, 1 ) );
            // Save new temperatures for next compare
            lastTemperature[i] = temperature;
          }
          //      } Theo
        }
      }
    }
    
    void onPulse() {
      if ( !SLEEP_MODE )  {
        unsigned long newBlink = micros();
        unsigned long interval = newBlink - lastBlink;
    
        if (interval != 0) {
          lastPulse = millis();
          if (interval < 1000000L) {
            // Sometimes we get interrupt on RISING,  1000000 = 1sek debounce ( max 60 l/min)
            return;
          }
          flow = (60000000.0 / interval) / ppl;
        }
        lastBlink = newBlink;
      }
      pulseCount++;
      dryPulseCount++;
    }
    

    Another MAX_ATTACHED_DS18B20 is 4. You only have 3 probes. This means that the 3rd and 4th will always report the same values.



  • @theol

    Yes, it is easier to discuss in Dutch, but that can not be followed for the rest.

    The only thing that does not work (well) is the reading of the temperature sensors after I turned off the "wait".

    Need to take a look at why the conversionTime does not work properly.

    The use of many blocks is mainly because I am a beginner, my third real arduino sketch.
    And I copied it partly from @rejoe2 his example, and tried to get it working, which also partly succeeded. partly by applying more blocks {} ....

    I can only learn from being very friendly that you help with making the sketch better.

    I would say,

    Neem een oliebol van mij!


  • Contest Winner

    @dzjr If removed all unused variables and stuff. And the use of the bracelets was actually smart of you. Because you combined the different functions between them. The problem with it, is that is makes hard to read the code. So what I've done is I've made new functions of them outside the loop() and give them meaningful names. That way you have the lines of code, need for a specific function together in a method.
    Especially when you start learning how to program, using functions is a good practice. It will help you understand the code better.

    This code should work if it was only because the wait was removed. You need it in this case. It compiles, but I can't test it for you.

    Thanks for the oliebol 🙂 If you have any questions just ask. I'm glad that I could escape from the oudjaar-ellende 🙂 so my thanx for that.

    /******************************************************************
      Created with PROGRAMINO IDE for Arduino - 28.12.2018 12:45:52
      Project     :MySensors Watermeter Node RS485
      Libraries   :MySensors, Dallas temp etc
      Author      :MySensors community & dzjr
      Description :Mysensors Watermeter node & leiding temperatuur
                  met lekkage detectie en optie voor waterdruk
    ******************************************************************/
    
    #define MY_DEBUG
    
    //RS 485 transport zaken
    #define MY_RS485                  //RS-485 transport
    #define MY_RS485_DE_PIN 11        //De DE pin benoemen, normaal is dit PIN-3
    #define MY_RS485_BAUD_RATE 9600
    //#define MY_RS485_MAX_MESSAGE_LENGTH 40
    //#define MY_RS485_SOH_COUNT 3 // gebruiken bij Collision op de bus
    
    //eerst wat administratie en dergelijk
    #define SN "PWN_Node" //Software Naam
    #define SV "1.01"      //Software versie
    #define MY_NODE_ID 20 //Node nummer
    #define MY_TRANSPORT_WAIT_READY_MS 3000    //wachten tot de gateway is opgestart
    
    
    //libaries activeren
    #include <MySensors.h>
    #include <DallasTemperature.h>
    #include <OneWire.h>
    #include <Bounce2.h>
    
    //Dallas settings
    #define ONE_WIRE_BUS 7
    
    #define TEMPERATURE_PRECISION 10 // 10 = 0,25°C 
    #define MAX_ATTACHED_DS18B20 4
    
    OneWire oneWire(ONE_WIRE_BUS); //Een oneWire-exemplaar instellen om te communiceren met alle OneWire-apparaten
    DallasTemperature sensors(&oneWire); //OneWire naar Dallas
    
    float lastTemperature[MAX_ATTACHED_DS18B20];
    
    int numSensors = 0;
    bool receivedConfig = false;
    //bool metric = true;
    
    DeviceAddress Probe03 = { 0x28, 0x80, 0x43, 0x77, 0x91, 0x0F, 0x02, 0x5A  }; // leiding temp
    DeviceAddress Probe02 = { 0x28, 0xFF, 0x64, 0x1D, 0xF9, 0x9D, 0xDC, 0x5E  }; // op print1
    DeviceAddress Probe01 = { 0x28, 0xFF, 0x64, 0x1D, 0xF8, 0x4F, 0x3A, 0x08  }; // op print2
    
    
    MyMessage msgTemp(0, V_TEMP);
    
    #define CHILD_ID_PWN 11                 //Child ID Sensor watermeter
    #define CHILD_ID_LEKKAGE 21             //Child ID Lekkage sensor
    #define CHILD_ID_DRUK 22                //Child ID Water druk sensor
    #define PWN_SENSOR 2                    //Pin waar sensor watermeter op is aangesloten
    #define LEKKAGE_PIN A0                  //Pin waarop de lekkage sensor op is aangesloten
    #define WATERDRUK_PIN A1                //Pin waarom de druksensor is aangesloten
    #define SENSOR_INTERRUPT PWN_SENSOR-2   //Usually the interrupt = pin -2 
    #define PULSE_FACTOR 1000               //Pulsen per m³ water 1000=één rotatie per 10 liter
    #define MAX_FLOW 60ul                     //flitert meetfouten eruit (40 van @RBisschops en 100 van @Rejoe) <-- Theo: ul toegevoegd hoef je niet te casten
    #define wachtTime 5000ul              // Theo: added ul which makes it an unsigned long also mixing dutch and english in names is very confusing. At least to me.
    
    MyMessage flowmsg (CHILD_ID_PWN, V_FLOW);
    MyMessage volumemsg (CHILD_ID_PWN, V_VOLUME);
    MyMessage lastcountermsg (CHILD_ID_PWN, V_VAR1);
    MyMessage lekmsg (CHILD_ID_LEKKAGE, V_TEXT);
    MyMessage drukmsg (CHILD_ID_DRUK, V_PRESSURE);
    
    #define SEND_FREQUENCY 30000ul // Theo it's a constant 
    
    double ppl = ((double)PULSE_FACTOR) / 1000;      // Pulses per liter
    volatile unsigned long pulseCount = 0;
    volatile unsigned long lastBlink = 0;
    volatile double flow = 0;
    boolean pcReceived = false; // Theo: This value never changes...???
    unsigned long oldPulseCount = 0;
    
    double oldflow = 0;
    double volume = 0;
    double oldvolume = 0;
    unsigned long lastSend = 0;
    unsigned long lastPulse = 0;
    #define SLEEP_MODE false        // Watt-value can only be reported when sleep mode is false.
    
    volatile unsigned long dryPulseCount = 0;
    int lastdrukValue = 0;
    
    // lowest and highest sensor readings:
    const int sensorMin = 0;     // sensor minimum
    const int sensorMax = 600;  // sensor maximum
    
    
    void before() {
      wait(wachtTime); // Theo: Since this is only used one, a constant is not really needed. You can keep it for better readability
      sensors.begin(); // Theo: I always use meaningfull names. To me sensors is to vague, I'd use dallasSensors or temperatureSensors.
    }
    
    void setup() {
      sensors.setWaitForConversion(false);
      pinMode(PWN_SENSOR, INPUT_PULLUP);
      sensors.setResolution(TEMPERATURE_PRECISION);
      //  pulseCount = oldPulseCount = 0; // Theo not needed they're initialized with 0 in their declaration
      attachInterrupt(SENSOR_INTERRUPT, onPulse , FALLING );
    
      // Theo: initialize the array with 0.0 as a value.
      for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
        lastTemperature[MAX_ATTACHED_DS18B20] = 0.0;
      };
    }
    
    void presentation() {
      sendSketchInfo(SN, SV);
    
      numSensors = sensors.getDeviceCount();
    
      for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
        //  metric = getControllerConfig().isMetric;
        // Registreer alle sensors naar de Gateway
        present(i + 0, S_TEMP, "temp sensors");
        //present(i+1, S_TEMP, "MK Node temp");
        //present(i+2, S_TEMP, "PWN Leiding temp");
        present(CHILD_ID_PWN, S_WATER, "PWN_Meter");
        request(CHILD_ID_PWN, V_VAR1, "Req PWN data" );
        present(CHILD_ID_LEKKAGE, S_INFO, "Lekkage MK");
        present(CHILD_ID_DRUK, S_BARO, "PWN Waterdruk");
      }
    }
    
    unsigned long currentTime;
    
    void sendPulseValue() {
      if (flow != oldflow) {
        oldflow = flow;
    
        // Check that we dont get unresonable large flow value.
        // could hapen when long wraps or false interrupt triggered
        if (flow < MAX_FLOW ) { // Theo: <-- cast (unsigned long) removed. No longer needed constant defined is ul (unsigned long) saves a bit of cpu time.
          send(flowmsg.set(flow, 2 ) ); // Send flow value to gw
        }
      }
    
      // No Pulse count received in 2min
      if (currentTime - lastPulse > 120000) {
        flow = 0;
      }
    
      // Pulse count has changed
      if (pulseCount != oldPulseCount) {
        oldPulseCount = pulseCount;
    #ifdef MY_DEBUG
        Serial.print(F("pulsecnt:"));
        Serial.println(pulseCount);
    #endif
        if (!pcReceived) { // Because this value never changes you're requesting the value from the gateway every other 30 seconds....??
          request(CHILD_ID_PWN, V_VAR1);
        }
        send(flowmsg.set(pulseCount));                  // Send  pulsecount value to gw in VAR1
    
        double volume = ((double)pulseCount / ((double)PULSE_FACTOR));
        if (volume != oldvolume) {
          oldvolume = volume;
    #ifdef MY_DEBUG
          Serial.print(F("vol:"));
          Serial.println(volume, 3);
    #endif
          send(volumemsg.set(volume, 3));               // Send volume value to gw
        }
      }
    }
    
    void sendWaterPressure() {
      //Waterdruk meten
      int Waterdruk = (analogRead(WATERDRUK_PIN)) * 10;
      if (Waterdruk != lastdrukValue) {
        send (drukmsg.set(Waterdruk));
        lastdrukValue = Waterdruk;
      }
    }
    
    void sendWaterLeakageText() {
      //waterlekkage sensor
      int lekLevel = map(analogRead(LEKKAGE_PIN), sensorMin, sensorMax, 0, 3);
    
      switch (lekLevel) {
        case 0:    // Sensor is droog
          send(lekmsg.set("Geen lekkage"));
          break;
        case 1:    // Sensor raakt nat
          send(lekmsg.set("Vochtig"));
          break;
        case 2:   // Sensor is volledig bedekt met water
          send(lekmsg.set("Lekkage"));
          break;
      }
    }
    
    void sendTemperatureValues() {
      //Dallas temperature sensoren
      // Fetch temperatures from Dallas sensors
      sensors.requestTemperatures();
    
      // query conversion time and sleep until conversion completed
      wait( sensors.millisToWaitForConversion( sensors.getResolution() ) );
    
      // 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.;
        float temperature;
        // voor geadreseerde sensoren
        switch (i)  {
          case 0:
            temperature = sensors.getTempC(Probe01);
            break;
          case 1:
            temperature = sensors.getTempC(Probe02);
            break;
          case 2:
            temperature = sensors.getTempC(Probe03);
            break;
          default:
            temperature = sensors.getTempCByIndex(Probe03);
            break;
        }
    
        // Only send data if temperature has changed and no error
        if ( lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
    
          // Send in the new temperature
          send( msgTemp.setSensor( i ).set( temperature, 1 ) );
          // Save new temperatures for next compare
          lastTemperature[i] = temperature;
        }
      }
    }
    
    void loop() {
      currentTime = millis();
    
      //Watermeter sensor
      //WaterPulse counter
      // Only send values at a maximum frequency or woken up from sleep
      if (currentTime - lastSend > SEND_FREQUENCY) {
        lastSend = currentTime;
    
        sendPulseValue();
        sendWaterPressure();
        sendWaterLeakageText();
        sendTemperatureValues();
      }
    }
    
    // unsigned long newBlink = 0; Theo: <-- removed from top because it's never used since it's a local in your interrupt handler
    void onPulse() {
      if ( !SLEEP_MODE )  { // Theo: since you've declared it as a constant with value false the check is not needed. The evaluation of the if statement will always be true
        unsigned long newBlink = micros();
        unsigned long interval = newBlink - lastBlink;
    
        if (interval != 0) {
          lastPulse = millis();
          if (interval < 1000000L) {
            // Sometimes we get interrupt on RISING,  1000000 = 1sek debounce ( max 60 l/min)
            return;
          }
          flow = (60000000.0 / interval) / ppl;
        }
        lastBlink = newBlink;
      }
      pulseCount++;
      dryPulseCount++;
    }
    


  • Good work, @TheoL!
    Some additional remarks intented for @dzjr form my side:

    • Do you really want to start the node also when no communication to the GW is present? Otherwise disable "#define MY_TRANSPORT_WAIT_READY_MS 3000"
    • calculation of the conversion time could also be done once
    • using an array containing all of the sensor addresses makes code even more easy to read.

    For the later two things see https://github.com/rejoe2/MySensors-Dallas-Address-ChildID-Consistency/blob/master/Dallas_Addresses_Array_Solution/Dallas_Addresses_Array_Solution.ino (hope this still works, there had been some changes in the dallas-temp lib since I last used it myself).



  • @theol
    As a first of course a happy new year for all of you.

    @TheoL thank you for your work, that reads and programs a lot easier with their own voids, did not know that could work!

    I just loaded the net, only the temperature sensors do not come through, I'll tell you tonight if I can find it.

    The sketch is partly based on the MySensor-Garage Sketch from @rejoe2 , I copied the parts I needed (for the water meter), and for the temperature I copied it from another sketch which I had also used for another project. .

    As I said before, I am a beginner with Arduino, so I am very happy with this help and advice.

    Thanks again for your help



  • @rejoe2

    I thought that with #define MY_TRANSPORT_WAIT_READY_MS you could start the gateway first and then the node, I built everything with one 5 volt power supply, which is why I want the node to start later, before I now have a wait in void put down.

    I will take a look at the DALLAS scketch tonight or I can also use it in this sketch.



  • I have it working!

    In "void setup" I removed the extra lines , and then it worked \ o /

    // Theo: initialize the array with 0.0 as a value.
    for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
      lastTemperature[MAX_ATTACHED_DS18B20] = 0.0;
    };
    

    @ rejoe2 i removed the " wait transport" ,
    I tried your Dallas_Addresses_Array_Solution sketch, I think that maybe there are some library adjustments given, because it did not work directly (I got 00000000 as message).
    By the way, if I disconnect one sensor, another sensor is set it place at the controller, if it is connected again then it is back to the original ID.

    I have changed this line (line 114)

    float temperature = static_cast<float>(static_cast<int>((metric ? sensors.getTempC(dallasAddresses[i]) : sensors.getTempF(dallasAddresses[i])) * 10.)) / 10.;
    

    into this: (from the example sketch at the build section)

    float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
    


  • @dzjr said in 2 dallas temp + 4 relays:

    By the way, if I disconnect one sensor, another sensor is set it place at the controller, if it is connected again then it is back to the original ID.

    This is where the array method is advantageous, the child-IDs of the chip addresses are fixed consecutively in the array, remove the chip from the line and it's place remains vacant until replaced.



  • @dzjr said in 2 dallas temp + 4 relays:

    MY_TRANSPORT_WAIT_READY_MS

    This flag is - amongst a lot of other stuff - explained here: https://www.mysensors.org/download/sensor_api_20.
    So putting it to (default) "0" will keep the node looking for an uplink to the GW until that one is really available. As I don't want that (my nodes have some logic of their own, I want to work independently), I added that. But in case, it's just sensors and so on, I'd recommend to stick with the defaults.

    Wrt. to the "metric"-topic: Please do always have a look at the entire sketch. In my sketches, typically the metric variable is just initialized once in setup(). Eg. in the array-sketch you'll find that in line 97.
    If you are looking for a "easy" way to replace single sensors and keeping the original order of the others, have a look at this one.



  • @rejoe2

    thank you, now I understand how it works, had it tried without a wait and then the transport did not start well, not all nodes were visible in the MySController, with "wait" in the setup all node's are visible in the controller at a complete restart (in case of power failure)

    The current method with dallas sensors also works well for me, not me to change the sensors, but to always give the sensors a fixed child id in Domoticz.



  • @dzjr Did you also try with the default value ("0") instead of 3000?
    I'm not familiar wir domoticz, but the need for another wait looks like a strange behaviour to me.



  • For low number of DS18B20 and if you have got enough free pins,
    I suggest use separate Arduino pin for each DS18B20.
    Then your code is absolute universal and you always know, which pin what measure.
    Do not matter, which DS18B20 you use.
    With your method, you must read each DS18B20 signature - hardcoded it, compile and flash.
    When sensor needs replacement due to malfunction - whole process again.



  • @kimot This consumes a lot of PINs, so it's a question what kind of trade-off you are looking for.
    As the 1Wire sensors have the option to address them correctly, I really like the advantage of reducing bus numbers. Just to remark: I also have at least one node running with 3 1Wire PINs - but each with a different timing 😁 . But if you are just worrying about replacement of single sensors, use something like that: https://github.com/rejoe2/MySensors-Dallas-Address-ChildID-Consistency. That only needs a restart between eacht replacement 😏 .
    Or add OTA features to your nodes...



  • @rejoe2

    Yes i tried is, i disable'd it in the sketch, but than the node's are nog presenting good to MYSController, only the update's are coming true but without the name's, only the first node give his client names.
    So ik just use wait in void setup.

    0_1546544175576_7235d3d6-97e7-4a34-b31e-5c67ac9b9147-image.png



  • @kimot
    In this node i can do that, i had copied it from another sketch i used 8 dallas sensors and i just copied that to this sketch.

    Perhaps i wil adjust the sketch and hardware.



  • First of all. thank you guys for all the help! here is what i found out. When testing my hardware i found that alone with the MySensors Dallas sensors sketch i would get readings from my Dallas sensors in serial and at controller. With relay sketch alone i would get All 4 relays working in controller and in serial. But combined no Dallas temp in serial or controller. I rewired with new sensors, Arduino nano, radio! Finally digging through my stuff i found a new board from a batch ordered 2 years ago, wired it up on bread board and wallah! Apparently the last batch or boards i ordered must have not passed quality or damaged in shipping!! Thanks again for the support!! On a way brighter note I have address's assigned to my temp sensors now on all my nodes and have learned so much more about the MySensors network!


Log in to reply
 

Suggested Topics

  • 3
  • 24
  • 2
  • 2
  • 2
  • 1

1
Online

11.2k
Users

11.1k
Topics

112.5k
Posts