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 therehere 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 :D
-
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. -
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 :D
-
Yeah thats on my todo list to , the weather station :D i got al the sensors now to hook them up and write the sketches then agian i got a verryyyyy long todo list