Navigation

    • Register
    • Login
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. RobKuipers
    3. Posts
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Posts made by RobKuipers

    • RE: 💬 Soil Moisture Sensor

      @dakipro Good to hear you have it up and running. You are correct about the connections.
      Any wire will do, they just have to be close to each other. Enough to bridge the leaking water. As soon as both wires touch the same puddle you will get readings way above zero.
      The sketch can do multiple detectors with just one Arduino; so you could could create separate alarms for both the washer and the dryer 🙂

      posted in Announcements
      RobKuipers
      RobKuipers
    • RE: 💬 Soil Moisture Sensor

      @dakipro the content of header.h is

      typedef struct {
      int digital_input_a;
      int analog_input_a;
      int digital_input_b;
      int analog_input_b;
      int level;
      bool connected;
      } sensorWiring;
      

      Detecting water leakage I would do exactly as you suggested: if you mean eg. to detect a leaking washing machine, it could be monitored by laying the stripped wires parallel on the bottom of a container or tray and put the machine on top of it.
      It should be easy to modify or extend the sketch to implement a binary switch to indicate leakage above a certain moisture threshold.

      Good luck. Please let us know about your progress.
      Rob

      posted in Announcements
      RobKuipers
      RobKuipers
    • RE: 💬 Soil Moisture Sensor

      @peternilsson75 With the sketch I posted back in May, you just need two pieces of conductive wire. No resistor or amplifier needed. 🙂

      posted in Announcements
      RobKuipers
      RobKuipers
    • RE: 💬 Soil Moisture Sensor

      @Ed1500 This is exactly what I've done with the sketch I posted earlier in this thread.
      Use two inputs per sensor. Flip polarity for every reading and then rest in a high impedance state so as not to corrode the measuring rods (just some copper wire in my case). This has the added benefit of using the least power.
      Has been working like a charm for a couple of months now. Still planning to make a couple extra for the garden.

      posted in Announcements
      RobKuipers
      RobKuipers
    • RE: Buy big amount of Arduino nano with FTDI

      @gloob I think Alibaba is meant for larger quantities.

      posted in Hardware
      RobKuipers
      RobKuipers
    • RE: 💬 Soil Moisture Sensor

      My two cents. A soil moisture sensor that requires no extra hardware (not counting electric wire). Highly inspired by everything I've read in this thread. Comments welcome.
      Excuse the long post.

      /*
       Name:		MYS_MoistureSensor.ino
       Created:	5/25/2017 1:04:35 PM
       Author:	Rob
      
       Soil moisture measuring by using stainless steel rods (or any other conductor).
       Probably the simplest project ever, since only a MySensors-node and some wire is needed to set things up.
       
       The sketch alternates current during measuring to prevent corrosion of the rods due to electrolyses.
       Odd readings may occur when starting (eg. increasing soil moisture for no apparent reason), please just allow the electrodes to settle down in the soil.
       No extra hardware needed. 
       
       I use an Arduino Mini 3V3, powered on two AA cells. It is suggested you set the fuses for a lower Brown Out Detection (BOD). But anything goes.
      
       Just tie D4 and A0 together to one rod, and D5 and A1 to another rod. This is sensor one.
       For the second sensor tie D6 and A2 together to one rod, and D7 and A3 to another rod.
       Connect a pushbutton between GND and D3 if you need a button that makes the node report immediately (can be omitted)
      
       Measurement are taken every minute and send to the gateway if different from the previous reading.
       In case of no changes, the node reports itself every four hours.
       The output is between 0 (dry) and 100 (wet).
      
       Can also be used as a depth moisture sensor with three sensor zones; in that case use one (common) long rod and three smaller sensors along
       the height of the rod and configure the sketch accordingly.
      	 sensors[0] = { 4, A0, 5, A1, -1, false };
      	 sensors[1] = { 4, A0, 6, A2, -1, false };
      	 sensors[2] = { 4, A0, 7, A3, -1, false };
      
      */
      
      #include "Header.h"
      
      // Enable debug Serial.prints to serial monitor
      //#define MY_DEBUG 
      
      #if defined MY_DEBUG
      #define Sprintln(a) (Serial.println(a))
      #define Sprint(a) (Serial.print(a))
      #else 
      #define Sprintln(a)
      #define Sprint(a)
      #endif
      
      // Enable and select radio type attached
      #define MY_RADIO_RFM69
      #define MY_RFM69_FREQUENCY RF69_868MHZ
      #define MY_IS_RFM69HW
      
      // Use PA_LOW for RF24+PA (Power Amplifier)
      //#define MY_RF24_PA_LEVEL RF24_PA_LOW
      //#define MY_RF24_PA_LEVEL RF24_PA_MAX
      
      #define MY_NODE_ID 4
      
      #include <MySensors.h>
      
      #define ACK 0        // = false
      #define CHILD_ID 1
      #define REPORTNOWSWITCH_PIN 3    // Arduino Digital I/O pin for button/reed switch (must be an interrupt pin!)
      
      #define NUM_MOISTURE_SENSORS 2
      #define CHILD_ID_TEMPERATURE (CHILD_ID+NUM_MOISTURE_SENSORS+1)
      
      #define SENSOR1_ROD1_DIGITAL 4
      #define SENSOR1_ROD1_ANALOG A0
      #define SENSOR1_ROD2_DIGITAL 5
      #define SENSOR1_ROD2_ANALOG A1
      
      #define SENSOR2_ROD1_DIGITAL 6
      #define SENSOR2_ROD1_ANALOG A2
      #define SENSOR2_ROD2_DIGITAL 7
      #define SENSOR2_ROD2_ANALOG A3
      
      #define SLEEP_IN_MS 60000		// every minute a new measurement
      #define EVERY_15_MINUTES (3600000/4/SLEEP_IN_MS)
      #define EVERY_4_HOURS (3600000*4/SLEEP_IN_MS) 
      #define NUM_READS (int)10		// Number of sensor reads for filtering
      
      int countLoops;
      int8_t interruptedBy = -1;
      int oldBatLevel;
      float oldTemperature;
      
      int output_value;
      
      /// Included in Header.h:
      //typedef struct {
      //	int digital_input_a;
      //	int analog_input_a;
      //	int digital_input_b;
      //	int analog_input_b;
      //	int level;
      //	bool connected;
      //} sensorWiring;
      
      sensorWiring sensors[NUM_MOISTURE_SENSORS];
      
      MyMessage msgMoistureSensor(CHILD_ID, V_LEVEL);
      MyMessage msgChipTemp(CHILD_ID_TEMPERATURE, V_TEMP);
      
      
      void before()
      {
      	// All buttons as input-pullup as per ATMEGA recommendation to use less power (and more safety) 
      	// (http://electronics.stackexchange.com/questions/43460/how-should-unused-i-o-pins-be-configured-on-atmega328p-for-lowest-power-consumpt)
      	for (int i = 1; i <= 8; i++)
      	{
      		pinMode(i, INPUT_PULLUP);
      	}
      
      	// Now explicity set pins as needed
      
      	// Setup report-now switch, activate internal pull-up
      	pinMode(REPORTNOWSWITCH_PIN, INPUT_PULLUP);
      
      	// Initialize sensor variables
      
      	// Connect Digital pin 4 to Analog input A0 and a metal rod
      	// Connect Digital pin 5 to Analog input A1 and another metal rod.
      	sensors[0] = { SENSOR1_ROD1_DIGITAL, SENSOR1_ROD1_ANALOG, SENSOR1_ROD2_DIGITAL, SENSOR1_ROD2_ANALOG, -1, false };
      
      	// Connect Digital pin 6 to Analog input A2 and a metal rod
      	// Connect Digital pin 7 to Analog input A3 and another metal rod.
      	sensors[1] = { SENSOR2_ROD1_DIGITAL, SENSOR2_ROD1_ANALOG, SENSOR2_ROD2_DIGITAL, SENSOR2_ROD2_ANALOG, -1, false };
      
      	for  (int i = 0; i<NUM_MOISTURE_SENSORS; i++)
      		sensors[i].connected = testSensorConnections(sensors[i]);
      }
      
      void setup()
      {
      
      }
      
      
      void presentation() {
      	sendSketchInfo("Moisture Sensor", "1.1", ACK);
      
      	for (int i = 0; i < NUM_MOISTURE_SENSORS; i++)
      	{
      		if (sensors[i].connected) present(CHILD_ID+i, S_MOISTURE, ACK);
      	}
      	present(CHILD_ID_TEMPERATURE, S_TEMP);
      }
      
      void loop()
      {
      	bool reportNow = (interruptedBy == digitalPinToInterrupt(REPORTNOWSWITCH_PIN));
      
      	if (reportNow)
      	{
      		// Little trick for debouncing the switch
      		attachInterrupt(digitalPinToInterrupt(REPORTNOWSWITCH_PIN), debounce, RISING);
      		wait(500);
      
      		Sprintln(F("Report now switch pressed"));
      		countLoops = 0;
      
      	}
      
      	for (int i = 0; i < NUM_MOISTURE_SENSORS; i++)
      	{
      		if (sensors[i].connected)
      		{
      			output_value = measure(sensors[i]);
      			if ((sensors[i].level != output_value) || reportNow)
      			{
      				sensors[i].level = output_value;
      				send(msgMoistureSensor.setSensor(CHILD_ID+i).set(output_value), ACK);
      			}
      		}
      	}
      
      	// Every fifteen minutes; poll temperature
      	if (countLoops%EVERY_15_MINUTES==0 || reportNow) 
      	{
      		float newTemp = readTemp();
      		if (oldTemperature != newTemp || reportNow)
      		{
      			send(msgChipTemp.set(newTemp, 1), ACK);
      			oldTemperature = newTemp;
      		}
      
      		int batLevel = getBatteryLevel();
      		if ((oldBatLevel != batLevel) || reportNow) // ...but only when changed, or when button is pressed; 
      		{
      			sendBatteryLevel(batLevel, ACK);
      			oldBatLevel = batLevel;
      		}
      	}
      
      	// So you know I'm alive
      	if (countLoops == EVERY_4_HOURS)
      	{
      		sendHeartbeat(ACK);
      		countLoops = 0;
      	}
      
      	countLoops++;
      
      	interruptedBy = sleep(digitalPinToInterrupt(REPORTNOWSWITCH_PIN), FALLING, SLEEP_IN_MS);
      }
      
      // Connect Digital pin 'digital_input_a' to Analog input 'analog_input_a' and a metal rod,
      // do the same for b
      long measure(sensorWiring sensor)
      {
      	long total = 0;
      	int reading_a = 0;
      	int reading_b = 0;
      
      	for (int i = 0; i<NUM_READS; i++) {
      		// Left to right
      		reading_a = measureOneDirection(sensor.digital_input_a, sensor.digital_input_b, sensor.analog_input_a);
      		// Right to left
      		reading_b = measureOneDirection(sensor.digital_input_b, sensor.digital_input_a, sensor.analog_input_b);
      
      		total += reading_a + reading_b;
      	}
      	return map(total / (2 * NUM_READS), 1023, 0, 0, 100);
      }
      
      long measureOneDirection(int digital_input_1, int digital_input_2, int analog_input_1)
      {
      	pinMode(digital_input_2, OUTPUT);
      	digitalWrite(digital_input_2, LOW);
      	pinMode(digital_input_1, INPUT_PULLUP);
      	delayMicroseconds(100);
      	long reading = analogRead(analog_input_1);
      	//delayMicroseconds(25);
      	pinMode(digital_input_1, INPUT);     // High impedance                 
      	pinMode(digital_input_2, INPUT);     // High impedance                 
      	delay(1);
      
      	Sprint(F("measureOneDirection - Reading "));
      	Sprintln(reading);
      
      	return reading;
      }
      
      // test the connections of both rods of a sensor
      boolean testSensorConnections(sensorWiring moistureSensor)
      {
      	return (testSensorConnection(moistureSensor.digital_input_a, moistureSensor.analog_input_a) && testSensorConnection(moistureSensor.digital_input_b, moistureSensor.analog_input_b));
      }
      
      //  test if digital pin is connected to correct analog pin
      boolean testSensorConnection(int digital_input, int analog_input)
      {
      	pinMode(digital_input, OUTPUT);
      	digitalWrite(digital_input, HIGH);                        
      	delayMicroseconds(100);
      	long reading_1 = analogRead(analog_input);   
      	digitalWrite(digital_input, LOW);                      
      	delayMicroseconds(100);
      	long reading_2 = analogRead(analog_input);   
      	pinMode(digital_input, INPUT);     // High impedance                 
      	delay(1);
      
      	Sprint(F("testSensorConnection - Reading1 "));
      	Sprintln(reading_1);
      	Sprint(F("testSensorConnection - Reading2 "));
      	Sprintln(reading_2);
      
      	bool correct = ((reading_1 == 1023) && (reading_2 == 0));
      	return correct;
      }
      
      float readTemp() 
      {
      #if defined (xxMY_RADIO_RFM69) && !defined(MY_RFM69_NEW_DRIVER)
      	return _radio.readTemperature(-3);
      #else
      	// Read 1.1V reference against MUX3  
      	return (readMUX(_BV(REFS1) | _BV(REFS0) | _BV(MUX3)) - 125) * 0.1075f;
      #endif
      }
      
      long readMUX(uint8_t aControl) 
      {
      	long result;
      
      	ADMUX = aControl;
      	delay(20); // Wait for Vref to settle
      	noInterrupts();
      	// start the conversion
      	ADCSRA |= _BV(ADSC) | _BV(ADIE);
      	set_sleep_mode(SLEEP_MODE_ADC);    // sleep during sample
      	interrupts();
      	sleep_mode();
      	// reading should be done, but better make sure
      	// maybe the timer interrupt fired 
      	while (bit_is_set(ADCSRA, ADSC));
      	// Reading register "ADCW" takes care of how to read ADCL and ADCH.
      	result = ADCW;
      
      	return result;
      
      }
      
      
      // Battery measure
      int getBatteryLevel()
      {
      	int results = (readVcc() - 2000) / 10;
      
      	if (results > 100)
      		results = 100;
      	if (results < 0)
      		results = 0;
      	return results;
      } // end of getBandgap
      
      // when ADC completed, take an interrupt 
      EMPTY_INTERRUPT(ADC_vect);
      
      long readVcc() {
      	long result;
      	// Read 1.1V reference against AVcc
      	result = readMUX(_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
      
      	result = 1126400L / result; // Back-calculate AVcc in mV (1024 steps times 1100 mV (1.1V) = 1126400L)
      
      	return result;
      }
      
      
      // Utter nonsense, but needed for attaching an interrupt to...
      void debounce() {
      }
      
      
      
      
      posted in Announcements
      RobKuipers
      RobKuipers