Advertisement
Guest User

Untitled

a guest
Apr 30th, 2016
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.27 KB | None | 0 0
  1. /*
  2.   REVISION HISTORY
  3.   Created by Mark Swift
  4.   V1.4 - Reversed waiting LED logic.
  5.   V1.5 - Added analog moisture option.
  6.   V1.6 - Added analog moisture reading gateway message
  7.   V1.7 - Added analog smoothing
  8.   V1.8 - Shortened Sketch Name (Prevent send presentation errors)
  9. */
  10.  
  11. // Enable debug prints
  12. #define MY_DEBUG
  13.  
  14. // Required for MQTT as gateway does not automagically assign ID's
  15. #define MY_NODE_ID 3
  16.  
  17. // Set parent node ID manually
  18. #define MY_PARENT_NODE_ID 0
  19.  
  20. // Enable and select radio type attached
  21. #define MY_RADIO_NRF24
  22. // #define MY_RADIO_RFM69
  23.  
  24. // Set RF24L01 channel number
  25. #define MY_RF24_CHANNEL 125
  26.  
  27. // Enabled repeater feature for this node
  28. #define MY_REPEATER_FEATURE
  29.  
  30. // Define radio wait time between sends
  31. #define RADIO_PAUSE 100 // This allows the radio to settle between sends, ideally 0...
  32.  
  33. // Define end of loop pause time
  34. #define LOOP_PAUSE 30000
  35.  
  36. // Define time between sensors blocks
  37. #define SENSORS_DELAY 100  // This allows sensor VCC to settle between readings, ideally 0...
  38.  
  39. #include <SPI.h>
  40. #include <MySensor.h>
  41. #include <BH1750.h>
  42. #include <NewPing.h>
  43. #include <Adafruit_NeoPixel.h>
  44. #include <elapsedMillis.h>
  45.  
  46. #define NEO_PIN 2
  47. #define NUM_LEDS 8
  48. Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(NUM_LEDS, NEO_PIN, NEO_GRB + NEO_KHZ800);
  49.  
  50. // Set moisture mode to either digital (D) or analog (A)
  51. #define MOISTURE_MODE_A
  52.  
  53. #ifdef MOISTURE_MODE_D
  54. // Digital input pin moisture sensor
  55. #define DIGITAL_INPUT_MOISTURE 6
  56. #endif
  57.  
  58. #ifdef MOISTURE_MODE_A
  59. // Analog input pin moisture sensor
  60. #define ANALOG_INPUT_MOISTURE A0
  61. // Define moisture upper limit
  62. int moistureLimit = 400;
  63. // Moisture reading derived from analog value
  64. int moistureValue = -1;
  65. // Analog smoothing
  66. const int numReadings = 10; // The number of samples to keep track of
  67. int readings[numReadings]; // The readings from the analog input
  68. int readIndex = 0; // The index of the current reading
  69. int total = 0; // The running total
  70. int average = 0; // The Average
  71. #endif
  72.  
  73. // Power pin moisture sensor
  74. #define MOISTURE_POWER_PIN 5
  75. // Send only if changed? 1 = Yes 0 = No
  76. #define COMPARE_MOISTURE 0
  77. // Store last moisture reading for comparison
  78. int lastMoistureValue = -1;
  79.  
  80. // Power pin rain sensor
  81. #define RAIN_POWER_PIN 7
  82. // Digital input pin rain sensor
  83. #define DIGITAL_INPUT_RAIN 8
  84. // Send only if changed? 1 = Yes 0 = No
  85. #define COMPARE_RAIN 0
  86. // Store last rain reading for comparison
  87. int lastRainValue = -1;
  88.  
  89. // Ultrasonic trigger pin
  90. #define TRIGGER_PIN 4
  91. // Ultrasonic echo pin
  92. #define ECHO_PIN 3
  93. // Maximum distance we want to ping for (in cms), maximum sensor distance is rated at 400-500cm
  94. #define MAX_DISTANCE 300
  95. // NewPing setup of pins and maximum distance
  96. NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
  97. // Send only if changed? 1 = Yes 0 = No
  98. #define COMPARE_DIST 0
  99. // Store last distance reading for comparison
  100. int lastDist = -1;
  101.  
  102. // Set BH1750 name
  103. BH1750 lightSensor;
  104. // Send only if changed? 1 = Yes 0 = No
  105. #define COMPARE_LUX 0
  106. // Store last LUX reading for comparison
  107. uint16_t lastlux = -1;
  108.  
  109. // Landroid settings
  110. boolean landroidWaiting = false;
  111. boolean landroidWaitingTriggered = false;
  112. boolean landroidHome = false;
  113. elapsedMillis timeElapsed;
  114.  
  115. // Landroid timers
  116. #define TIMER1 3200000 // 60 minutes * 60 seconds * 1000 millis = 3200000
  117. #define TIMER2 7200000 // 120 minutes * 60 seconds * 1000 millis = 7200000
  118. #define TIMER3 10800000 // 180 minutes * 60 seconds * 1000 millis = 10800000
  119. #define TIMER4 14400000 // 240 minutes * 60 seconds * 1000 millis = 14400000
  120.  
  121. // Set default gateway value for metric or imperial
  122. boolean metric = true;
  123.  
  124. // Define sensor children IDs for MySensors
  125. #define CHILD_ID1 1 // ID of the sensor child (Moisture Status)
  126. #ifdef MOISTURE_MODE_A
  127. #define CHILD_ID2 2 // ID of the sensor child (Moisture Analog Reading)
  128. #endif
  129. #define CHILD_ID3 3 // ID of the sensor child (Rain Status)
  130. #define CHILD_ID4 4 // ID of the sensor child (Light)
  131. #define CHILD_ID5 5 // ID of the sensor child (Distance)
  132. #define CHILD_ID10 10 // ID of the sensor child (Landroid home boolean)
  133. #define CHILD_ID11 11 // ID of the sensor child (Landroid waiting boolean)
  134. #define CHILD_ID12 12 // ID of the sensor child (Landroid time elapsed)
  135.  
  136. // Define MySensors message types
  137. MyMessage msg1(CHILD_ID1, V_TRIPPED); // Setup message
  138. #ifdef MOISTURE_MODE_A
  139. MyMessage msg2(CHILD_ID2, V_CUSTOM); // Setup message
  140. #endif
  141. MyMessage msg3(CHILD_ID3, V_TRIPPED); // Setup message
  142. MyMessage msg4(CHILD_ID4, V_LEVEL); // Setup message
  143. MyMessage msg5(CHILD_ID5, V_DISTANCE); // Setup message
  144. MyMessage msg10(CHILD_ID10, V_TRIPPED); // Setup message
  145. MyMessage msg11(CHILD_ID11, V_TRIPPED); // Setup message
  146. MyMessage msg12(CHILD_ID12, V_CUSTOM); // Setup message
  147.  
  148. void setup()
  149. {
  150.   // Send the sketch version information to the gateway and Controller
  151.   sendSketchInfo("MowerGarage", "1.8");
  152.   wait(RADIO_PAUSE);
  153.   // Register all sensors to the gateway (they will be created as child devices)
  154.   present(CHILD_ID1, S_MOTION);
  155.   wait(RADIO_PAUSE);
  156. #ifdef MOISTURE_MODE_A
  157.   present(CHILD_ID2, S_CUSTOM);
  158.   wait(RADIO_PAUSE);
  159. #endif
  160.   present(CHILD_ID3, S_MOTION);
  161.   wait(RADIO_PAUSE);
  162.   present(CHILD_ID4, S_LIGHT_LEVEL);
  163.   wait(RADIO_PAUSE);
  164.   present(CHILD_ID5, S_DISTANCE);
  165.   wait(RADIO_PAUSE);
  166.   present(CHILD_ID10, S_MOTION);
  167.   wait(RADIO_PAUSE);
  168.   present(CHILD_ID11, S_MOTION);
  169.   wait(RADIO_PAUSE);
  170.   present(CHILD_ID12, S_CUSTOM);
  171.   wait(RADIO_PAUSE);
  172. #ifdef MOISTURE_MODE_D
  173.   // Set the moisture sensor digital pin as input
  174.   pinMode(DIGITAL_INPUT_MOISTURE, INPUT);
  175. #endif
  176.   // Set the rain sensor digital pin as input
  177.   pinMode(DIGITAL_INPUT_RAIN, INPUT);
  178.   // Set the moisture sensor power pin as output
  179.   pinMode(MOISTURE_POWER_PIN, OUTPUT);
  180.   // Set the rain sensor power pin as output
  181.   pinMode(RAIN_POWER_PIN, OUTPUT);
  182.   // Set to LOW so no power is flowing through the moisture sensor
  183.   digitalWrite(MOISTURE_POWER_PIN, LOW);
  184.   // Set to LOW so no power is flowing through the rain sensor
  185.   digitalWrite(RAIN_POWER_PIN, LOW);
  186.   // Check gateway for metric setting
  187.   boolean metric = getConfig().isMetric;
  188.   // Start BH1750 light sensor
  189.   lightSensor.begin();
  190.   // Start NeoPixel LED strip
  191.   strip1.begin();
  192.   // Initialise all Neopixel LEDs off
  193.   strip1.show();
  194. }
  195.  
  196. void loop()
  197. {
  198. #ifdef MOISTURE_MODE_D
  199.   //--- Digital Moisture sensor ---//
  200.   digitalWrite(MOISTURE_POWER_PIN, HIGH); // Turn moisture power pin on
  201.   wait(200); // Set a delay to ensure the moisture sensor has powered up
  202.   int moistureValue = digitalRead(DIGITAL_INPUT_MOISTURE); // Read digital moisture value
  203.   digitalWrite(MOISTURE_POWER_PIN, LOW); // Turn moisture power pin off
  204. #if COMPARE_MOISTURE == 1
  205.   if (moistureValue != lastMoistureValue)
  206. #endif
  207.   {
  208. #ifdef MY_DEBUG
  209.     Serial.print("Moisture: ");
  210.     Serial.println(moistureValue == 0 ? 1 : 0);
  211. #endif
  212.     send(msg1.set(moistureValue == 0 ? 1 : 0)); // Send the inverse
  213.     wait(RADIO_PAUSE);
  214.     lastMoistureValue = moistureValue; // For testing can be 0 or 1 or back to moistureValue
  215.   }
  216. #endif
  217.  
  218. #ifdef MOISTURE_MODE_A
  219.   //--- Analog Moisture sensor ---//
  220.   total = total - readings[readIndex]; // Subtract the last smoothing reading
  221.   digitalWrite(MOISTURE_POWER_PIN, HIGH); // Turn moisture power pin on
  222.   wait(200); // Set a delay to ensure the moisture sensor has powered up
  223.   readings[readIndex] = analogRead(ANALOG_INPUT_MOISTURE); // Read analog moisture value
  224.   digitalWrite(MOISTURE_POWER_PIN, LOW); // Turn moisture power pin off
  225.   total = total + readings[readIndex]; // Add the reading to the smoothing total
  226.   readIndex = readIndex + 1; // Advance to the next position in the smoothing array
  227.   if (readIndex >= numReadings) // If we're at the end of the array...
  228.   {
  229.     readIndex = 0; // Wrap around to the beginning
  230.   }
  231.   average = total / numReadings;
  232.   average = map(average, 0, 1023, 1023, 0);
  233.   if (average <= moistureLimit)
  234.   {
  235.     moistureValue = 1;
  236.   }
  237.   else
  238.   {
  239.     moistureValue = 0;
  240.   }
  241. #if COMPARE_MOISTURE == 1
  242.   if (moistureValue != lastMoistureValue)
  243. #endif
  244.   {
  245. #ifdef MY_DEBUG
  246.     Serial.print("Moisture: ");
  247.     Serial.println(moistureValue);
  248.     Serial.print("Moisture: ");
  249.     Serial.println(average);
  250. #endif
  251.     {
  252.       send(msg1.set(moistureValue == 0 ? 1 : 0));
  253.       wait(RADIO_PAUSE);
  254.       send(msg2.set(average));
  255.       wait(RADIO_PAUSE);
  256.       lastMoistureValue = moistureValue; // For testing can be 0 or 1 or back to moistureValue
  257.     }
  258.   }
  259. #endif
  260.  
  261.   wait(SENSORS_DELAY); // Wait between sensor readings, seems to help reliability of readings
  262.  
  263.   //--- Rain sensor ---//
  264.   digitalWrite(RAIN_POWER_PIN, HIGH); // Turn rain power pin on
  265.   wait(200); // Set a delay to ensure the moisture sensor has powered up
  266.   int rainValue = digitalRead(DIGITAL_INPUT_RAIN); // Read digital rain value
  267.   digitalWrite(RAIN_POWER_PIN, LOW); // Turn rain power pin off
  268. #if COMPARE_RAIN == 1
  269.   if (rainValue != lastRainValue) // Check value against saved value
  270. #endif
  271.   {
  272. #ifdef MY_DEBUG
  273.     Serial.print("Rain: ");
  274.     Serial.println(rainValue == 0 ? 1 : 0);
  275. #endif
  276.     send(msg3.set(rainValue == 0 ? 1 : 0)); // Send the inverse
  277.     wait(RADIO_PAUSE);
  278.     lastRainValue = rainValue; // For testing can be 0 or 1 or back to rainValue
  279.   }
  280.  
  281.   wait(SENSORS_DELAY); // Wait between sensor readings, seems to help reliability of readings
  282.  
  283.   //--- Light sensor ---//
  284.   uint16_t lux = lightSensor.readLightLevel(); // Get Lux value
  285. #if COMPARE_LUX == 1
  286.   if (lux != lastlux)
  287. #endif
  288.   {
  289. #ifdef MY_DEBUG
  290.     Serial.print("LUX: ");
  291.     Serial.println(lux);
  292. #endif
  293.     send(msg4.set(lux));
  294.     wait(RADIO_PAUSE);
  295.     lastlux = lux;
  296.   }
  297.  
  298.   wait(SENSORS_DELAY); // Wait between sensor readings, seems to help reliability of readings
  299.  
  300.   //--- Distance sensor ---//
  301.   int dist = metric ? sonar.ping_cm() : sonar.ping_in();
  302. #if COMPARE_DIST == 1
  303.   if (dist != lastDist)
  304. #endif
  305.   {
  306. #ifdef MY_DEBUG
  307.     Serial.print("Distance: ");
  308.     Serial.print(dist); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  309.     Serial.println(metric ? " cm" : " in");
  310. #endif
  311.     send(msg5.set(dist));
  312.     wait(RADIO_PAUSE);
  313.     lastDist = dist;
  314.   }
  315.  
  316.   //--- Analyse readings, set Neopixels, booleans, and send gateway status messages ---//
  317.   if (lastMoistureValue == 0 || lastRainValue == 0)
  318.   {
  319.     landroidWaiting = true;
  320.     landroidWaitingTriggered = true;
  321.     timeElapsed = 0;
  322.     strip1.setPixelColor(0, 255, 0, 0);
  323.     strip1.setPixelColor(1, 255, 0, 0);
  324.     strip1.setPixelColor(2, 255, 0, 0);
  325.     strip1.setPixelColor(3, 255, 0, 0);
  326.     strip1.show();
  327. #ifdef MY_DEBUG
  328.     Serial.print("Rain or moisture detected, waiting: ");
  329.     Serial.print("Status");
  330.     Serial.print("(");
  331.     Serial.print(landroidWaiting);
  332.     Serial.println(")");
  333. #endif
  334.   }
  335.  
  336.   else
  337.   {
  338.     landroidWaiting = false;
  339. #ifdef MY_DEBUG
  340.     Serial.print("No rain or moisture detected, not waiting: ");
  341.     Serial.print("Status");
  342.     Serial.print("(");
  343.     Serial.print(landroidWaiting);
  344.     Serial.println(")");
  345. #endif
  346.   }
  347.  
  348.   if ( landroidWaiting == false && landroidWaitingTriggered == false )
  349.   {
  350.     strip1.setPixelColor(0, 0, 127, 0);
  351.     strip1.setPixelColor(1, 0, 127, 0);
  352.     strip1.setPixelColor(2, 0, 127, 0);
  353.     strip1.setPixelColor(3, 0, 127, 0);
  354.     strip1.show();
  355. #ifdef MY_DEBUG
  356.     Serial.print("Waiting on normal schedule: ");
  357.     Serial.print("Status");
  358.     Serial.print("(");
  359.     Serial.print(landroidWaiting);
  360.     Serial.println(")");
  361. #endif
  362.   }
  363.  
  364.   if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed < TIMER1 ) // Logic for timer trigger
  365.   {
  366.     strip1.setPixelColor(0, 255, 0, 0);
  367.     strip1.setPixelColor(1, 255, 0, 0);
  368.     strip1.setPixelColor(2, 255, 0, 0);
  369.     strip1.setPixelColor(3, 255, 0, 0);
  370.     strip1.show();
  371. #ifdef MY_DEBUG
  372.     Serial.print("4 Hours Left: ");
  373.     Serial.println("4 LEDs");
  374.     Serial.print("Status");
  375.     Serial.print("(");
  376.     Serial.print(landroidWaiting);
  377.     Serial.println(")");
  378.     Serial.print("Time elapsed: ");
  379.     Serial.println(timeElapsed / 1000);
  380. #endif
  381.   }
  382.  
  383.   if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER1 ) // Logic for timer trigger
  384.   {
  385.     strip1.setPixelColor(0, 0, 0, 0);
  386.     strip1.setPixelColor(1, 255, 0, 0);
  387.     strip1.setPixelColor(2, 255, 0, 0);
  388.     strip1.setPixelColor(3, 255, 0, 0);
  389.     strip1.show();
  390. #ifdef MY_DEBUG
  391.     Serial.print("3 Hours Left: ");
  392.     Serial.println("3 LEDs");
  393.     Serial.print("Status");
  394.     Serial.print("(");
  395.     Serial.print(landroidWaiting);
  396.     Serial.println(")");
  397.     Serial.print("Time elapsed: ");
  398.     Serial.println(timeElapsed / 1000);
  399. #endif
  400.   }
  401.  
  402.   if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER2 ) // Logic for timer trigger
  403.   {
  404.     strip1.setPixelColor(0, 0, 0, 0);
  405.     strip1.setPixelColor(1, 0, 0, 0);
  406.     strip1.setPixelColor(2, 255, 0, 0);
  407.     strip1.setPixelColor(3, 255, 0, 0);
  408.     strip1.show();
  409. #ifdef MY_DEBUG
  410.     Serial.print("2 Hours Left: ");
  411.     Serial.println("2 LEDs");
  412.     Serial.print("Status");
  413.     Serial.print("(");
  414.     Serial.print(landroidWaiting);
  415.     Serial.println(")");
  416.     Serial.print("Time elapsed: ");
  417.     Serial.println(timeElapsed / 1000);
  418. #endif
  419.   }
  420.  
  421.   if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER3 ) // Logic for timer trigger
  422.   {
  423.     strip1.setPixelColor(0, 0, 0, 0);
  424.     strip1.setPixelColor(1, 0, 0, 0);
  425.     strip1.setPixelColor(2, 0, 0, 0);
  426.     strip1.setPixelColor(3, 255, 0, 0);
  427.     strip1.show();
  428. #ifdef MY_DEBUG
  429.     Serial.print("1 Hour Left: ");
  430.     Serial.println("1 LEDs");
  431.     Serial.print("Status");
  432.     Serial.print("(");
  433.     Serial.print(landroidWaiting);
  434.     Serial.println(")");
  435.     Serial.print("Time elapsed: ");
  436.     Serial.println(timeElapsed / 1000);
  437. #endif
  438.   }
  439.  
  440.   if ( landroidWaiting == false && landroidWaitingTriggered == true && timeElapsed > TIMER4 ) // Logic for timer trigger
  441.   {
  442.     landroidWaitingTriggered = false;
  443.     strip1.setPixelColor(0, 0, 127, 0);
  444.     strip1.setPixelColor(1, 0, 127, 0);
  445.     strip1.setPixelColor(2, 0, 127, 0);
  446.     strip1.setPixelColor(3, 0, 127, 0);
  447.     strip1.show();
  448. #ifdef MY_DEBUG
  449.     Serial.print("4 Hours Passed: ");
  450.     Serial.println("It's no longer wet! Waiting on normal schedule");
  451.     Serial.print("Status");
  452.     Serial.print("(");
  453.     Serial.print(landroidWaiting);
  454.     Serial.println(")");
  455.     Serial.print("Time elapsed: ");
  456.     Serial.println(timeElapsed / 1000);
  457. #endif
  458.   }
  459.  
  460.   if (lastDist < 30)
  461.   {
  462.     landroidHome = true;
  463.     strip1.setPixelColor(4, 0, 127, 0);
  464.     strip1.setPixelColor(5, 0, 127, 0);
  465.     strip1.setPixelColor(6, 0, 127, 0);
  466.     strip1.setPixelColor(7, 0, 127, 0);
  467.     strip1.show();
  468. #ifdef MY_DEBUG
  469.     Serial.println("Home charging");
  470. #endif
  471.   }
  472.  
  473.   else
  474.   {
  475.     landroidHome = false;
  476.     strip1.setPixelColor(4, 255, 0, 0);
  477.     strip1.setPixelColor(5, 255, 0, 0);
  478.     strip1.setPixelColor(6, 255, 0, 0);
  479.     strip1.setPixelColor(7, 255, 0, 0);
  480.     strip1.show();
  481. #ifdef MY_DEBUG
  482.     Serial.println("Cutting the grass!");
  483. #endif
  484.   }
  485.  
  486.   // Send Landroid home status to gateway
  487. #ifdef MY_DEBUG
  488.   Serial.print("Sending landroidHome ");
  489.   Serial.print("(");
  490.   Serial.print(landroidHome);
  491.   Serial.print(")");
  492.   Serial.print(" status: ");
  493. #endif
  494.   send(msg10.set(landroidHome));
  495.   wait(RADIO_PAUSE);
  496.  
  497.   // Send Landroid waiting status to gateway
  498. #ifdef MY_DEBUG
  499.   Serial.print("Sending landroidWaitingTriggered ");
  500.   Serial.print("(");
  501.   Serial.print(landroidWaitingTriggered);
  502.   Serial.print(")");
  503.   Serial.print(" status: ");
  504. #endif
  505.   send(msg11.set(landroidWaitingTriggered));
  506.   wait(RADIO_PAUSE);
  507.  
  508.   // Send Landroid waiting timer status to gateway
  509.   if ( landroidWaitingTriggered == true && timeElapsed > LOOP_PAUSE && timeElapsed < TIMER4)
  510.   {
  511. #ifdef MY_DEBUG
  512.     Serial.print("Sending timeElapsed ");
  513.     Serial.print("(");
  514.     Serial.print(timeElapsed / 1000);
  515.     Serial.print(")");
  516.     Serial.print(" status: ");
  517. #endif
  518.     send(msg12.set(timeElapsed / 1000));
  519.     wait(RADIO_PAUSE);
  520.   }
  521.  
  522.   else
  523.   {
  524. #ifdef MY_DEBUG
  525.     Serial.print("Sending timeElapsed ");
  526.     Serial.print("(");
  527.     Serial.print(0);
  528.     Serial.print(")");
  529.     Serial.print(" status: ");
  530. #endif
  531.     send(msg12.set(0));
  532.     wait(RADIO_PAUSE);
  533.   }
  534.  
  535.   wait(LOOP_PAUSE); // Sleep or wait (repeater)
  536. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement