Saturday fun : playing with automatic watering system & calibatring sensors

Abstract : Winter is^W^W Holydays are coming ! I want my six plants to be keeped well watered — even if I go away from home for a w hile. Actually it’s prototyping, because the 10L tank i’m using isn’t big enough to provide needs for a long while. In this system are also included a flow sensor that counts the liquid quantity delivered to plants, and we will first discuss moisture sensors I played with.

Soil Moisture Sensing

To go quick on hardware, I got this kind kind of stuff :


I won’t spend much time to explain how to use them : with Arduino API just analogRead() the analog pin of the sensor (in this case, the sensor is used as voltage dividor). With AVR flavoured C, just enable ADC and use it as described in datasheet.

NOTE : The sensor includes a varistor and an IC (probably an OpAmp for valtage comparison), to provide a custumizabe threshold detection on a (for me) superfluous digital pin.

One “fun fact” to note : at first, I tried to use analogRead() from a NON-arduino program… (Just like I was using the Arduino Serial class in non-arduino programs in the past, with full success). But in the case of analogRead(), I could not get a single meaningful value, until I realized that it was beacause i don’t pass trought the Arduino’s main(), the function that calls setup() and then loop()s, which also sets to 1 the ADEN (ADc ENable) bit, even if the datasheet advise to set it only when using the ADC (mainly, to save power) !.. NOTE : Actually, this is done in the “wiring” module which didn’t change much recently I guess !..

Further that, it’s just analog reading. I did some experiments with a glass of water at various level of filling, and the analogRead() value seemed linearly correlated… All values were lower when adding liquid fertilizer, which match expectations : fertilizer contains ionic particules that improve ElectroConductivity of water, lowering the variable resistance of the soil in regard of a constant resistance : voltage division gives lower value, so does analogRead().

In conclusion

Such detector are easy to make D.I.Y. Further it could be great to a read the mean / sum of two variables resistances : one in the top of the pot, one at the bottom. Unsure if it would improve efficiency, but can be a leading idea for DIY “smart-pots” receiving auto-watered plants…

Auto-watering : it’s powering a pump when soil is dry, but not only !

Here is my strange (and somewhat dangerous) setup this  day :

Link to full size image


  • A. This laptop is in a dangerous situation (actually not, it’s only “posing” for the picture !). Its role is to program Arduino borad and display measurement each sec.
  • B. Arduino is “sensing” the flow throught the device that is cartoned in C. But pay NO attention to the breadboard, it only mechanical (mainly fixing floating bus wires, but also provide more friction/inertia to arduino board iself…)
  • C. the sensor flow must stand vertical, that why it stands in a carton. Quick and dirty but this worked four the few hours of the experiement.
  • D. This is the “pump” output/reductor. The circuit between pump and this very part excluded ; costed me few hours digging in a harware store, after a lot of worring… I found a suitable solution, involving a 12 mm tube that fit my 15W pump output, and two pieces that allow adaptation on this given input for the watering system (delivered in watering kit). See photo below for more details.
  • E. This stuff thightens the carton and the tank. The sensor is NOT in-between.
  • F. I plugged a T connector and 2 ‘random-lenght’ tube to simulate some hydrolic resistance, BUT multiple output // parallelisation… Did not calculate anything, sure that a complete system will have more resistance (unsure, just an intuition).
  • H. This cat has lost his keys because he was too drunk the night before… He’s still hanging around my house, but pay no attention to him, he will leave soon I guess !


Hack “DATA”

I had absolutely no clue of the output DATA signal waveform. I was guessing a short up or downrising pulse. I was wrong !

Hhaving a look on the oscilloscope to inspect that “DATA” wire. and I got a very clean square wave with a (looks like) 50% duty cycle which seemed perfect for detection. Also I had to setup a low time base to see the square, which gave me an order of frequency (about 40Hz in my system). So write, compile, and dowload that :

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "avr_uart.h"

// === TIMER1 ISR =========
int timer1_macro_counter = 10;
volatile unsigned char tick;

void setup_TIMER1() {
  DDRB |= (1 << PORTB5); // set LED pin as output
  TCCR1B |= (1 << WGM12); // configure timer1 for CTC mode
  TIMSK1 |= (1 << OCIE1A); // enable the CTC interrupt
  OCR1A = 25000; // set the CTC compare value
  TCCR1B |= ((1 << CS11) | (1 << CS10)); // start the timer at XXMHz/64
}  // XX == 16 MHz (arduino)

  if (!timer1_macro_counter) {
    PORTB ^= (1 << PORTB5);
    timer1_macro_counter = 10;
// ----------------------

// === INT0 ISR =========

volatile unsigned char flow_counter = 0;

void setup_INT0() {
  DDRD = 0x02; // bit 2 is 0 (PORTD2/INT0 as INPUT), bit 1 on (TX=>output), 0 off (RX=>input)
  EICRA=0x02; // EXT_INT0 on falling edge.
  EIMSK=0x01; // enable INT0

ISR(INT0_vect) {
// ----------------------

void main(void) {
  cli(); // at least timer1 (16bits) setup needs atomicty
  stdout = &avr_uart_output;
  stdin = &avr_uart_input_echo;
  printf("Pump flow sensor, welcome\n\n => ");
  while(1) {
    if (tick) {
      cli(); // Avoid race conditions
      int tmp = flow_counter;
      flow_counter = 0;
      tick = 0;
      sei(); // restart interrupts
      printf("%d\n", tmp);



Here you can plainly see the relevant hardware solution I found to connect a 12mm pump output to a 1/4 inch tube… How do you say “Casse-tête chinois” in your own language ?

This hydrolic circuit as 6 outputs. Its flow has to be tested, yet.


The experiment gave on my screen 644 measures (10 minutes, 44 seconds), but more, it gave about 300.000 cycles on DATA wire (300724 exactly), for barely a bit more than 9L, which gives me a factor of 0,3mL / Hz… If you want liters per minutes, the coeficient is 0.018. I found this consistent with the coeffcient found out by another Amazon Custmer on a sililar, but quite different device, here, he said:

Post Scriptum : Go “naked” at your own risk…

At first I tried to make INT0_vect an NAKED_ISR… As (des-)Assembly code was touching “just” r24 & r25 registrers (using adwi 16 bit addition opcode) I pushed & poped those registers (reverse order OBV) around the incrementation.

It was clarly not enought !

The behaviour was surprizing : while no pumping, LED blink and printf() were regular as the clock, but as soon as the pump runned, printf() was called “randomly”… I added the LED blink inside IMER1_COMPA_vect after some investigations. The LED blink was OK.

By writing those lines, I realise I forgot about restoring SREG ! It’s probably THE source for all my troubles… Unsure, but I bet !

Indeed, the Status REGister contains status bits (OK so far). Some of those bits are used by latter assembly instruction, to “know” the result of a former one. It’s a general principle, valid in every CPU (AFAIK).

On the other hand, I soon realized that in such simple code ; only “if(tick)” could misbehave. Thus, meaning probably that ‘tick‘ variable memory space was trashed elsewhere (I do multi-thread programmation, and debugging, as a day-job, so,  I know a bit about that). But in this case, the timing was secured, I even added superfluous ‘volatile‘ keywords… But cli/sei should be enought to avoid any problem !

In my first version of ISR(INT0_vect, NAKED_ISR), I was NOT saving/restoring SREG !

THAT could expain “if” instruction execution got in trouble, when INT0 ISR occurred in-between and trashes SREG state.





Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s