Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- REVISION HISTORY
- Created by Mark Swift
- V1.4 - Reversed waiting LED logic.
- V1.5 - Added analog moisture option.
- V1.6 - Added analog moisture reading gateway message
- V1.7 - Added analog smoothing
- V1.8 - Shortened Sketch Name (Prevent send presentation errors)
- */
- // Enable debug prints
- #define MY_DEBUG
- // Required for MQTT as gateway does not automagically assign ID's
- #define MY_NODE_ID 3
- // Set parent node ID manually
- #define MY_PARENT_NODE_ID 0
- // Enable and select radio type attached
- #define MY_RADIO_NRF24
- // #define MY_RADIO_RFM69
- // Set RF24L01 channel number
- #define MY_RF24_CHANNEL 125
- // Enabled repeater feature for this node
- #define MY_REPEATER_FEATURE
- // Define radio wait time between sends
- #define RADIO_PAUSE 100 // This allows the radio to settle between sends, ideally 0...
- // Define end of loop pause time
- #define LOOP_PAUSE 30000
- // Define time between sensors blocks
- #define SENSORS_DELAY 100 // This allows sensor VCC to settle between readings, ideally 0...
- #include <SPI.h>
- #include <MySensor.h>
- #include <BH1750.h>
- #include <NewPing.h>
- #include <Adafruit_NeoPixel.h>
- #include <elapsedMillis.h>
- #define NEO_PIN 2
- #define NUM_LEDS 8
- Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(NUM_LEDS, NEO_PIN, NEO_GRB + NEO_KHZ800);
- // Set moisture mode to either digital (D) or analog (A)
- #define MOISTURE_MODE_A
- #ifdef MOISTURE_MODE_D
- // Digital input pin moisture sensor
- #define DIGITAL_INPUT_MOISTURE 6
- #endif
- #ifdef MOISTURE_MODE_A
- // Analog input pin moisture sensor
- #define ANALOG_INPUT_MOISTURE A0
- // Define moisture upper limit
- int moistureLimit = 400;
- // Moisture reading derived from analog value
- int moistureValue = -1;
- // Analog smoothing
- const int numReadings = 10; // The number of samples to keep track of
- int readings[numReadings]; // The readings from the analog input
- int readIndex = 0; // The index of the current reading
- int total = 0; // The running total
- int average = 0; // The Average
- #endif
- // Power pin moisture sensor
- #define MOISTURE_POWER_PIN 5
- // Send only if changed? 1 = Yes 0 = No
- #define COMPARE_MOISTURE 0
- // Store last moisture reading for comparison
- int lastMoistureValue = -1;
- // Power pin rain sensor
- #define RAIN_POWER_PIN 7
- // Digital input pin rain sensor
- #define DIGITAL_INPUT_RAIN 8
- // Send only if changed? 1 = Yes 0 = No
- #define COMPARE_RAIN 0
- // Store last rain reading for comparison
- int lastRainValue = -1;
- // Ultrasonic trigger pin
- #define TRIGGER_PIN 4
- // Ultrasonic echo pin
- #define ECHO_PIN 3
- // Maximum distance we want to ping for (in cms), maximum sensor distance is rated at 400-500cm
- #define MAX_DISTANCE 300
- // NewPing setup of pins and maximum distance
- NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
- // Send only if changed? 1 = Yes 0 = No
- #define COMPARE_DIST 0
- // Store last distance reading for comparison
- int lastDist = -1;
- // Set BH1750 name
- BH1750 lightSensor;
- // Send only if changed? 1 = Yes 0 = No
- #define COMPARE_LUX 0
- // Store last LUX reading for comparison
- uint16_t lastlux = -1;
- // Landroid settings
- boolean landroidWaiting = false;
- boolean landroidWaitingTriggered = false;
- boolean landroidHome = false;
- elapsedMillis timeElapsed;
- // Landroid timers
- #define TIMER1 3200000 // 60 minutes * 60 seconds * 1000 millis = 3200000
- #define TIMER2 7200000 // 120 minutes * 60 seconds * 1000 millis = 7200000
- #define TIMER3 10800000 // 180 minutes * 60 seconds * 1000 millis = 10800000
- #define TIMER4 14400000 // 240 minutes * 60 seconds * 1000 millis = 14400000
- // Set default gateway value for metric or imperial
- boolean metric = true;
- // Define sensor children IDs for MySensors
- #define CHILD_ID1 1 // ID of the sensor child (Moisture Status)
- #ifdef MOISTURE_MODE_A
- #define CHILD_ID2 2 // ID of the sensor child (Moisture Analog Reading)
- #endif
- #define CHILD_ID3 3 // ID of the sensor child (Rain Status)
- #define CHILD_ID4 4 // ID of the sensor child (Light)
- #define CHILD_ID5 5 // ID of the sensor child (Distance)
- #define CHILD_ID10 10 // ID of the sensor child (Landroid home boolean)
- #define CHILD_ID11 11 // ID of the sensor child (Landroid waiting boolean)
- #define CHILD_ID12 12 // ID of the sensor child (Landroid time elapsed)
- // Define MySensors message types
- MyMessage msg1(CHILD_ID1, V_TRIPPED); // Setup message
- #ifdef MOISTURE_MODE_A
- MyMessage msg2(CHILD_ID2, V_CUSTOM); // Setup message
- #endif
- MyMessage msg3(CHILD_ID3, V_TRIPPED); // Setup message
- MyMessage msg4(CHILD_ID4, V_LEVEL); // Setup message
- MyMessage msg5(CHILD_ID5, V_DISTANCE); // Setup message
- MyMessage msg10(CHILD_ID10, V_TRIPPED); // Setup message
- MyMessage msg11(CHILD_ID11, V_TRIPPED); // Setup message
- MyMessage msg12(CHILD_ID12, V_CUSTOM); // Setup message
- void setup()
- {
- // Send the sketch version information to the gateway and Controller
- sendSketchInfo("MowerGarage", "1.8");
- wait(RADIO_PAUSE);
- // Register all sensors to the gateway (they will be created as child devices)
- present(CHILD_ID1, S_MOTION);
- wait(RADIO_PAUSE);
- #ifdef MOISTURE_MODE_A
- present(CHILD_ID2, S_CUSTOM);
- wait(RADIO_PAUSE);
- #endif
- present(CHILD_ID3, S_MOTION);
- wait(RADIO_PAUSE);
- present(CHILD_ID4, S_LIGHT_LEVEL);
- wait(RADIO_PAUSE);
- present(CHILD_ID5, S_DISTANCE);
- wait(RADIO_PAUSE);
- present(CHILD_ID10, S_MOTION);
- wait(RADIO_PAUSE);
- present(CHILD_ID11, S_MOTION);
- wait(RADIO_PAUSE);
- present(CHILD_ID12, S_CUSTOM);
- wait(RADIO_PAUSE);
- #ifdef MOISTURE_MODE_D
- // Set the moisture sensor digital pin as input
- pinMode(DIGITAL_INPUT_MOISTURE, INPUT);
- #endif
- // Set the rain sensor digital pin as input
- pinMode(DIGITAL_INPUT_RAIN, INPUT);
- // Set the moisture sensor power pin as output
- pinMode(MOISTURE_POWER_PIN, OUTPUT);
- // Set the rain sensor power pin as output
- pinMode(RAIN_POWER_PIN, OUTPUT);
- // Set to LOW so no power is flowing through the moisture sensor
- digitalWrite(MOISTURE_POWER_PIN, LOW);
- // Set to LOW so no power is flowing through the rain sensor
- digitalWrite(RAIN_POWER_PIN, LOW);
- // Check gateway for metric setting
- boolean metric = getConfig().isMetric;
- // Start BH1750 light sensor
- lightSensor.begin();
- // Start NeoPixel LED strip
- strip1.begin();
- // Initialise all Neopixel LEDs off
- strip1.show();
- }
- void loop()
- {
- #ifdef MOISTURE_MODE_D
- //--- Digital Moisture sensor ---//
- digitalWrite(MOISTURE_POWER_PIN, HIGH); // Turn moisture power pin on
- wait(200); // Set a delay to ensure the moisture sensor has powered up
- int moistureValue = digitalRead(DIGITAL_INPUT_MOISTURE); // Read digital moisture value
- digitalWrite(MOISTURE_POWER_PIN, LOW); // Turn moisture power pin off
- #if COMPARE_MOISTURE == 1
- if (moistureValue != lastMoistureValue)
- #endif
- {
- #ifdef MY_DEBUG
- Serial.print("Moisture: ");
- Serial.println(moistureValue == 0 ? 1 : 0);
- #endif
- send(msg1.set(moistureValue == 0 ? 1 : 0)); // Send the inverse
- wait(RADIO_PAUSE);
- lastMoistureValue = moistureValue; // For testing can be 0 or 1 or back to moistureValue
- }
- #endif
- #ifdef MOISTURE_MODE_A
- //--- Analog Moisture sensor ---//
- total = total - readings[readIndex]; // Subtract the last smoothing reading
- digitalWrite(MOISTURE_POWER_PIN, HIGH); // Turn moisture power pin on
- wait(200); // Set a delay to ensure the moisture sensor has powered up
- readings[readIndex] = analogRead(ANALOG_INPUT_MOISTURE); // Read analog moisture value
- digitalWrite(MOISTURE_POWER_PIN, LOW); // Turn moisture power pin off
- total = total + readings[readIndex]; // Add the reading to the smoothing total
- readIndex = readIndex + 1; // Advance to the next position in the smoothing array
- if (readIndex >= numReadings) // If we're at the end of the array...
- {
- readIndex = 0; // Wrap around to the beginning
- }
- average = total / numReadings;
- average = map(average, 0, 1023, 1023, 0);
- if (average <= moistureLimit)
- {
- moistureValue = 1;
- }
- else
- {
- moistureValue = 0;
- }
- #if COMPARE_MOISTURE == 1
- if (moistureValue != lastMoistureValue)
- #endif
- {
- #ifdef MY_DEBUG
- Serial.print("Moisture: ");
- Serial.println(moistureValue);
- Serial.print("Moisture: ");
- Serial.println(average);
- #endif
- {
- send(msg1.set(moistureValue == 0 ? 1 : 0));
- wait(RADIO_PAUSE);
- send(msg2.set(average));
- wait(RADIO_PAUSE);
- lastMoistureValue = moistureValue; // For testing can be 0 or 1 or back to moistureValue
- }
- }
- #endif
- wait(SENSORS_DELAY); // Wait between sensor readings, seems to help reliability of readings
- //--- Rain sensor ---//
- digitalWrite(RAIN_POWER_PIN, HIGH); // Turn rain power pin on
- wait(200); // Set a delay to ensure the moisture sensor has powered up
- int rainValue = digitalRead(DIGITAL_INPUT_RAIN); // Read digital rain value
- digitalWrite(RAIN_POWER_PIN, LOW); // Turn rain power pin off
- #if COMPARE_RAIN == 1
- if (rainValue != lastRainValue) // Check value against saved value
- #endif
- {
- #ifdef MY_DEBUG
- Serial.print("Rain: ");
- Serial.println(rainValue == 0 ? 1 : 0);
- #endif
- send(msg3.set(rainValue == 0 ? 1 : 0)); // Send the inverse
- wait(RADIO_PAUSE);
- lastRainValue = rainValue; // For testing can be 0 or 1 or back to rainValue
- }
- wait(SENSORS_DELAY); // Wait between sensor readings, seems to help reliability of readings
- //--- Light sensor ---//
- uint16_t lux = lightSensor.readLightLevel(); // Get Lux value
- #if COMPARE_LUX == 1
- if (lux != lastlux)
- #endif
- {
- #ifdef MY_DEBUG
- Serial.print("LUX: ");
- Serial.println(lux);
- #endif
- send(msg4.set(lux));
- wait(RADIO_PAUSE);
- lastlux = lux;
- }
- wait(SENSORS_DELAY); // Wait between sensor readings, seems to help reliability of readings
- //--- Distance sensor ---//
- int dist = metric ? sonar.ping_cm() : sonar.ping_in();
- #if COMPARE_DIST == 1
- if (dist != lastDist)
- #endif
- {
- #ifdef MY_DEBUG
- Serial.print("Distance: ");
- Serial.print(dist); // Convert ping time to distance in cm and print result (0 = outside set distance range)
- Serial.println(metric ? " cm" : " in");
- #endif
- send(msg5.set(dist));
- wait(RADIO_PAUSE);
- lastDist = dist;
- }
- //--- Analyse readings, set Neopixels, booleans, and send gateway status messages ---//
- if (lastMoistureValue == 0 || lastRainValue == 0)
- {
- landroidWaiting = true;
- landroidWaitingTriggered = true;
- timeElapsed = 0;
- strip1.setPixelColor(0, 255, 0, 0);
- strip1.setPixelColor(1, 255, 0, 0);
- strip1.setPixelColor(2, 255, 0, 0);
- strip1.setPixelColor(3, 255, 0, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.print("Rain or moisture detected, waiting: ");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- #endif
- }
- else
- {
- landroidWaiting = false;
- #ifdef MY_DEBUG
- Serial.print("No rain or moisture detected, not waiting: ");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- #endif
- }
- if ( landroidWaiting == false && landroidWaitingTriggered == false )
- {
- strip1.setPixelColor(0, 0, 127, 0);
- strip1.setPixelColor(1, 0, 127, 0);
- strip1.setPixelColor(2, 0, 127, 0);
- strip1.setPixelColor(3, 0, 127, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.print("Waiting on normal schedule: ");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- #endif
- }
- if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed < TIMER1 ) // Logic for timer trigger
- {
- strip1.setPixelColor(0, 255, 0, 0);
- strip1.setPixelColor(1, 255, 0, 0);
- strip1.setPixelColor(2, 255, 0, 0);
- strip1.setPixelColor(3, 255, 0, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.print("4 Hours Left: ");
- Serial.println("4 LEDs");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- Serial.print("Time elapsed: ");
- Serial.println(timeElapsed / 1000);
- #endif
- }
- if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER1 ) // Logic for timer trigger
- {
- strip1.setPixelColor(0, 0, 0, 0);
- strip1.setPixelColor(1, 255, 0, 0);
- strip1.setPixelColor(2, 255, 0, 0);
- strip1.setPixelColor(3, 255, 0, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.print("3 Hours Left: ");
- Serial.println("3 LEDs");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- Serial.print("Time elapsed: ");
- Serial.println(timeElapsed / 1000);
- #endif
- }
- if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER2 ) // Logic for timer trigger
- {
- strip1.setPixelColor(0, 0, 0, 0);
- strip1.setPixelColor(1, 0, 0, 0);
- strip1.setPixelColor(2, 255, 0, 0);
- strip1.setPixelColor(3, 255, 0, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.print("2 Hours Left: ");
- Serial.println("2 LEDs");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- Serial.print("Time elapsed: ");
- Serial.println(timeElapsed / 1000);
- #endif
- }
- if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER3 ) // Logic for timer trigger
- {
- strip1.setPixelColor(0, 0, 0, 0);
- strip1.setPixelColor(1, 0, 0, 0);
- strip1.setPixelColor(2, 0, 0, 0);
- strip1.setPixelColor(3, 255, 0, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.print("1 Hour Left: ");
- Serial.println("1 LEDs");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- Serial.print("Time elapsed: ");
- Serial.println(timeElapsed / 1000);
- #endif
- }
- if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER4 ) // Logic for timer trigger
- {
- landroidWaitingTriggered = false;
- strip1.setPixelColor(0, 0, 127, 0);
- strip1.setPixelColor(1, 0, 127, 0);
- strip1.setPixelColor(2, 0, 127, 0);
- strip1.setPixelColor(3, 0, 127, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.print("4 Hours Passed: ");
- Serial.println("It's no longer wet! Waiting on normal schedule");
- Serial.print("Status");
- Serial.print("(");
- Serial.print(landroidWaiting);
- Serial.println(")");
- Serial.print("Time elapsed: ");
- Serial.println(timeElapsed / 1000);
- #endif
- }
- if (lastDist < 30)
- {
- landroidHome = true;
- strip1.setPixelColor(4, 0, 127, 0);
- strip1.setPixelColor(5, 0, 127, 0);
- strip1.setPixelColor(6, 0, 127, 0);
- strip1.setPixelColor(7, 0, 127, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.println("Home charging");
- #endif
- }
- else
- {
- landroidHome = false;
- strip1.setPixelColor(4, 255, 0, 0);
- strip1.setPixelColor(5, 255, 0, 0);
- strip1.setPixelColor(6, 255, 0, 0);
- strip1.setPixelColor(7, 255, 0, 0);
- strip1.show();
- #ifdef MY_DEBUG
- Serial.println("Cutting the grass!");
- #endif
- }
- // Send Landroid home status to gateway
- #ifdef MY_DEBUG
- Serial.print("Sending landroidHome ");
- Serial.print("(");
- Serial.print(landroidHome);
- Serial.print(")");
- Serial.print(" status: ");
- #endif
- send(msg10.set(landroidHome));
- wait(RADIO_PAUSE);
- // Send Landroid waiting status to gateway
- #ifdef MY_DEBUG
- Serial.print("Sending landroidWaitingTriggered ");
- Serial.print("(");
- Serial.print(landroidWaitingTriggered);
- Serial.print(")");
- Serial.print(" status: ");
- #endif
- send(msg11.set(landroidWaitingTriggered));
- wait(RADIO_PAUSE);
- // Send Landroid waiting timer status to gateway
- if ( landroidWaitingTriggered == true && timeElapsed > LOOP_PAUSE && timeElapsed < TIMER4)
- {
- #ifdef MY_DEBUG
- Serial.print("Sending timeElapsed ");
- Serial.print("(");
- Serial.print(timeElapsed / 1000);
- Serial.print(")");
- Serial.print(" status: ");
- #endif
- send(msg12.set(timeElapsed / 1000));
- wait(RADIO_PAUSE);
- }
- else
- {
- #ifdef MY_DEBUG
- Serial.print("Sending timeElapsed ");
- Serial.print("(");
- Serial.print(0);
- Serial.print(")");
- Serial.print(" status: ");
- #endif
- send(msg12.set(0));
- wait(RADIO_PAUSE);
- }
- wait(LOOP_PAUSE); // Sleep or wait (repeater)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement