Multi mysensor sketch help



  • Hello i have a question and need some help since im new to arduino . ive tried to build my first multi sensor sketch and it works only i need to add one more (smoke sensor) and i need someone to look at it and tell me how to clean it up better. im a quick learner and need some pointers.
    The sketch is working i get all the readings in my openhab2 server running on a pi the ethernet gateway is runnning on the mysensors binding. we are rebuilding our entire home and making it a selfsuccient smart home. were 1 year into the build and getting there

    here is the sketch for my wifes greenhous i got a dht sensor (had troubles with the 2320sensors) a soil sensor with a 2 relay module and a door/window button. they talk over a nrf network wich runs ok allready got a bunch of sensor nodes up and running.

    im trying to use the millis count to keep it al working the help i need is cleaning the sketch up. can someone please give me pointers on what i can do to clean it up or where i may have made misstakes.

    Regards and sorry for the bad english

    Robert

    /**
     * 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
     * Version 1.1 - 2016-07-20: Converted to MySensors v2.0 and added various improvements - Torben Woltjen (mozzbozz)
     * 
     * DESCRIPTION
     * This sketch provides an example of how to implement a humidity/temperature
     * sensor using a DHT11/DHT-22.
     *  
     * For more information, please visit:
     * http://www.mysensors.org/build/humidity
     * 
     */
    
    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached 
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    //#define MY_RS485
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DHT.h>
    #include <math.h>       // Conversion equation from resistance to % tbv soil
    #include <Bounce2.h>
    #define MY_NODE_ID 5
    
    
    // Setting up
    #define NUM_READS 10    // Number of sensor reads for filtering
    #define CHILD_ID_SOIL 7
    #define CHILD_ID_HUM 8
    #define CHILD_ID_TEMP 9
    #define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define NUMBER_OF_RELAYS 2 // 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
    #define CHILD_ID_BUTTON 6
    #define BUTTON_PIN  5  // Arduino Digital I/O pin for button/reed switch
    
    // unsigned long   var1_usl;     //uptime in ms
    
    Bounce debouncer = Bounce(); 
    int oldValue=-1;
    
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msgBut(CHILD_ID_BUTTON, V_TRIPPED);
    
    MyMessage msgSoil(CHILD_ID_SOIL, V_LEVEL);
    
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    
    long buffer[NUM_READS];
    int index;
    
    /// @brief Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs)
    typedef struct {
        int moisture; //!< Moisture
        long resistance; //!< Resistance
    } values;
    
    const long knownResistor = 4700;  // Constant value of known resistor in Ohms
    
    int supplyVoltage;                // Measured supply voltage
    int sensorVoltage;                // Measured sensor voltage
    
    values valueOf[NUM_READS];        // Calculated moisture percentages and resistances to be sorted and filtered
    
    int i;                            // Simple index variable
    
    
    // Set this to the pin you connected the DHT's data pin to
    #define DHT_DATA_PIN 8
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET 0
    
    // Sleep time between sensor updates (in milliseconds)
    // Must be >1000ms for DHT22 and >2000ms for DHT11
    static const uint64_t UPDATE_INTERVAL = 20000;
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 10;
    
    float lastTemp;
    float lastHum;
    uint8_t nNoUpdatesTemp;
    uint8_t nNoUpdatesHum;
    bool metric = true;
    
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    DHT dht;
    
    // Timings
    unsigned long temperature_time;
    unsigned long soil_time;
    
    void presentation()  
    { 
      // Send the sketch version information to the gateway
      sendSketchInfo("Greenhouse", "1.1");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_SOIL, S_MOISTURE);
      present(CHILD_ID_BUTTON, S_DOOR);
      metric = getControllerConfig().isMetric;
       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);
        }
    }
    
    
    void setup()
    {
    // Setup the button
      pinMode(BUTTON_PIN,INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN,HIGH);
    
      // After setting up the button, setup debouncer
      debouncer.attach(BUTTON_PIN);
      debouncer.interval(5);
    
    
    
    
    //relay ohohwerkieofni
      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);
        }
      //soil
      // initialize the digital pins as an output
        // Pin 6,7 is for sensor 1
        // initialize the digital pin as an output.
        // Pin 6 is sense resistor voltage supply 1
        pinMode(6, OUTPUT);
    
        // initialize the digital pin as an output.
        // Pin 7 is sense resistor voltage supply 2
        pinMode(7, OUTPUT);
    
    
     
      //dht
      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) 
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
      
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      sleep(dht.getMinimumSamplingPeriod());
    
      //initialize times
      temperature_time = millis();
      soil_time = millis();
    
      }  
    void loop()      
    {  
    
        unsigned long time_passed = 0;
     //BUTTON 
      debouncer.update();
      // Get the update value
      int value = debouncer.read();
    
      if (value != oldValue) {
         // Send in the new value
         send(msgBut.set(value==HIGH ? 1 : 0));
         oldValue = value;
      }
    // Temp/Hum sensor 
      
      // Force reading sensor, so it works also after sleep()
      // dht.readSensor(true);
    time_passed = millis() - temperature_time;
    if (time_passed < 0)
    {
    temperature_time = millis();
    }
      
    if (time_passed > 6000)
    {
      // Get temperature from DHT library
      float temperature = dht.getTemperature();
      if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT!");
      } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
        // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        // Reset no updates counter
        nNoUpdatesTemp = 0;
        temperature += SENSOR_TEMP_OFFSET;
        send(msgTemp.set(temperature, 1));
    
        #ifdef MY_DEBUG
        Serial.print("T: ");
        Serial.println(temperature);
        temperature_time = millis();
        #endif
      } else {
        // Increase no update counter if the temperature stayed the same
        nNoUpdatesTemp++;
      }
    
      // Get humidity from DHT library
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
        // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
        lastHum = humidity;
        // Reset no updates counter
        nNoUpdatesHum = 0;
        send(msgHum.set(humidity, 1));
    
        #ifdef MY_DEBUG
        Serial.print("H: ");
        Serial.println(humidity);
        #endif
      } else {
        // Increase no update counter if the humidity stayed the same
        nNoUpdatesHum++;
      
      } 
      // Sleep for a while to save energy
    // sleep(UPDATE_INTERVAL); 
    
    //soil
    
    time_passed = millis() - soil_time;
      if (time_passed < 0)
      {
      soil_time = millis();
      }
      
      if (time_passed > 6000)
    {
    
     measure(6,7,1);
        Serial.print ("\t");
        Serial.println (average());
        long read1 = average();
    
        measure(7,6,0);
        Serial.print ("\t");
        Serial.println (average());
        long read2= average();
    
        long sensor1 = (read1 + read2)/2;
    
        Serial.print ("resistance bias =" );
        Serial.println (read1-read2);
        Serial.print ("sensor bias compensated value = ");
        Serial.println (sensor1);
        Serial.println ();
        soil_time = millis();
    
        //send back the values
        send(msgSoil.set((long int)ceil(sensor1)));
        // delay until next measurement (msec)
    //    sleep(SLEEP_TIME);
    }
    }
    }
    void measure (int phase_b, int phase_a, int analog_input)
    {
        // read sensor, filter, and calculate resistance value
        // Noise filter: median filter
    
        for (i=0; i<NUM_READS; i++) {
    
            // Read 1 pair of voltage values
            digitalWrite(phase_a, HIGH);                 // set the voltage supply on
            delayMicroseconds(25);
            supplyVoltage = analogRead(analog_input);   // read the supply voltage
            delayMicroseconds(25);
            digitalWrite(phase_a, LOW);                  // set the voltage supply off
            delay(1);
    
            digitalWrite(phase_b, HIGH);                 // set the voltage supply on
            delayMicroseconds(25);
            sensorVoltage = analogRead(analog_input);   // read the sensor voltage
            delayMicroseconds(25);
            digitalWrite(phase_b, LOW);                  // set the voltage supply off
    
            // Calculate resistance
            // the 0.5 add-term is used to round to the nearest integer
            // Tip: no need to transform 0-1023 voltage value to 0-5 range, due to following fraction
            long resistance = (knownResistor * (supplyVoltage - sensorVoltage ) / sensorVoltage) ;
    
            delay(1);
            addReading(resistance);
            Serial.print (resistance);
            Serial.print ("\t");
        }
    }
    
    
    
    // Averaging algorithm
    void addReading(long resistance)
    {
        buffer[index] = resistance;
        index++;
        if (index >= NUM_READS) {
            index = 0;
        }
    }
    
    long average()
    {
        long sum = 0;
        for (int i = 0; i < NUM_READS; i++) {
            sum += buffer[i];
        }
        return (long)(sum / NUM_READS);
    }
    
    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());
        }
    }
    


  • I'm not en expert, but the sketch looks quite ok.

    One thing seems to be faulty: the reassignment of the temperature_time is within the #ifdef ... section. If you comment out MY_DEBUG, this will not be executed.

    Options for enhancements:

    • as time_passed is unsigned long, it could not get lower than 0, so asking for this is not necessary (some explanation: time_passed will be a very huge figure in case millis() is lower than temperature time). Same for soil_time.
    • as you use the same timings, distinguishing between both is not necessary
    • 6 seconds as a intervall for this kind of measurement seems pretty short imo
    • with only one button you could also use an interrupt and make the node sleep() or wait() in between (needs a change in HW also, PIN2 or 3 for swith; see the BinarySwitchSleep-example for details or the PulseWaterMeter for using a seperate routine. In later case you have to include the send() instruction within the interrupt routine).


  • Thank you for your quick response !

    Ill have a go changing all you said, the 6 seconds interval was for testing purposes so i didnt have to wait for the output.

    Ill have a looksee at the examples you mentioned.

    my next step is to hook up the 1000 meters of cat6e cable i put everywhere, to hook up all the door/window buttons and sensors/arduinos and making rules to get them all to work with all the philips hue lights and whatnot.

    this was my first multi sketch with a lot of copy paste and trial and error πŸ˜„



  • You are welcome!
    If you are interested in some examples of combined sensors: Most of my stuff is located at github: https://github.com/rejoe2
    You may be especially interested in the code here: https://github.com/rejoe2/MySensors_Small/tree/master/MyS103, but be warned: there seems to be some problem with this node, but imo this is related to either RF or the BMP180 part of it.


  • Mod

    @rob
    Is your node battery powered? If not, sleep isn't that mandatory and if node is sleeping you can't send commands to activate relays, just saying in case you missed it.



  • Yeah thats on my todo list to , the weather station πŸ˜„ i got al the sensors now to hook them up and write the sketches then agian i got a verryyyyy long todo list


  • Mod

    You are not alone between those with long to do lists 😁



  • no this node is not batterpowerd, hence the millis etc for the wait period still need to clean up the sketch and still remove some of the stuff left behind from al that copy and pasting πŸ˜„



  • @rob The weather station is not tested at all, just a collection of ideas and a lot of parts laying around for a long time already 😞
    @gohan Thx for clarification wrt. to !sleep()!


Log in to reply
 

Suggested Topics

0
Online

11.2k
Users

11.1k
Topics

112.5k
Posts