First Attempt at Energy Monitoring

I want to measure how much electricity our family is using.  This way, we can find ways to use less.  Lucky for all of us, there is the OpenEnergyMonitor project.

Thanks To Those That Went Before

OpenEnergyMonitor (OEM) project – It is inspiring and exciting to be able to benefit from the vast amount of information and resources provided by the OEM project.  In addition, the folks participating on their forums are exceptionally responsive and helpful.  THANK YOU.

boblemaire’s IOTAWATT project – What a fantastic source!  THANK YOU.

My First Prototype

The goals of my first prototype are to:

  • gain an understanding of how to build a DIY electricity use monitoring system.
  • evolve my thoughts on how I want myself (and potentially others) using this system (e.g.: if my neighborhood participates, can we collectively lower our use?).
  • Build a prototype that is the simplest possible to figure out stuff.

The High Level Design

This image shows the major components of the prototype:

For this project, I decided to measure the current flowing through the circuits instead of the main line.  The maximum current that can flow through each circuit in our house is 20A.  The voltage is ~ 120V.  This means the maximum power a microwave, toaster, or any combination on a circuit can draw is P = IV = 20*120 = 2,400 Watts.  Looking at our microwave, it requires 1,250 Watts.  The circuit breaker would constantly be flicking on if I were to try to put two of these microwaves on the same circuit.

The CT is attached to one of the 20A circuits in our panel (1).  The CT has a 3.5mm jack(2 & 3).  This AC circuit gets converted to DC through one of the Feather M0’s ADCs.  RFM69 is used to communicate with another device within my house.

Energy Monitoring 101

This recollection is really for my own benefit since I am a novice when it comes to energy monitoring.  Besides, any project that has me in close proximity of a high voltage of electricity commands my respect.

A question I have going in is how do we go from a wire that provides 20A to an area of our house to measuring some appliance using the electricity?  I mean, I can’t very well measure 120V and 20A with my trusty Arduino…even if it is the mighty Feather…

Lucky for me, the OpenEnergyMonitor web site tries very hard to explain all this to me.:

The first thing I needed to understand was the job the CT played in energy measurements.  The job of the CT is to produce an AC current that is proportionally lower to the AC current that is flowing through the house.  The amount the CT scales down the current is the amount needed to be measured by the voltage/current constraints of the chips the measurement hardware is using.  In the example above, the current needs to scale such that it can be measured by an Arduino.

The CT

The CT I got for this experiment

NewImage

 has the following specs:

NewImage

and schematic:

NewImage

I noticed on the specs it says Iout instead of Vout.  Given the 0-1V output and schematic, I assume the spec should be Vout for this model.

From what I can tell, split core CTs from YHDC are popular with the OEM folks.  The OEM project describes the YHDC sensor they tested in this post.  Looking at the YHDC web site, I got a better feel for which sensors output current and which output voltage.  For example, here are a few:

NewImage

In addition, the number after SCT is the hole size.  The 13mm diameter hole size was big for the wires coming off of the breaker switch.  Eventually I’m interested in measuring all the wires, so I ordered an SCT006 from eBay.  I’ll figure out how to set up the circuit when it comes in.

The Turns Ratio-1

To understand the importance of the turns ratio, I like the image drawn during this video:
NewImage

In the case of the CT I’m using, Np = 1 and Ns = 1800.  So the current coming in (Ip) is scaled to 1/1800 in order to get to the measured current (Is).  So if an appliance used a full 20A, the CT would scale this to 1/1800*20 = 10mA.  10mA…I’m much more comfortable measuring that amount of current.

CT Output

What gets measured out of the CT depends on the CT.  The one I got returns a reading between 0 – 1 V.  What this tells me is it has a built in Burden Resistor.  

Negative Voltage

The challenge then is how do we measure negative (AC) voltage?  The same way I did when I designed the EC circuit – which I called a floating ground.  Thisis also commonly called a bias.

Notice R1 and R2 in the image.  These create a voltage divider that lifts (biases) the ground up from 0V to 1/2 the voltage of the Arduino (which in the diagram is 5V – so the bias is 2.5V).  The GND connection of the CT connector is connected to the mid-point of the voltage divider.  Thus, readings will be (positively) biased by 2.5V.  A reading would be Is a secondary voltage reading( which in our example will be +/- 10mA) +2.5V.

Wiring

For my hands on part of my energy 101 learning, I set up the circuit OpenEnergy kindly provided.

 

 
IMG 6070IMG 6059
I mounted the female side of the jack to a proto board.  This way I could make sure the signal got from the CT to the Arduino’s A1 pin. 
 
I ended up putting the CT around two circuits because of space constraints.  So instead of measuring a max of 20A, I am measuring a max of 40A.
 
The CT has a 3.5mm male jack.  I used this female jack from Digikey:  

Pasted Image 8 13 17 1 11 PM

NewImage

 

 

 

 

 

 

 

hooking 1 on the female jack to the BIAS on the breadboard and 2 to A1 of the Arduino.  

Software

I ran the current_only.ino Example that comes with the EmonLib library.

// EmonLibrary examples openenergymonitor.org, Licence GNU GPL V3

#include "EmonLib.h"                   // Include Emon Library
EnergyMonitor emon1;                   // Create an instance

void setup()
{  
  emon1.current(1, 60);             // Current: input pin, calibration.
}

void loop()
{
  double Irms = emon1.calcIrms(1480);  // Calculate Irms only
  
  Serial.print(Irms*123.7);	       // Apparent power
  Serial.print(" ");
  Serial.println(Irms);		       // Irms
}

Calibration

Why did I put 60 for the second variable in the call to current (i.e.: emon1.current(1,60) )?

The OpenEnergyMonitor docs includes a section on current sensor calibration.  I found the most important info to be:

 

If you use a current transformer with a built-in burden (voltage output type)

(MY NOTES: I am…see below).

Look at the last line of the theory where the current constant is derived:

current constant = (100 ÷ 0.050) ÷ 18 = 111.11

“100” is the current transformer primary current, and “0.050 × 18” is in fact the voltage across the burden resistor for the standard CT and burden at that current, so to arrive at your current constant you simply substitute your transformer’s rated current in place of “100” and the voltage it gives in place of “0.050 × 18”. For example, the YHDC SCT-013-030 gives 1 V at a rated current of 30 A, so for this transformer you have:

current constant = 30 ÷ 1 = 30
(MY NOTES: I am using the YHDC-SCT-013-060.  In this case, the current constant I will use is 60….and yah - looks like I don’t need a burden resistor).

Or to put it in words, the current constant is the value of current you want to read when 1 V is produced at the analogue input.

Irms

I am sadly intimidated by terms like “Root Mean Square.”  It sounds so physics/math related.  It sounds so much like the professor who always glared directly into my eyes  when he said “Assuming you have the intelligence….”  (seriously!..as an aside, if you have a daughter, don’t let this happen to her…).  Anywho, I think of Irms is the DC equivalent value of an AC current.  While this video starts off slow, “The Concept of RMS” gives me a feeling for Irms (Vrms) perhaps assuming I don’t  have the intelligence….

in the call to the sampling function: emon1.calcIrms(1480); I left the number of samples to what the script recommends.  Here’s a little bit more info (from this web site): The sketch reads approximately 106 samples of current in each cycle of mains at 50 Hz. 1480 samples therefore works out at 14 cycles of mains. That will give you a good average reading. You can change the number, but you should get as close as possible to having a whole number of mains cycles, otherwise if you have only part of a cycle on the end, you will introduce an error.

 

Measurements

Before I list some numbers, I should point out my simple project isn’t measuring voltage.  This means I’m not measuring the real power being used.  Rather I’m measuring the apparent powe

Apparent Power

Note: I am writing this section for my own benefit.  By doing so, I can use wording that helps me understand Apparent Power since it is a key aspect in AC Power measurement.

I found the following info the most helpful:

I am thrilled to have done this experiment if only to learn more about AC Power.  So far, my focus in electronics has been around Ohm’s law – DC Power.  I didn’t know one way or the other about AC, but assumed it too follows Ohm’s law.  Well, most of the time it doesn’t.  If the load drawing current is like a resistor – e.g.: things that use resistance to heat or light – incandescent light bulbs, hair dryers, toasters, and kettles…then P = IV.

However, most of the loads in our houses (as note in this document):

  • Refrigerators, Freezers
  • Air conditioners (all types)
  • Fluorescent lights including CF lights
  • TV, computer, stereo, any wall-wart
  • Microwave Oven
  • Washer, Dryer
  • Vacuum cleaner
  • Fans
  • Power tools: grinder, electric saw, compressor, etc.
  • Humidifier, dehumidifier
  • Garage door opener, pool pump, electric lawn mower, etc 

use inductors and / or capacitors which momentarily store some of the energy and then return it to the energy source.  This means Power measurements using the simple IV calculation that is used in the Arduino sketch for this project where the voltage is approximated at all points to be 123.7V (based on a Kill-A-Watt reading),  will be higher than the actual amount of power being used.

Not Much Load

Here are some measurements I got when I wasn’t running much on the circuit:

0.23 123.7 28.97
0.27 123.7 32.83
0.33 123.7 41.16
0.28 123.7 34.61
0.24 123.7 30.18

The first column is Irms, the third column is the first column multiplied by the second column = Apparent Power.

Microwave

When I turned on the microwave, I got readings like these:

33.94 123.7 4198.91
32.5 123.7 4019.83
30.85 123.7 3816.13
31.82 123.7 3935.75
31.83 123.7 3936.79
31.79 123.7 3932.57

Certainly a much higher amount of Apparent Power.

Coffee Machine

I have a fairly elaborate coffee machine.  The first thing it does upon turning on is heat to 200˚F.

25.41 123.7 3143.41
25.17 123.7 3112.98
25.25 123.7 3123.45
25.23 123.7 3121.1

Heating takes a lot of energy. Given that this process is heating, I assume the Apparent Power is much closer to the real amount of power being used.

What’s Next

To evolve my knowledge, I plan to measure the real amount of power being used coming in from the source rather than one of the (smaller) circuits.  By doing this, I can compare/contrast my readings to the monthly readings I get from my energy provider.  Using these results, I can calibrate future energy monitoring projects to accurately reflect the amount of energy actually being used.

 

 

 

Thanks for reading this far.  Please find many things to smile about.

Advertisements

We’ve Got Mail

ChallengesBringOpportunitesI’ve been delighted with the results of my We’ve Got Mail project.  Now we know when mail is put into our mailbox.  Our mailbox is down the road from our house.  There are days when my husband goes down and checks for mail delivery several times.  A little exercise is a great thing.  But some days it is cold, rainy, and dark.  

NOT ANY MORE – when mail comes, the super-dah-dee-duper We’ve Got Mail home device starts to sparkle…a DEFINITE YIPPEE moment…It knows when to sparkle because the Mail Box Puck – which sits inside the mailbox – sends a message to the controller when the mailbox door is opened.

WeGotMailController

This can’t be seen in the image, but the top of the device’s enclosure is printed with translucent filament.  When mail comes, the neopixel FeatherWing starts lighting up in a sparkle panel.  There is a button on the left side of the enclosure that turns off the sparkling.

Thanks To Those That Went Before

I am very grateful for the knowledge, excellence, and practical use of:

  • the RadioHead RF arduino libraries.  These libraries have been the backbone of my radio projects.  Well done.  My only challenge is in power management with the m0 – getting to deep sleep requires waiting for an interrupt.  My current challenge is the RF library takes over the interrupt I define for RF traffic.  When I put the m0 in idle mode 2, I get the interrupt.  When I put the m0 into deep sleep and wait for an interrupt, I don’t receive one.  I should do more investigation.  However, at this time I want to make progress on other project.
  • Adafruit products and services.  THANK YOU for the spirit of “We all do better when we all do better.” (see Al Franken’s book).  For the RF95 feather, neopixels, their exceptional service, exceptional support, exceptional videos.  From all I can tell employees are treated well.  They care about each other and us.  It would be SO AMAZING if more companies shared the “We all do better when we all do better” spirit.
  • John Ericksen’s really nice neopixel sparkle sketch.  It would take me a long, long time to figure out the graphics/math and put this together.  John made this easy and shared it with us.  THANK YOU.
  • Tweaking4All’s also really nice Fire neopixel sketch.  Same comments as with John’s work.  THANK YOU.
  • Jeremy Bloom’s tutorial on using hardware to debounce button input.

Open Source

The two Arduino sketches I used:

  • GotMail_Home_V2.ino
  • GotMail_MB_V1.ino
are located at this GitHub location.

The Goal

The goal is to build a Mail Box puck and Controller that lets us know when mail has arrived.  The Mail Box puck sits in the mail box.  When the door is opened, it sends a notification to the Controller.  The Controller is responsible for:

  • receiving the message from the Mail Box puck.
  • sparkling when it receives the message.
  • turning off sparking when a button is pushed. 

The Hardware

NewImage

The Mail Box Puck

MailBoxPuck

Thankfully, the RFM95 LoRa sends a strong enough signal to easily reach inside our house from the mailbox.  The mail box puck is extremely simple (see GotMail_MB_V1.ino):

  • The PIR sensor is hooked up to a GPIO pin.
  • The first thing the loop() does is goToSleep() – i.e.: set the M0 into deep sleep mode, put the RF95 to sleep, and set the motionDetected interrupt to be called back when the GPIO pin assigned to the PIR sensor goes off.  The GPIO pin will change from LOW/HIGH when the mailbox is opened.  When this happens, the __WFI() happens, which plops the code into motionDetected().
  • The bMotionDetected is set to true.  
  • When bMotionDetected is true and now the code is running below the interrupt in the loop(), a mail message is sent to the WeGotMail home device. 
  • The message includes the battery level.

The Controller

The Controller uses the GotMail_Home_V2.ino code.

There are three Feather boards inside the Controller – a Feather M0 RFM95 LoRa, a proto FeatherWing, and a neopixel FeatherWing.  This image shows the neopixel Featherwing connected to the proto Featherwing.

NewImage

The RF95 code was easy because I was familiar with how RadioHead’s library worked after using it for my outdoor gardening project.  I LOVE evolving what I have learned.

Start Sparkling

I grabbed the sparkle() routine from John Ericksen’s Multicolored Plasma for the Arduino Micro-Controller and NeoPixel Shield sketch.  When a message is received from the Mail Box Puck with a battery reading <= 3.7, the sparkle pattern changes to flickers of red in the Fire() routine.  I grabbed this code from Tweaking4All’s work and slightly modified it.

Stop Sparkling

There is a button on the side of the enclosure that when pressed turns off the neopixels.

Button Wiring

I hooked up a  button I found lying around.  Because I easily forget the basics, I decided to document how a simple button switch works.  

Here is an image from an Adafruit tutorial that shows how a button switch should be wired:

note:

  // initialize the pushbutton pin as an input.  Use INPUT_PULLUP
  // so that when the button is open, the digitalRead will be HIGH.
  pinMode(buttonPin, INPUT_PULLUP);

These two tidbits of information made it easy for me to wire up the button.

Button Detection

The two challenges I had were:

  • realizing the best way to trigger an interrupt when the button was pushed was on the RISING or FALLING edge.  Triggering on the HIGH or LOW reading returns many (many) readings.  Yah. Obvious to you.  I get it. (BTW: I thought Jeremy Bloom’s discussion on how interrupts work on the Arduino was excellent…)
  • just getting one interrupt when the button was pressed and the interrupt was set to fire on RISING (or FALLING).  AKA debouncing. The debouncing links shows how to do this when the code does not use a hardware interrupt.  I’m glad it did because I didn’t know how to hardware debounce.  Lucky for us, Jeremy Bloom has a tutorial discussing hardware debouncing.

NewImage

I am using the NTE74HC14 Schmitt Trigger Inverter.  I chose this one because our local hardware shop had it, making it easy for me to pick up.  

NewImage

The pins I used include 7, 14, 2, and 1. Pin 1 is input from the button push and pin 2 is output that goes into a GPIO pin of the Feather M0.

NewImage

 

Firmware

The Controller’s job is to hear a message from the mail box puck.  When it does, it starts sparkling the neopixels.  There is a button on the side of the box to turn off sparkling.  When the battery level of the Mail Box Puck is <= 3.7V, the sparkling looks like red fire to symbolize the Mail Box puck’s battery needs to be recharged.

Feature requirements:

  • Sparkle when a “We’ve got mail” message is received from the mail box puck.
  • Stop sparkling when the button is pushed.
  • Have a robust and attractive enclosure.
  • Be available wherever we are within the house.  In order to do this, the Controller will use a battery.  The enclosure must make it easy to recharge the Controller through the USB port.  The Controller should use minimum battery power.
It is my hope/expectation that the GotMail_Home_V2.ino is readable enough for anyone interested to figure out what is going on.
 
 
 
 
…Thanks for reading this far.  Please find many things to smile about.  I for one, am grateful.

 

 

 

 

 

Moisture Puck – Firmware Evolved with Better Power Management

Tags

Thanks To Those That Went Before

It’s all too easy for me to overlook the efforts by amazing folks.  I find though when I stop and express gratitude, I am much happier.  More at peace.  So for purely selfish reasons, I thank:

  • Ron Sousa  of HDE for excellent 1:1’s in which he walked me through Cortex m0 power management registers and what to look for.  I is a credit to Contextual Electronics to have such amazing folks on staff.
  • Adafruit for products like the Feather line, the  INA219 Current Sensor Breakout.  For their excellent support.  For the way they seem to care about the workers.  For their videos.  I hope more companies become like Adafruit.  
  • Rick for his comments on this blog.  I find them very useful.  The most recent one being hook up a current sensor.  Thank you Rick.  I did this.  Talk about a great thing to do!

Open Source

The Arduino code for the Moisture Puck and the Controller (v3) can be found at this GitHub location.

Overview

It is unacceptable to recharge the battery after 3 days.  The Moisture Puck was burning on average about 25mA.  Given the Feather is powered by a 2000mAh LiPo, the back of the envelope calculation (2000/25/24 = 3.3 days) is “close enough” to what I observed when the Moisture Puck was in the soil sending measurements to the Controller.

The updated Moisture Puck code cuts down the power usage considerably.  For ~ 6 seconds each hour, it draws 32mA.  For the the majority of the rest, it draws 1.2mA.  There are occasional spike of ~5mA.  Averaging the spikes with the 1.2mA, it’s at about 1.45mA for the other 54 seconds of the hour.  So: 10% of the time, the Moisture Puck draws 32mA.  This is when packets are being sent/received to/from the Controller.  The other 90% of the time the Moisture Puck is sleeping, drawing about 1.45mA.  This comes to (.1*32) + (.9*1.45)  = 4.5mA.  Given this calculation, I hope to see the Moisture Puck’s battery last (2000/4.5/24 = 18.5 days….roughly 18 days.  The key to these power management improvements included:

  • Using the rtczero library.
  • Restructuring the code so that the Moisture Puck wakes up at an AM and PM watering time then sends packets.  The rest of the time the m0 and RFM69 are sleeping.
  • Only powering the moisture probe when it is being used.  Prior, the moisture probe’s V+ was wired directly to the Feather M0’s V+.  I moved the V+ wire to the Feather M0’s 12 GPIO pin and set the pin to HIGH when taking a measurement and then low once finished taking the measurement.
While this is a significant improvement, it is still higher than it need be.  I’ll save more power reduction exploration for a later time.

New Moisture Puck Firmware

  • More accurate time of day: MoisturePuck2007_v3.ino/Controller2007_v3.ino take advantage of Adafruit io’s time feed to set the time on the Moisture Puck.  This way, the Moisture Puck has an accurate time without the need of a RTC chip.
  • Less power used:

Less Powered Used

Measuring Current Draw

An essential tool for this exploration is Adafruit’s nifty INA219 Current Sensor Breakout. I modified a USB cable so that I could insert the INA219 into the power side of the circuit over USB.  

NewImage

I hooked up the INA219’s I2C to the Arduino and run the getCurrent.ino sketch (found in Examples that come with the INA219 library) on the Arduino.  I suppose I could have more easily measured current through the battery (by more easily I mean I wouldn’t need to hack up a USB cable).  However, using the USB port for building/debugging is easier.  

Numbers:

  • about 13mA when the Feather m0 was in upload mode.
  • about 32 mA when sending/receiving RFM69 packets
  • about 1.2-1.5 mA when in rtc.standby() and the moisture sensor is not drawing power.
I would think deep sleep would draw less power (around 700µA?) and the 5mA spikes are suspicious.  I assume there are peripherals (e.g.: Flash) that are still on needlessly sucking up power.  For now, I’ll let that go to allow exploration into other areas that I’d like to improve on.

Turn Off the Moisture Sensor

One thing I noticed that was like “oh – right – duh” was the moisture sensor was being powered by the 3.3V pin of the Feather m0.  It was on all the time.  As noted by Chris Ruppel in his “Arduino soil moisture sensor” blog post, only send power to the sensor when actively taking a reading of the soil moisture. Powering only during these short moments helps avoid corrosion caused by the constant flow of electricity between the two pads of the sensor.

Besides corrosion, power consumption is 2.15mA when the moisture sensor is on and 1.45 when off.  The moisture sensor sucks up 700µA!

I attached the v+ of the moisture pin to pin 12 of the Feather and now turn the pin HIGH right before measuring then back to LOW after measuring.  Much better.

MoisturePuck2007_v3.ino

This version of the firmware is – happily – simpler.

  • Controller sets the time from Adafruit.io: A core assumption with this experience is the Moisture Puck knows the correct current time as well as the AM and PM watering times.  Neither Controller nor Moisture Puck have a RTC.  The Controller grabs the current time from Adafruit.io’s time feed.  Once the Controller’s firmware is loaded, it subscribes to Adafruit.io’s time feed.  The Controller waits around until it receives the current hour, minute, and seconds from Adafruit.io.  It then sets it’s time to these values.  The Controller switches to listening for a Moisture Info packet.
  • Controller listens for a Moisture Info packet: Once the time is set, the Controller listens for moisture info packets. 
  • Moisture Puck sends Moisture Info Packet: The Moisture Puck takes moisture readings when the firmware is first loaded and then at the AM and the PM watering hours.  The Moisture Puck sends the Moisture Info packet to the Controller and then waits to receive a Time Info packet.
  • Moisture Puck goes to sleep: Using APIs in the rtczero library, the moisture puck sets a wake up alarm and then goes into a deep sleep.
  • Controller gets a Moisture Info packet:  When the Controller gets a Moisture Info packet, it publishes the values to Adafruit.io.  The Controller then sets up a Time Info packet and sends it to the Moisture Puck.  This way the Moisture Puck knows the correct time.

 

NewImage

 

That’s it for the update.  Please see the GitHub location above to get the code.  Thank you and please find many things to smile about.

 

Auto Irrigation 2017 – June 20 Update

Tags

, , , , ,

A month ago, I decided to work on this summer’s irrigation project for one month ending June 20th

Thanks To Those That Went Before

  • cmpxchg8b – In their reply to the Adafruit forum discussion post M0 wait for interrupt (worth a read), they provide the useful idleSleep() function. THANK YOU.
  • monohelixlabs – for  the DataFeeds iPhone app.  By using this app, I was quickly able to view the Adafruit.io data feeds on my iPhone.
  • Adafruit – for the great products, tutorials, libraries, support, and incredible people.  Adafruit has made it extremely easy for me to evolve and learn through projects like this one.

The Goal

The goal of this post is to document the June 20th status of my 2017 Auto irrigation project.

Open Source

The Arduino code I used for the Moisture Puck and Controller are located at this GitHub location.

(note to myself?)

There were a lot of test Arduino sketches that are not relevant to this post in the folder containing the sketches I push to GitHub.  To ignore these sketches, I added them to the .gitignore file.  I did this by:

  • opening a terminal on the Arduino folder
  • ls > list.txt
  • sed ‘s;$;/*;’ list.txt > new_list.txt

  • copy/paste the contents of new_list.txt into .gitignore
  • deleting the sketches that should not be ignored for the Controller and Moisture Puck.

The Project

All this technology and I’m wasting time hand watering three different growing areas in my backyard (see this post for a description of my backyard watering areas).

What I Set Out to Build

I set out to build an automated watering system.  The soil needs water, it automatically gets watered.

What I Built

Instead of auto watering, I opted to get a better feel how the system works (worts and all!) by tying into the Internet through Adafruit.io.  I did not break into the irrigation pipes and install solenoid valves.

This is what I built:

Overview

Overview of Interactions

 The actors in this story include:

  • The Moisture Puck.  The Moisture Puck uses a moisture sensor to measure how wet the soil is.  The Controller sends a request (1) for moisture info.  The Moisture Puck returns (2) the moisture level, the battery level, and how hot the RFM69 chip is.
  • The Controller.  The Controller controls the conversation between itself and the Moisture Puck as well as communicating with the Adafruit.io service (3).  When the Controller receives moisture information from the Moisture Puck, it publishes the moisture level, battery level and RFM69 chip temperature as data feeds to Adafruit.io.
  • Adafruit.io.  There are four data feeds.  One for each of the values captured from the Moisture Puck.  A fourth feed – I call this the water feed – is used as a “control” feed.  The firmware in the Controller subscribes to the water feed.  When a data value is added to the water feed, the Controller receives an update.  This causes the controller to talk to the Moisture Puck, get a reading, and then publish the reading on Adafruit.io.
  • IFTT.  YIPPEE! For me, Adafruit made it so I can write applets in IFTT that include Adafruit.io data feeds.  The applets I built include:
    • an applet that gets the sunrise information (when the sunrise occurs, what the current weather condition is).  The sunrise time and weather condition is written to the water feed.  As I noted above, writing to the water feed triggers the Controller to request a moisture reading which is then written to the Adafruit.io data feeds.
    • a similar applet that gets the sunset information.
    • an applet that connects SMS to the water feed.  I send a text message to the IFTT SMS number….and…yah…you guessed it…this triggers the Controller to request a moisture reading….

 The Moisture Puck In the Garden

MoisturePuckV2InAction

Moisture Puck In Action

Hook Up

The hookup is very simple.  The soil moisture is connected to the Feather’s 3V, GND for power.  It uses A0 to get moisture readings from the moisture sensor.

NewImageThe battery is wrapped with gaffer tape to give a layer of protection.

What Worked

  • I really liked the Feather M0 RFM69. The radio can send/receive packets at the distance needed.  The Cortex M0 has been very stable, has strong power management (assuming I can figure out more 🙂 ), and has great documentation.
  • While a little bit too finicky for my tastes, the Feather Huzzah has proven to provide a steady Internet connection.
  • Adafruit.io made it extremely simple and easy to integrate in powerful apps such as IFTT.  Compared to my recollection of what was available just 5 years ago, I find this simplicity amazing.
  • Taking and interpreting sensors readings worked seamlessly.
  • Separating the enclosure into two boxes – one to hold the battery and one to hold the feather.
  • Attaching the moisture probe to a cable instead of to the enclosure.  I was able to better place the probe close to plant roots.  I was excited to repurpose an audio cable that was sitting within a snarl of cables in our garage.
NewImage

What Needs Work

  • An enclosure that is completely waterproof inside.  Adding a coating of XTC stopped leakage coming in between the plastic layers.  What needs work is a top and bottom piece of a (box like) enclosure that is easy to take apart – say for example to recharge the LiPo battery in the case of the Moisture Sensor – but is also waterproof.  What I am currently doing is wrapping the sides of the box in gaffer tape.
  • I’m having to recharge the LiPo after 2.5 days. This is way too often.  I was able to improve the battery life by ~ 27% using the Cortex M0’s IDLE mode 2 (see the SAM D21 Data sheet, section 15.6.2.8).  I was not able to set the M0 into STANDBY mode. STANDBY mode is a lower power mode than IDLE mode 2.  I am investigating what should be done to get STANDBY mode to work.
  • Using text messages as the user interface.  I send a text message on my phone and then look at updates to the feeds within the DataFeeds iPhone app.  I should be able to send different text messages and receive immediate responses….questions like “what is the current moisture level/battery level…” or get a text when watering is needed.

What Didn’t Work

  • I didn’t get around to connecting a solenoid valve to the irrigation lines in order to start auto watering.  I ran into challenges getting the circuits working reliably on a Feather proto board.  These challenges shifted my focus to Internet integration.  I don’t see any showstoppers at this time. I just haven’t got around to getting auto watering built and running.  It’s probably just as well because there is still tweaking of the Moisture Puck.  I’m not at 7 x 24 x the days of spring, summer, and fall of reliable moisture readings.
  • Saving additional battery life by putting the M0 into STANDBY mode. As I mentioned earlier, I plan to spend time figuring this out.  I also want to try solar power/recharge once I get all the parts.

Initial Notes on Power Management

When I didn’t add power management code, the moisture puck stopped talking to the Controller after 44 hours.

I added in this code without knowing much about the AtSamD21 power settings:

/*
   IDLESLEEP - thanks to cmpxchg8b: https://forums.adafruit.com/viewtopic.php?f=57&t=104548&p=523829&sid=22b8d0735f65f3f53a0f1e8781c886e6#p523829
*/
void idleSleep()
{
  // Select IDLE, not STANDBY, by turning off the SLEEPDEEP bit
  SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;

  // Select IDLE mode 2 (asynchronous wakeup only)
  PM->SLEEP.bit.IDLE = 2;

  // ARM WFI (Wait For Interrupt) instruction enters sleep mode
  __WFI();
}

The Controller started receiving data on 6/15 at ~3:47AM.

The last data the Controller received was on 6/17 at 11:20AM:

NewImage

Progress.  Based on the same hourly readings used in the experiment where the moisture puck lasted for 44 hours with no power management code, power to run the moisture puck was increased to 56 hours.  This gave 27% more time (i.e.: to calculate percent increase: (56-44)/44 – yah, yah … you know this it is so basic..yah, yah…ooh – umm..hold on…look at this picture of the Grand Canyon – HOW A-W-E-S-O-M-E:

[Side note: Here’s my challenge with remembering basic math…I mean…the image of the Grand Canyon or calculating percent increases?  My mind chooses images of the Grand Canyon every single time.  But I diverge.]…

Looking at the AtSamD21 data sheet, section 15.6.2.8 Sleep Mode Controller,  Table 15-4: Sleep Mode Overview, Idle 2 (the sleep mode used in the current firmware) uses more power than Standby.  Hmmm…the data sheet goes on to note that standby mode (uses less power than idle mode) should react to an interrupt from the RFM69 chip:  Any peripheral able to generate an asynchronous interrupt can wake up the system. For example, a module running on a Generic clock can trigger an interrupt. When the enabled asynchronous wake-upevent occurs and the system is woken up, the device will either execute the interrupt service routine or continue the normal program execution according to the Priority Mask Register (PRIMASK) configuration of the CPU.

I will write a sample client/server that:

  • First, uses the power saving code I am currently using to make sure it works in this mode.
  • Second uses deep sleep/stand by mode.
Hmmm…based on the above comment, I thought this:
void idleSleep()
{
  // Just put in deep sleep:
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  // Select IDLE, not STANDBY, by turning off the SLEEPDEEP bit
  //SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;

  // Select IDLE mode 2 (asynchronous wakeup only)
  //PM->SLEEP.bit.IDLE = 2;

  // ARM WFI (Wait For Interrupt) instruction enters sleep mode
  __WFI();
}

but alas… the code just waits…and waits…and waits…and waits…and waits…. so for now, power management means putting the M0 to wait for interrupt when the chip is in idle  mode 2.  Too bad.

Talking To The Controller from my Phone

Given the iPhone is evolving into my trusted assistant, I wanted to communicate to the Controller through text messaging…the same way I communicate with…well…humans when I use my iPhone…

My first attempt at this is to use Adafruit.io and IFTT.  I can send a text message to the IFTT SMS service to get the Adafruit.io IFTT service to post the message on the water feed. Posting the message on the water feed invokes the function within the Controller that is subscribed to be notified of changes to the water feed.  The Controller gets a reading from the Moisture Puck.  The Controller then publishes the moisture, battery level, and RM69 chip temperature readings to their Adafruit.io feeds.  Also, I created an IFTT applet that fires when the battery level is less than 3.6V.  This way, I will know when to charge the battery.

NewImage

I then look at the data feeds within monohelixlab’s data feeds iPhone app.

What Worked

 

I started using Adafruit’s mqtt library.  Stuff worked.  Then I thought…ooh…neato….Adafruit has a simpler library – Adafruit.io – so I mucked up the code to try the simplified version.  

Frustrated sadly, the Adafruit.io library calls seems to cause a soft reset of the Huzzah.  Honestly, many things cause a soft reset.  With that said, at this point I won’t spend time debugging the Huzzah.  I want to change to the newer Feather Huzzah32 but they are (still!) on back order…so…back to the lower level mqtt library…which works fine.

Bit Manipulation

As I was exploring, my old friend – bit manipulation – came for a visit.

Bit manipulation techniques reminds me of learning multiplication tables.  At least for me.  Perhaps for some it “just appears” in their skill set.  For me, it is practice.  When it comes to practice, I’m finding if I can minimize and simplify what I practice, I am better prepared to make the technique a constant part of my toolset.

I want to use bit manipulation more for keeping track of state – as well as the obvious setting of registry bits – because to me it becomes more intuitive than perhaps using an enum of states.  In the case of the moisture puck firmware, bit manipulation is used disable deep sleep.  From this ARM post, deep sleep is enabled by turning on the deep sleep mask:

SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; /* Enable deepsleep */

in the moisture puck firmware code, the deep sleep mask is disabled. The mode is then set to idle mode 2:

  // Select IDLE, not STANDBY, by turning off the SLEEPDEEP bit
  SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;

  // Select IDLE mode 2 (asynchronous wakeup only)
  PM->SLEEP.bit.IDLE = 2;

ON: Turn a bit on with |= .

OFF: Turn a bit off with &= ~<variable set to all zero’s except a 1 on the bit that is being turned off>

IS THE BIT ON

uint8_t flagByte = 0x0;
uint8_t firstBit = 0x1;
flagByte |= firstBit;
if (flagByte & firstBit){
  // the firstBit bit of the flagByte variable is on
}

Is the bit OFF?

uint8_t flagByte = 0x0;
uint8_t firstBit = 0x1;
if (~flagByte & firstBit){
  // the firstBit bit of the flagByte variable is off
}

Auto Irrigation Build Log for June 1st

I spent my time looking into uploading the boot loading code onto the Feather M0..

Restoring the Bootloader on the bricked Feather

Adafruit has this “step by step” guide.  This is one of the few guides on the Adafruit web site that I do not think following the steps is the best way to get to my goal – which is to reload the boot load binary code onto the Feather.  It points me on the right direction which is to get a J-Link connection to the M0 on the feather and upload the binary that way.  

I have an nRF51 DK which has a SEGGER J-Link OB debugger chip .  As I pointed out in this post, a great feature of the nRF51 DK is its debug out capability.

The question I am exploring: Can I use the nRF51 DK and SEGGER’s JLinkExe utility to upload the bootloader hex filefeatherm0bootloader_160305.zip?

to jump to the answer:

 NO

below is how I figured out the answer is NO….

Getting Ready – What JLinkExe command should I use to upload the hex file?   

JLinkExe -device ATSMD21G18

will connect me to the device over SWD (assuming I can get the connection to work). Now that the JLinkeExe utility has the right device, I should be able to upload the feather boot loader bytes with this command (assuming I’m executing the command within the same folder in which the hex file is located):

loadfile featherm0bootloader_160305.hex

Getting a J-Link Connection

Wiring up the Feather to the JLink connector is a bit of a pain because of the way the feather exposes the SWD pins:

NewImage

NewImage

A JLink connection requires 4 wires – in this post I discuss connecting these.  I need to solder wires to the feather’s SWD and SWC pins and connect them to these pins on the nRF51 DK.  Updated JLink commander, told JLink commander the device is a ATSMD21G18…and…

and…

*** J-Link V6.14g J-Link V6.14g Info ***

The connected J-Link (S/N 681099822) has been designed to work with devices made by Nordic Semi only.

Debugging the selected device ATSAMD21G18 is not supported by this J-Link.

 

To program and debug the target device, please consider purchasing a full J-Link.

More information: <a>https://www.segger.com/jlink-debug-probes.html</a&gt;

*** J-Link V6.14g J-Link V6.14g Info ***

Oh well.  Now I know.  OK fine.  I probably will need a JLink in the future so I ordered the EDU version from Digikey.  At least it is less expensive than the last pair of shoes I bought.  Of course, I wear shoes for about 10 years….so…ok, the JLink better be useful for 10 years.

 

Auto Irrigation Build Log for May 31st

Two things:

  • Given the 2000mAH LiPo battery needed to be recharged after 44 hours, I spent time looking into CPU (the Feather I am using uses the M0 CPU) power management.  
  • I removed the Moisture Puck from Strawberry Swirl and opened it up.  The enclosure design needs improvement:
    • waterproof the top.  There were drips of water on the under side of the top of the lid pointing to water seeping through the top.
    • a design in which the battery can be recharged without having to take out all screws.  As I gain knowledge into enclosure design, I can’t help but admire the design of many small consumer devices.

Power Management

Test Code Results

I wrote PowerManagementServerRFM69.ino to act as the Power Management code that would run on the Moisture Puck.  I simplified the sending side in PowerManagementClientRFM69.ino.

I loaded each sketch on it’s Feather.  Packets were received by the server from the client.  

Frustrated

Then…um….I couldn’t get the server into boot loader mode even after (carefully – at least I thought I was careful…I admit following directions isn’t all that easy for me…) following Adafruit’s directions.  Well…that means…TIME TO LEARN…YIPPEE!  I will try restoring the boot loader. Then continue power management testing.

One thing that was “fun” to learn about and try out was Apple’s USB Prober utility: “ USB Prober displays USB specific information from the system and from IORegistry. It also displays status messages generated by the USBLog function call.

 

 

 

 

Info on Power Management

Battery Life Power Management Info sources that I found very useful (by useful I mean a quick read to get me up to speed):

Checking on Current Consumption

In Tony’s discussion on Current Consumption, he notes Adafruit’s INA219 current sensor breakout board.  I have one on order.  I hope this will give me a better feel for (close to) exactly how much battery life I can expect to gain with the changes made.

Waterproofing Moisture Puck Enclosure

The third image of the Moisture Puck shows a water drop on the inside of the enclosure:

 

NewImage  NewImage  NewImage

The second image shows the pain that must be endured to get to the LiPo battery, unplug it, and the recharge.  Yuck.

Next Steps

Next steps based on May 31st include:

  • Getting the bricked Feather to upload sketches and be seen by a serial port.
  • Evolving the design of the Moisture Puck so that recharging the battery is much easier.
  • Figuring out the best way to waterproof the top of the Moisture Puck.

Auto Irrigation Build Log for May 30th

Today my focus is on adding the Controller “stuff” to turn the water on and off.  

The additional “stuff” I need includes:

  • a four way valve splitter.
I added one to our back yard spigot last year:
 
NewImage   NewImage
The valve on the far right goes to a hose.  The other three are feed water through the three irrigation lines to either Strawberry Swirl, Upper Deck, or Lower Deck.
  • hardware to turn the solenoid on/off.
I went off on a bit of a learning tangent exploring the difference between a solenoid and a relay.  I liked ScienceOnline’s video “Solenoids & Relays.
 
Each solenoid will use the following circuit to open/close the valve:
A diode, TIP 120 transistor, and a resistor.
 
I have both through hole and SMD versions of these chips.  Here’s my through hole collection:
NewImage 
I could make a Feather PCB and send this off to OSH Park.  First I want to see how well using Adafruit’s FeatherWing Proto – Prototyping Add-on.  I plan to solder on the through hole parts to create the circuits for the solenoids.

Setup

It’s time for me to evolve the enclosure for the Controller.  I plan to mount the controller along this wall:

NewImage

It’s close to a wall socket as well as to the three irrigation pipes where I can insert the solenoids.  See that peanut shell?  There are these two squirrels that constantly dash around.  We find peanut shells all over the place.  I find it pretty hilarious – it is like an ongoing Easter Egg hunt.  Those squirrels better keep running…I’m just saying….

Enclosure

I will evolve the Adafruit’s Fusion 360 Feather Enclosure.  Right now I’m printing out the bottom.  It’s pretty much what was designed by Adafruit…but…Ugh. So far I’m starting over for the 3rd time. The layer of plastic slips.  I’m tweaking variables discussed in previous 3d printing posts as well as slowing down printing.

Shopping List

 

Post Data Analysis

I was thinking about data collection and analysis.  One thing I want to log is hourly temperature reports.  I could set up a outdoor temperature sensor and take readings.  I’m thinking of exploring the AccuWeather API to add current weather with moisture readings, watering times, and amount.  I’m not ready to jump into this right now.

Appendix – First Readings

How exciting! The Moisture Puck stopped sending Moisture Info after 44 hours.  Good to know.  I’ll be excited to learn the difference when power management code has been added to the Moisture Puck firmware.  Charging the battery every 2 days is not something I want to do.

***Garden Controller***

RFM69 radio init OK!
RFM69 radio @915 MHz
…got reply from node 2 | RSSI: -91
—> Moisture Info <—
Moisture Reading: 366| Battery level: 4.22| Radio Temperature: 93
…got reply from node 2 | RSSI: -80
—> Moisture Info <—
Moisture Reading: 385| Battery level: 4.20| Radio Temperature: 104
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 394| Battery level: 4.17| Radio Temperature: 107
…got reply from node 2 | RSSI: -81
—> Moisture Info <—
Moisture Reading: 394| Battery level: 4.15| Radio Temperature: 107
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 391| Battery level: 4.13| Radio Temperature: 104
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 385| Battery level: 4.11| Radio Temperature: 98
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 373| Battery level: 4.09| Radio Temperature: 89
…got reply from node 2 | RSSI: -87
—> Moisture Info <—
Moisture Reading: 360| Battery level: 4.07| Radio Temperature: 84
…got reply from node 2 | RSSI: -87
—> Moisture Info <—
Moisture Reading: 348| Battery level: 4.04| Radio Temperature: 80
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 341| Battery level: 4.03| Radio Temperature: 77
…got reply from node 2 | RSSI: -83
—> Moisture Info <—
Moisture Reading: 334| Battery level: 4.02| Radio Temperature: 77
…got reply from node 2 | RSSI: -83
—> Moisture Info <—
Moisture Reading: 328| Battery level: 4.00| Radio Temperature: 75
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 320| Battery level: 3.98| Radio Temperature: 73
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 308| Battery level: 3.96| Radio Temperature: 71
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 304| Battery level: 3.94| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 298| Battery level: 3.94| Radio Temperature: 69
…got reply from node 2 | RSSI: -66
—> Moisture Info <—
Moisture Reading: 298| Battery level: 3.93| Radio Temperature: 69
…got reply from node 2 | RSSI: -71
—> Moisture Info <—
Moisture Reading: 293| Battery level: 3.91| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 382| Battery level: 3.89| Radio Temperature: 69
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 371| Battery level: 3.88| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 361| Battery level: 3.86| Radio Temperature: 71
…got reply from node 2 | RSSI: -74
—> Moisture Info <—
Moisture Reading: 356| Battery level: 3.86| Radio Temperature: 73
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 346| Battery level: 3.85| Radio Temperature: 71
…got reply from node 2 | RSSI: -79
—> Moisture Info <—
Moisture Reading: 371| Battery level: 3.85| Radio Temperature: 100
…got reply from node 2 | RSSI: -78
—> Moisture Info <—
Moisture Reading: 391| Battery level: 3.85| Radio Temperature: 104
…got reply from node 2 | RSSI: -78
—> Moisture Info <—
Moisture Reading: 389| Battery level: 3.84| Radio Temperature: 107
…got reply from node 2 | RSSI: -78
—> Moisture Info <—
Moisture Reading: 382| Battery level: 3.83| Radio Temperature: 107
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 372| Battery level: 3.83| Radio Temperature: 102
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 362| Battery level: 3.82| Radio Temperature: 100
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 352| Battery level: 3.82| Radio Temperature: 95
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 337| Battery level: 3.82| Radio Temperature: 84
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 326| Battery level: 3.80| Radio Temperature: 78
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 317| Battery level: 3.79| Radio Temperature: 77
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 311| Battery level: 3.79| Radio Temperature: 73
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 305| Battery level: 3.78| Radio Temperature: 71
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 301| Battery level: 3.78| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 298| Battery level: 3.76| Radio Temperature: 69
…got reply from node 2 | RSSI: -74
—> Moisture Info <—
Moisture Reading: 295| Battery level: 3.75| Radio Temperature: 68
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 293| Battery level: 3.73| Radio Temperature: 68
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 290| Battery level: 3.72| Radio Temperature: 68
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 289| Battery level: 3.71| Radio Temperature: 68
…got reply from node 2 | RSSI: -72
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.69| Radio Temperature: 68
…got reply from node 2 | RSSI: -72
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.66| Radio Temperature: 68
…got reply from node 2 | RSSI: -81
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.56| Radio Temperature: 68
…got reply from node 2 | RSSI: -86
—> Moisture Info <—
Moisture Reading: 278| Battery level: 3.56| Radio Temperature: 68
sendtoWait failed
sendtoWait failed
sendtoWait failed

Auto Irrigation Build Log for May 29th

Tags

, , , , ,

Where Project is At

Successfully sending Moisture Info packets from a Moisture Puck situated in Strawberry Swirl to a RFM69 Feather attached to my Mac within my house.

The Arduino Code/version I used is located at this GitHub location.  See Firmware Tests below for more info.

Moisture Puck

Here’s some Fusion 360 images of the Moisture Puck:

NewImage   NewImage

In my excitement, I forgot to take a picture of the insides of the Moisture Puck that is situated in Strawberry Swirl.  Here is an image of the Strawberry Swirl Moisture Puck:

NewImage 

  • Radio and micro controller:   I am using Adafruit’s Feather M0 RFM69HCW – 915 MHz for communication between the controller and the Moisture Pucks (Note the green dot.  This means 900 MHz.  I’ve had others with a red dot on the RM69 chip.  The red dot means it’s 433 MHz).

  • Moisture sensor: I’m using Funduino moisture sensors I had from last year.

 

 

 I bought several of these:

NewImage

Good better bestWhile the Funduino sensors are readily available and inexpensive, they are not robust and the “sensor legs” are short  The moisture sensor should be taking readings at the root level.  I could go the expensive/accurate route and explore using the Vegetronix VH-400 sensor.  But – whoa $40? Given accuracy is not required, for now I will continue to use the Funduino sensors and replace them each season.

Firmware Tests

Something that made testing easier was opening two separate copies of the Arduino IDE.  This way, each copy can use a different serial port.  This way, I can open a serial monitor for both feathers while I built the code.  To do this, I opened up a terminal and entered:

open -n -a /Applications/Arduino.app

Once the Feathers came in from Adafruit, I quickly wrote up some Arduino code to get a better understanding of communications between the Controller and one Moisture Puck.  I changed RFM69 libraries from using Felix’s to RadioHead’s.  I did this based on Adafruit’s recommendation.  My reasoning is I will be going to Adafruit for support.  It helps to use the same 3rd party libraries they use / recommend.

Firmware tests are based on the code located at this GitHub location.

First Readings

I have included the First Readings I am basing these comments on at the end of this post

Prior to watering, the moisture reading from the Strawberry Swirl moisture puck was 293.  After 8 minute watering, it was 382. Reading and watering was taken around 7AM.

The weather forecast for today (weather.com): Some clouds this morning will give way to generally sunny skies for the afternoon. High 78F. Winds W at 5 to 10 mph.

A question of interest: What is the moisture reading later in the day?  Given the difference in reading, how should the amount of watering time be adjusted (if at all)?

One thing that makes it difficult to answer this question is I did not include the Time of Day with the hourly logging of each reading.  I was able to backtrack and figure out the reading was slightly above 300.  This means there wouldn’t be a PM reading, but there would be an AM reading.  This seems a bit right, perhaps a bit on the low end. I will update the plan I have for the amount of time to water to 10 minutes from 8 minutes.

Waterproof Enclosure

A concern I had was if the container was enclosed enough to be waterproof.  While I haven’t opened up the enclosure to check, I was relieved to get a reading after watering.  If water is detected inside the enclosure when I open it up, I’ll see about adding a gasket or some other seal.

Temperature

(Note Doxygen documentation for RH_RF69 is located here).

Another concern of mine was whether it got too hot within the enclosure.  I’m using the temperature of the radio since this was easy for me to use.  The temperature values returned went from a low of 69˚F to a high of 104˚F.  While this range is acceptable – and it “feels” about right – I should heed the documentation made by Mike McCauley in the RH_RF69.h file:

/// Reads the on-chip temperature sensor.
  /// The RF69 must be in Idle mode (= RF69 Standby) to measure temperature.
  /// The measurement is uncalibrated and without calibration, you can expect it to be far from
  /// correct.
  /// \return The measured temperature, in degrees C from -40 to 85 (uncalibrated)
  int8_t temperatureRead();

 

  • I’m not sure the RFM69 is in standby mode when I’m taking the measurement.  I will figure this out and correct if needed.  Perhaps when temperatureRead() is called it puts the radio into standby mode? Dunno right now….
Here is the temperatureRead() code from RH_RF69.cpp:
int8_t RH_RF69::temperatureRead()
  {
  // Caution: must be ins standby.
  // setModeIdle();
  spiWrite(RH_RF69_REG_4E_TEMP1, RH_RF69_TEMP1_TEMPMEASSTART); // Start the measurement
  while (spiRead(RH_RF69_REG_4E_TEMP1) & RH_RF69_TEMP1_TEMPMEASRUNNING)
  ; // Wait for the measurement to complete
  return 166spiRead(RH_RF69_REG_4F_TEMP2); // Very approximate, based on observation
 

}

hmm…I assume setModeIdle(); puts the RF69 into standby mode?  If so why is it commented out?  According to the Doxygen documentationIf current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running, disables them.

What I am currently doing is documented in MoisturePuck2017.ino.

  • Calibrate?  How do I do that?  Not sure…and perhaps “unprofessional” of me, I’m ignoring the calibration comment since the readings look “about right.”

Battery Life

Ideally, the batteries would never have to be recharged.  Right now I’m not using solar power – although I’ll explore this….the focus here is on power management.

Power Management

The firmware currently running on the Moisture Puck has no power management optimizations.  Without power management, the battery needs to be recharged after about 40 hours.

The first reading I took yesterday afternoon:

…got reply from node 2 | RSSI: -91
—> Moisture Info <—
Moisture Reading: 366| Battery level: 4.22| Radio Temperature: 93

The Latest readings – about 39 hours later :

—> Moisture Info <—
Moisture Reading: 290| Battery level: 3.72| Radio Temperature: 68
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 289| Battery level: 3.71| Radio Temperature: 68
…got reply from node 2 | RSSI: -72
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.69| Radio Temperature: 68
…got reply from node 2 | RSSI: -72
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.66| Radio Temperature: 68
…got reply from node 2 | RSSI: -81
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.56| Radio Temperature: 68

show the battery should be recharged as discussed in Adafruit’s documentation:  Lipoly batteries are ‘maxed out’ at 4.2V and stick around 3.7V for much of the battery life, then slowly sink down to 3.2V or so before the protection circuitry cuts it off. By measuring the voltage you can quickly tell when you’re heading below 3.7V.

The Battery University web page provides awesome material on LiPo batteries.  Here’s their image of a standard LiPo discharge curve:

A Question of Interest: How long before this code sinks below 3.2V?

Code Additions

Things I’ll add to the code in an attempt to maximize the battery life:

  • Call RH_RF69::sleep() .  See the Doxygen documentation.  Also Adafruit’s documentation notesIf you put the radio to sleep after transmitting with radio.sleep(); rather than just sitting in receive mode, you can save more current, after transmit is complete, the average current drops to ~10mA which is just for the microcontroller.  I added code into the Moisture Puck Arduino code.
  • Stuff on My Virtual Life’s blog post for October 11, 2016.  The post discusses power management techniques specific to Feather M0’s.  I haven’t read it enough to do anything with it…but looks promising.

Shopping List

Explore Solar Powered

The shopping list includes:

Moisture Pucks

Appendix: First Readings

***Garden Controller***

RFM69 radio init OK!
RFM69 radio @915 MHz
…got reply from node 2 | RSSI: -91
—> Moisture Info <—
Moisture Reading: 366| Battery level: 4.22| Radio Temperature: 93
…got reply from node 2 | RSSI: -80
—> Moisture Info <—
Moisture Reading: 385| Battery level: 4.20| Radio Temperature: 104
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 394| Battery level: 4.17| Radio Temperature: 107
…got reply from node 2 | RSSI: -81
—> Moisture Info <—
Moisture Reading: 394| Battery level: 4.15| Radio Temperature: 107
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 391| Battery level: 4.13| Radio Temperature: 104
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 385| Battery level: 4.11| Radio Temperature: 98
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 373| Battery level: 4.09| Radio Temperature: 89
…got reply from node 2 | RSSI: -87
—> Moisture Info <—
Moisture Reading: 360| Battery level: 4.07| Radio Temperature: 84
…got reply from node 2 | RSSI: -87
—> Moisture Info <—
Moisture Reading: 348| Battery level: 4.04| Radio Temperature: 80
…got reply from node 2 | RSSI: -84
—> Moisture Info <—
Moisture Reading: 341| Battery level: 4.03| Radio Temperature: 77
…got reply from node 2 | RSSI: -83
—> Moisture Info <—
Moisture Reading: 334| Battery level: 4.02| Radio Temperature: 77
…got reply from node 2 | RSSI: -83
—> Moisture Info <—
Moisture Reading: 328| Battery level: 4.00| Radio Temperature: 75
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 320| Battery level: 3.98| Radio Temperature: 73
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 308| Battery level: 3.96| Radio Temperature: 71
…got reply from node 2 | RSSI: -85
—> Moisture Info <—
Moisture Reading: 304| Battery level: 3.94| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 298| Battery level: 3.94| Radio Temperature: 69
…got reply from node 2 | RSSI: -66
—> Moisture Info <—
Moisture Reading: 298| Battery level: 3.93| Radio Temperature: 69
…got reply from node 2 | RSSI: -71
—> Moisture Info <—
Moisture Reading: 293| Battery level: 3.91| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 382| Battery level: 3.89| Radio Temperature: 69
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 371| Battery level: 3.88| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 361| Battery level: 3.86| Radio Temperature: 71
…got reply from node 2 | RSSI: -74
—> Moisture Info <—
Moisture Reading: 356| Battery level: 3.86| Radio Temperature: 73
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 346| Battery level: 3.85| Radio Temperature: 71
…got reply from node 2 | RSSI: -79
—> Moisture Info <—
Moisture Reading: 371| Battery level: 3.85| Radio Temperature: 100
…got reply from node 2 | RSSI: -78
—> Moisture Info <—
Moisture Reading: 391| Battery level: 3.85| Radio Temperature: 104
…got reply from node 2 | RSSI: -78
—> Moisture Info <—
Moisture Reading: 389| Battery level: 3.84| Radio Temperature: 107
…got reply from node 2 | RSSI: -78
—> Moisture Info <—
Moisture Reading: 382| Battery level: 3.83| Radio Temperature: 107
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 372| Battery level: 3.83| Radio Temperature: 102
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 362| Battery level: 3.82| Radio Temperature: 100
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 352| Battery level: 3.82| Radio Temperature: 95
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 337| Battery level: 3.82| Radio Temperature: 84
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 326| Battery level: 3.80| Radio Temperature: 78
…got reply from node 2 | RSSI: -75
—> Moisture Info <—
Moisture Reading: 317| Battery level: 3.79| Radio Temperature: 77
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 311| Battery level: 3.79| Radio Temperature: 73
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 305| Battery level: 3.78| Radio Temperature: 71
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 301| Battery level: 3.78| Radio Temperature: 69
…got reply from node 2 | RSSI: -76
—> Moisture Info <—
Moisture Reading: 298| Battery level: 3.76| Radio Temperature: 69
…got reply from node 2 | RSSI: -74
—> Moisture Info <—
Moisture Reading: 295| Battery level: 3.75| Radio Temperature: 68
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 293| Battery level: 3.73| Radio Temperature: 68
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 290| Battery level: 3.72| Radio Temperature: 68
…got reply from node 2 | RSSI: -73
—> Moisture Info <—
Moisture Reading: 289| Battery level: 3.71| Radio Temperature: 68
…got reply from node 2 | RSSI: -72
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.69| Radio Temperature: 68
…got reply from node 2 | RSSI: -72
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.66| Radio Temperature: 68
…got reply from node 2 | RSSI: -81
—> Moisture Info <—
Moisture Reading: 287| Battery level: 3.56| Radio Temperature: 68

2017 May 20 – June 20 Backyard Auto Irrigation Update

Tags

, , ,

Last year, I started an auto irrigation project for my backyard.  This blog post documents this year’s one month focus (May 20th to June 20th) evolution of my backyard auto irrigation project.  Subsequent blog posts during this period will be build logs as the project evolves.  Hopefully by the end I will be gorging on fruits and vegetables. 🙂

Thanks To Those That Went Before

Hilary Dahl and Kellie Phelan for their excellent Encyclopedia Podcast.  They exuberantly share their knowledge about growing and are masters at creating a community spirit.  I learn a lot not only from the podcast but also from participating in the Slack Channel.

Backyard Growing Areas

Rather randomly and with only minor consideration of sun movement, I have three spots in my backyard that I plant vegetables that need to be watered.  I’ll start calling these:

  • strawberry swirl – here I am growing Seascape Strawberry Bndl of 25 [SPRING] strawberries from Rain Tree nurseries.  Why these? I learned from the Encyclopedia Botanica podcast Episode 37: Strawberries the difference between June-bearing and Everbearing.  I wanted Everbearing strawberries.  I chose Rain Tree nurseries because members of the Encyclopedia Botanica Slack Channel had bought strawberries from them and highly recommended.  I chose Seascape because the description made me drool and I think at the point I bought them other Everbearing varieties had been snatched up.

I snagged this image off of Google Earth.  It seems a bit old because the area identified as lower deck uses cold frames.

GoogleEarthPointingOutIrrigationSpots

 

NewImage

Strawberry Swirl Location 

NewImage

Moisture Puck at Strawberry Swirl Location

  • Upper Deck – I have one area with snap peas, one area with cucumbers, and one area – I call the holding area because I put stuff there thinking I might transplant them somewhere else.  Currently there are tomatoes, rosemary, lavender.
NewImage
  • Lower Deck – One cold frame contains potatoes spaced too close together, carrots, and a third cold frame that currently has succession lettuce I planted too late.  I think I’ll plant carrots here because I love carrots.  I love carrots so much my skin is orange.
NewImage

The Goals

One goal that is core to everything is learning.  I am excited to evolve my knowledge of:

  • gardening.
  • hardware and software that I can put together to enhance my abilities.
  • building and putting together a complete solution to a challenge – in this case giving me time back as well as growing healthier plants.

From the Perspective of a Gardender

From my view as a gardener, my goals revolve around desperately trying to grow the most abundant and tastiest crops:

  • Save a significant amount of my time from having to drag out the hose and go around to the different spots within my backyard constantly watering.
  • Water the plants when needed, preventing overwatering and under watering.  Either of which can at the best lower the production and at the worst kill the plants.
  • Use only the amount of water needed.  
From the Perspective of a Hardware/Firmware/Mechanical Engineer:
  • Automatically water three different areas of my backyard when the soil is dry enough to cause plant stress.
  • Water only in the early AM or early PM.
  • Minimize the number of times the battery needs to be recharged (i.e.: maximize battery life).
  • Detect a malfunction.
  • Post analyze wet/dry soil behavior.
  • Stretch goal: inject the correct level/type of fertilizer into the irrigation.

The Equipment Setup

I used Google Draw to illustrate the setup:

Each planting area has a Moisture Puck (represented by the green dot).  The different colors – green, blue, and red – represent different communications going on:

  • green: communications between the Controller and a Moisture Puck.  The Controller has the same conversation with each Moisture Puck.  It’s a simple question from the Controller happening early AM or later PM asking the Moisture Puck to return it information on whether watering is needed.
  • blue: if the Controller decides the area being monitored by a Moisture Puck needs watering, it communicates with the spigot turning on/off the valve that is handling watering for that area.
  • red: the Controller sends me the moisture readings, inside temperature, and battery level of the moisture puck.  If the controller detects a problem – for example, the battery needs to be replaced, the temperature is too hot for the electronics within a Moisture Puck, or it hasn’t received readings for awhile… – it sends me an alert so I can follow up and fix the problem.

When To Water

The watering system starts watering when an analog value is read and interpreted by the code to mean the water is dry enough to water.  But what does “dry enough to water” mean?  I will be using the 1 to 5 plug tray moisture scale I learned about when I took a horticulture course from Dr. Fisher at the University of Florida.  Since watering only happens at most twice a day, I’m going to set “dry enough to water” to be within the 3 range of the tray moisture scale.  From my testing,

NewImage 

this will be when a moisture reading of 300 or less is read from the analog pin.

How Long To Water

As with when to water, how long to water is subjective.  My current plan is to water for 15 minutes.

 

…And off I go….

 

Rick’s comments on Pinch Valve Exploration

THANK YOU RICK for your comment.  The night before I read your comment, I was talking to my husband about how writing this blog took time away from building stuff.  Rick’s comment is a KEY REASON I write the blog – to learn from others who have A LOT more knowledge than I have.  It is totally exciting to evolve a skill to a level in which the beauty of the mechanics combine with a design that …well, solves a problem.  I find Rick’s comment inspiring so….again, THANK YOU RICK.  THANK YOU.

I spent last week getting older as well as evolving my current design of the pinch valve.  So what are the results?

Frustrated EPIC FAIL

drip..drip…drip….

NewImage

And then I thought…yah know what?  I’m stopping my current goal of automating calibration (meaning I’d need solutions/containers for pH4, pH7, and an EC calibration solution) as well as checking the pH and EC outside of the nutrient bath.  If I just leave the pH and EC probes in the nutrient bath, I don’t need any of this stuff.  Talk about a simplification.  I only got to this added complexity because I wanted to evolve my knowledge of valves.  AND I think logically the pH probe would degrade faster if it is always submerged within a bath full of salts smacking on it’s delicate membrane.  That and constant calibration would give accurate results.  But given the range of pH and EC values that are acceptable, I don’t need great accuracy…so bah-bye clean pH and EC probe.  Bah-bye always on calibration….back to what I was doing before…dangling the probes within the nutrient bath…

and yes…but wait…Rick then wrote a comment that interrupted this line of thinking.

Rick’s Comments

Rick noted:

  • consider changing the thickness of the tubing – Shore Hardness.  Now here’s something about learning without guidance…I was going to give this a twirl but 1) didn’t know googling “Shore Hardness” would evolve my knowledge on tube thickness.  And I didn’t know what kind of tubing to get.  Rick recommended this latext (surgical) tubing.

To explore this, I ordered:

NewImage

  • try a shorter arm on the servo (increases the available torque).  Oh..right…yah!  Will do.  Again I question what I was doing during science classes.  

NewImage

I assume I was taught this?  But in what context?  As I get older, it turns out context is so important to empathy and interest..yet I diverge.

Rick asked about using a peristaltic pump…and indeed, I have used these in the past.  I know how these work and yah, I could use it…I was hoping for something less bulky.  I would be using peristaltic pumps in pH UP, DOWN, and EC adjustments within the nutrient baths within the adjustment section of the Leaf Spa.  I have done this in the past but haven’t yet added auto adjustment.

  • consider a different design for the container/test tube (whatever) where the probe will be inserted to take a measurement. Rick’s comments are detailed and I might have misinterpreted, but this got me thinking.  Yah – instead of separate chambers, one block-o-food safe plastic with holes drilled in them where the solution will drip into.  Once measurement is done, use a servo to tilt the block 180˚ and dump the solution out.  The challenge I was thinking about was fluid flow when the servo is in rotation.  The potential of solutions intermingling – which is not what I want.  I thought at this point I could experiment with ways of directing fluid away from one of the holes….hmmm….

The above is my interpretation.  Here are Rick’s words: “Regarding your test chamber/test tube assembly … take a block of HDPE (high density polyethylene, say 1″ x 7″ x 5″, drill 5 (or more) round-bottom holes part way through, and then mount this drilled block on pivots, so you can use your existing servo to dump the contents into a waste pan after you calibrate. The round bottom hole can be created with a 1/2″ box core router bit (woodworking tools are very compatible with HDPE). HDPE is pretty insensitive to most of the chemicals you’ll be comfortable working around, is rated food-safe (FDA), and is inexpensive.The round bottom prevents gunk (highly technical term) from collecting in the crevice a flat-bottomed hole would provide.
When sampling your nutrient solution, you can tilt the test chamber 45°, have a channel milled on the side of the test chamber to route the nutrient solution back into the reservoir until you have flushed the tubing and have a good sample available. Stop the pump, rotate the test chamber vertically, and then fill, test, and dump (in this case you can choose to dump the tested nutrient solution back into the reservoir (slight risk of contaminating your nutrient solution), or dumping it directly into the waste pan (slight volume loss, but absolutely safest for the customers.”

THANK YOU RICK

Once I get the tubing in I will most likely give yet another go at automating measurement.  But always I will be thankful for the knowledge and thought process Rick provided.