Irrigation controller
-
Hi!
I am using the code at https://blog.m.nu/gastblogg-styrning-av-bevattning-balkonglador/ (swedish page) but can't seem to get it to work. The trick is, I have only one sensor.
Which parts of the code needs to be altered?Pasted code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 /* **SKETCH BEGINNING** /** * 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 */ // Enable debug prints to serial monitor //#define MY_DEBUG //Network #define MY_NODE_ID 8 // I have hardcoded the ID #define MY_PARENT_NODE_ID 0 // I have hardcoded the gateway #define MY_PARENT_NODE_IS_STATIC #define MY_RADIO_NRF24 //What type of radio #define MY_RF24_PA_LEVEL RF24_PA_MAX //The radio is one with antenna so we must set this to max //Signing makes everything secure. Arduino must be prepared before according to mysensors.org #define MY_SIGNING_SOFT #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 #define MY_SIGNING_REQUEST_SIGNATURES //Includes #include <SPI.h> #include <MySensors.h> #include <SI7021.h> #include <RunningAverage.h> //Define Relay #define RELAY_1 3 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define RELAY_2 4 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define RELAY_3 5 // 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 #define RELEASE "1.4" //Define Moisture things #define AVERAGES 2 //we use 2 readings to smooth the readings #define STABILIZATION_TIME 1000 // Let the sensor stabilize before reading //Change direction on moisture could help with corrosion byte direction = 0; //Moisture sensor pins const int SENSOR_ANALOG_PINS[] = {A0, A1}; // Sensor1 is connected to these two pins. const int SENSOR_ANALOG_PINS2[] = {A2, A3}; // Sensor2 is connected to these two pins. // Child sensor ID's #define CHILD_ID_TEMP 5 #define CHILD_ID_HUM 6 #define CHILD_ID_MOISTURE 7 #define CHILD_ID_MOISTURE2 8 #define CHILD_ID_BUTTON 9 #define CHILD_ID_BUTTON2 10 // How many milli seconds between each measurement of temp and humidity #define MEASURE_INTERVAL 30000 // FORCE_TRANSMIT_INTERVAL, the sensor is forced to report all values to the controller #define FORCE_TRANSMIT_INTERVAL 2000 // 20minutes // TRANSMIT_THRESHOLD tells how much the humidity/remperature should have changed since last time it was transmitted. #define HUMI_TRANSMIT_THRESHOLD 1.0 #define TEMP_TRANSMIT_THRESHOLD 0.2 #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) #define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) SI7021 humiditySensor; RunningAverage raHum(AVERAGES); // Sensor messages, here I define different channels where the info is sent MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); MyMessage msgMoist(CHILD_ID_MOISTURE, V_HUM); MyMessage msgMoist2(CHILD_ID_MOISTURE2, V_HUM); MyMessage msgButton(CHILD_ID_BUTTON, V_HUM); MyMessage msgButton2(CHILD_ID_BUTTON2, V_HUM); MyMessage msgR1(RELAY_1, V_STATUS); MyMessage msgR2(RELAY_2, V_STATUS); // Global settings const unsigned long tUpdateMoist = 3600000; // update interval for the moisture sensor1, 1hour const unsigned long tUpdateMoist2 = 3600000; //update interval for the moisture sensor2, 1hour unsigned long t1; //defining t1 unsigned long t2; //defining t2 int measureCount = 0; //defining measureCount boolean isMetric = true; boolean highfreq = true; //delete, is probably not needed boolean transmission_occured = false; //reset so it starts at false // Storage of old measurements, reset them all to 0 float lastTemperature = -100; int lastHumidity = -100; int oldMoistureLevel = -1; int oldMoistureLevel2 = -1; int button = -1; int button2 = -1; 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); } } void setup() { Serial.begin(115200); humiditySensor.begin(); isMetric = getControllerConfig().isMetric; Serial.print(F("isMetric: ")); Serial.println(isMetric); raHum.clear(); t1=millis(); t2=millis(); //sendTempHumidityMeasurements(true); sendMoistureMeasurements(); sendMoistureMeasurements2(); delay(250); for (int i = 0; i < N_ELEMENTS(SENSOR_ANALOG_PINS); i++) { pinMode(SENSOR_ANALOG_PINS[i], OUTPUT); digitalWrite(SENSOR_ANALOG_PINS[i], LOW); } for (int j = 0; j < N_ELEMENTS(SENSOR_ANALOG_PINS2); j++) { pinMode(SENSOR_ANALOG_PINS2[j], OUTPUT); digitalWrite(SENSOR_ANALOG_PINS2[j], LOW); } } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("RelayTempHumMoist", "1.0"); 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,"Relays"); } present(CHILD_ID_TEMP,S_TEMP,"Temperature"); present(CHILD_ID_HUM,S_HUM,"Humidity"); present(CHILD_ID_MOISTURE, S_HUM,"Moisture"); present(CHILD_ID_MOISTURE2, S_HUM,"Moisture2"); present(CHILD_ID_BUTTON, S_HUM,"Button"); present(CHILD_ID_BUTTON2, S_HUM,"Button2"); } void loop() { measureCount ++; bool forceTransmit = false; transmission_occured = false; if (measureCount > FORCE_TRANSMIT_INTERVAL) { forceTransmit = true; measureCount = 0; Serial.print(F("inne i loopen :")); } if ((millis() - t1) > tUpdateMoist) sendMoistureMeasurements(); if ((millis() - t2) > tUpdateMoist2) sendMoistureMeasurements2(); sendTempHumidityMeasurements(forceTransmit); } void sendTempHumidityMeasurements(bool force) { wait(MEASURE_INTERVAL); bool tx = force; si7021_env data = humiditySensor.getHumidityAndTemperature(); raHum.addValue(data.humidityPercent); float diffTemp = abs(lastTemperature - (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths)/100.0); float diffHum = abs(lastHumidity - raHum.getAverage()); Serial.print(F("TempDiff :"));Serial.println(diffTemp); Serial.print(F("HumDiff :"));Serial.println(diffHum); if (isnan(diffHum)) tx = true; if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true; if (diffHum > HUMI_TRANSMIT_THRESHOLD) tx = true; if (tx) { measureCount = 0; float temperature = (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths) / 100.0; int humidity = data.humidityPercent; Serial.print("T: ");Serial.println(temperature); Serial.print("H: ");Serial.println(humidity); send(msgTemp.set(temperature,1)); send(msgHum.set(humidity)); lastTemperature = temperature; lastHumidity = humidity; transmission_occured = true; } } void sendMoistureMeasurements() { pinMode(SENSOR_ANALOG_PINS[direction], INPUT_PULLUP); // Power on the sensor analogRead(SENSOR_ANALOG_PINS[direction]);// Read once to let the ADC capacitor start charging sleep(STABILIZATION_TIME); int moistureLevel = (1023 - analogRead(SENSOR_ANALOG_PINS[direction])); // Turn off the sensor to conserve battery and minimize corrosion pinMode(SENSOR_ANALOG_PINS[direction], OUTPUT); digitalWrite(SENSOR_ANALOG_PINS[direction], LOW); direction = (direction + 1) % 2; // Make direction alternate between 0 and 1 to reverse polarity which reduces corrosion // Always send moisture information so the controller sees that the node is alive // Send rolling average of 2 samples to get rid of the "ripple" produced by different resistance in the internal pull-up resistors // See http://forum.mysensors.org/topic/2147/office-plant-monitoring/55 for more information if (oldMoistureLevel == -1) { // First reading, save value oldMoistureLevel = moistureLevel; } if (button == 1) { send(msgButton.set((moistureLevel + oldMoistureLevel + 0.5) / 2 / 10.23, 1)); oldMoistureLevel = moistureLevel; t1 = millis(); Serial.print(F("inne i button :")); } if (button == 0) { send(msgMoist.set((moistureLevel + oldMoistureLevel + 0.5) / 2 / 10.23, 1)); oldMoistureLevel = moistureLevel; t1 = millis(); } button = 0; } void sendMoistureMeasurements2() { pinMode(SENSOR_ANALOG_PINS2[direction], INPUT_PULLUP); // Power on the sensor analogRead(SENSOR_ANALOG_PINS2[direction]);// Read once to let the ADC capacitor start charging sleep(STABILIZATION_TIME); int moistureLevel2 = (1023 - analogRead(SENSOR_ANALOG_PINS2[direction])); // Turn off the sensor to conserve battery and minimize corrosion pinMode(SENSOR_ANALOG_PINS2[direction], OUTPUT); digitalWrite(SENSOR_ANALOG_PINS2[direction], LOW); direction = (direction + 1) % 2; // Make direction alternate between 0 and 1 to reverse polarity which reduces corrosion // Always send moisture information so the controller sees that the node is alive // Send rolling average of 2 samples to get rid of the "ripple" produced by different resistance in the internal pull-up resistors // See http://forum.mysensors.org/topic/2147/office-plant-monitoring/55 for more information if (oldMoistureLevel2 == -1) { // First reading, save value oldMoistureLevel2 = moistureLevel2; } if (button2 == 1) { send(msgButton2.set((moistureLevel2 + oldMoistureLevel2 + 0.5) / 2 / 10.23, 1)); oldMoistureLevel2 = moistureLevel2; t2 = millis(); Serial.print(F("inne i button2 :")); } if (button2 == 0) { send(msgMoist2.set((moistureLevel2 + oldMoistureLevel2 + 0.5) / 2 / 10.23, 1)); oldMoistureLevel2 = moistureLevel2; t2 = millis(); } button2 = 0; } void receive(const MyMessage &message) { // Here I can send messages to the node. 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()); } if (message.type==V_TRIPPED) { // Change relay state button = 1; button2 = 1; sendMoistureMeasurements(); sendMoistureMeasurements2(); } } **SKETCH END** */
Thanks in advance.
Cheers,
Erik
-
Welcome to the MySensors forum, @erik
I think @Nicklas-Starkel wrote that blog post, tagging him so maybe he can assist.
-
@erik the sketch enables signing. As per the comment, that require the node to be personalized. Have you done that? And configured the gateway accordingly? If you don't want or don't plan to use signing, comment those flags.
To the blogger (if he reads this): please be more clear on the implications of using security when posting online.
-
@anticimex @mfalkvidd thanks for the replies.
You mean line 41-43? I'm quite new to this, so even though I have bought and attached a wifi device I plan to start simple. A single sensor and water pump, no signing nor gateway. I do have a raspberry pi available, but haven't bought the required pi radio module from what I understand is required.
-
@erik everything starting with "MY_SIGNING".
Running a mysensors node without gateway? I don't think that is possible. The gateway is the interface to whateger controller you use/plan to use.
-
@anticimex gotcha. But the article says that if you want to run without a gateway, just skip the wifi part? Am I missing something here?
-
@erik I don't know. I am suspicious of the article since it shows a sketch that enables and enforces signing, but does not mention signing at all, so I don't know how many other assumptions are implicitly hidden in the article.
As far as I know, a atmega328p device has no wifi capability, so it has to use one of the other radios (nrf24, rfm69, etc) to communicate its data to a receiver. That receiver is designated gateway.
The only other way I can think of is running sensors directly on the gateway and have the gateway then communicate the sensor data using the gateway protocol in whatever transport the gateway has (which might be wifi).
-
@erik said in Irrigation controller:
https://blog.m.nu/gastblogg-styrning-av-bevattning-balkonglador/
I don't know if it's useful to you, but here's my sketch. I use it to connect 6 analog capacitive sensors to one Arduino Nano, and also attach 6 LED's (or solenoid valves!) to 6 digital outputs.
So for example, if plant number 5 is thirsty (<30% moisture), then solenoid 5 will open to give it some water.
/** * 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 * * This node can measure the moisture of 6 different plants. It uses the cheap 'capacitive analog * moisture sensor' that you can get for about 3 dollars an Aliexpress or eBay. For example: * https://www.aliexpress.com/item/Analog-Capacitive-Soil-Moisture-Sensor-V1-2-Corrosion-Resistant-Z09-Drop-ship/32858273308.html * * Each plant' moisture value can also be responded to individually, either by turning on an LED (wire that to the plan, and you can see which one is thirsty) or, if you want, per-plant automated irrigation by connecting a little solenoid.. * * Todo: Allow the controller to set the threshold values for each plant individually. Unfortunately, Domoticz doesn't support this yet :-( * */ //#define MY_SIGNING_SIMPLE_PASSWD "changeme" // Useful if your MySensors network is encrypted. #define MY_SPLASH_SCREEN_DISABLED // saves a little memory. //#define MY_DISABLE_RAM_ROUTING_TABLE_FEATURE // saves a little memory. //#define MY_NODE_ID 60 // Optional. Sets fixed id with controller. //#define MY_PARENT_NODE_ID 0 // Optional. Sets fixed id for controller. //#define MY_PARENT_NODE_IS_STATIC // Optional. Sets fixed id for controller. #define MY_TRANSPORT_WAIT_READY_MS 10000 // try connecting to the gateway for 10 seconds. Otherwise just continue. // Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_NRF5_ESB //#define MY_RADIO_RFM69 //#define MY_RADIO_RFM95 #define MY_RF24_PA_LEVEL RF24_PA_LOW // Low power radio setting works better with cheap Chinese radios. #include <MySensors.h> #define NUMBEROFSENSORS 6 // How many sensors are connected? #define DRYNESSTHRESHOLD 45 // minimum moisture level that is still ok. A lower value will trigger LED/irrigation. #define SLEEPTIME 60 // sleep time between the sending of data (in SECONDS). Maximum is 254 seconds. Change "byte" to "int" further down in the code if you want more time between sending updates. unsigned long lastTimeChecked = 0; // used by the measurement timer. MyMessage msg(0, V_LEVEL); // used to send data to the gateway void before() { for (byte i = 3; i < NUMBEROFSENSORS + 3; i++){ // Set the LED (or irrigation vales) to their initial position. Because Mysensors uses pin 2, we use pin 3 till 8 as output. pinMode(i, OUTPUT); digitalWrite(i, LOW); } } void presentation() { // send the sketch version information to the gateway and Controller sendSketchInfo(F("Plant Sensorium"), F("1.0")); // present the sensors for (byte i=0; i<NUMBEROFSENSORS ; i++) { present(i, S_MOISTURE); // the last i gives the controller a name, in this case the number of the sensor. } } void setup() { Serial.begin(115200); delay(1000); Serial.println(F("Hello world. Warming up the sensors (15 seconds).")); // to avoid weird measurements delay(15000); } void loop() { static byte measurementCounter = 0; // Counts the measurements. Internally the node measures once per second. if (millis() - lastTimeChecked > 1000) { lastTimeChecked = millis(); Serial.println(F("__________")); for (int i=0; i<NUMBEROFSENSORS; i++) { // loop over all the sensors. byte shiftedDigitalPin = i + 3; int16_t moistureLevel = (1023-analogRead(i))/10.23; Serial.print(i); Serial.print(F(" mosture level: ")); Serial.println(moistureLevel); if(digitalRead(shiftedDigitalPin) == HIGH){ // outputs the LED/irrigation status via serial. This code can be removed. Serial.print(F("- currently watering until ")); Serial.println(DRYNESSTHRESHOLD + 10); } if (moistureLevel < DRYNESSTHRESHOLD){ // if the plant doesn' have enough water, turn on the LED/water. Serial.print(F("- moisture level is below ")); Serial.println(DRYNESSTHRESHOLD); digitalWrite(shiftedDigitalPin, HIGH); }else if (moistureLevel >= DRYNESSTHRESHOLD + 10){ // turn of the water/led if the plant is wet enough. digitalWrite(shiftedDigitalPin, LOW); } if(measurementCounter < NUMBEROFSENSORS){ // During the first 6 seconds the script will send updated data. if(measurementCounter == i){ // it sends sensor 0 at second 0. Sensor 1 at second 1, etc. This keeps the radio happy. Serial.println(F("- sending data.")); send(msg.setSensor(i).set(moistureLevel)); } } if(measurementCounter > SLEEPTIME){ // If enough time has passed, the counter is reset, and new data is sent. measurementCounter = 0; }else{ measurementCounter++; } } } }
-
Erik .if you dont have a gateway or mysensors implemented in your house yet,you should do someting simple.that schetch its crazy for a new start person.
Some relays that fire by time its enouf. Wifi part that you want provably its realy Wi-Fi,not mysensors conection that its an wireless protocol,(not wifi). We are deep in summer,its not time to make a new irrigation controller from 0 and tryit
-
@Anticimex well the article spawned my interest but not sure at all about assumptions or similar. I kind of just tried to find relevant parts on AliExpress based on the article and started building. I have bought a nrf24 card to connect. How can I modify the code then to just skip the signing and wifi connectivity for now, just to see if this works?
@alowhum nice. How do you define which sensors are connected where? Do I need more code than that? Other libraries (doesn't seem so?).
@Tmaster not sure what you are saying here, are the wifi sensors not using Wifi?
I bought this module: https://www.aliexpress.com/item/nrf24l0-PA-VER2-0-small-size-of-the-module-high-power-wireless-module-long-distance/32458371131.html and attach it through the socket adapter (which turns 3.3V to 5V) https://www.aliexpress.com/item/1pcs-New-Socket-Adapter-plate-Board-for-8Pin-NRF24L01-Wireless-Transceive-module-51/32656317260.html . The Wifi antenna itself I grabbed from an old router I had laying around. Then attached the module according to the article; VCC to a β5Vβ block and pin GND to β5V GNDβ. The others were connected: CE to 9, CSN to 10, MOSI to 11, MISO to 12 and SCK to 13.
Anyway, that is the Wifi module and of course I am interested in getting that to work as well (perhaps with my raspberry pi?), but the immediate goal is to get it to work at all.Appreciate the help people
-
@erik to disable signing in the sketch, I already gave you the answer above.
Quote: "everything starting with "MY_SIGNING"."
-
@Anticimex just tried this, doesn't seem to work.
What is the easiest way to debug this? How can I verify that all the components work?