Thursday, December 8, 2016

Clockwork Coop Version 2: A Good Decision

Remember the decision to use two door switches on this post?  It turns out this was a good decision.  Things seemed to operate very well when everything was installed.  But I soon after I started using remote manual controls I got an error.  It seems the coupler holding the threaded rod onto the shaft of the stepper motor failed and the door fell into the closed position.  If I had used a single switch to detect the door state, I might not have noticed the error.  Instead, I went to investigate and quickly realized I needed an adhesive to secure the coupler to the stepper motor.  After a quick fix with some silicone caulk I was back in business.

Clockwork Coop Version 1 Mechanics Second Try

After several failures using DC motors, I wanted explore other options to open, close, and secure the door.  I decided to investigate a stepper motor and lead screw mechanism.  The door would open and close exactly as before, but the new setup had several advantages.

1)  The door was lowered under power so there was less chance of it getting stuck
2)  The door could be "locked" at any location simply by stopping the motor.  This meant the mechanics was simpler
3)  The stepper motor I chose had more power than my DC motor and could raise and lower the door faster.

I used a pair of A4988 driver chips under full-step mode to run the stepper motors.  Initially I just used two pins for each chip, but I realized the motors were drawing a lot of unnecessary power this way.  I decided to use the enable line on the chips to reduce power consumption but this would require 6 total pins (when I only had 5 available).  However, since I wasn't using the serial port for anything, I could re-purpose the TX line (D1) as one of the 6 pins.

I quickly realized an installation and maintenance problem needed to be solved.  How can the door be easily attached to or detached from the lead screw?  Additionally, there's a requirement to easily disengage the door from electronic control in the case of a power outage.  How do I make this easy?

The lead screw setup works by spinning a long threaded rod that has a nut attached to it.  The nut is trapped by a bracket that prevents it from spinning.  This converts the spinning motion of the rod into the linear motion of the trapped nut.  So, I designed a bracket that traps the nut and attaches to the door.  The bracket was made out of two parts.  One part attached to the door and allowed the threaded rod and nut to fully pass into it.  The second part snapped into the first in such a way that the threaded rod was held firmly against the bracket.  This fully captured the rod and nut while being easy to disengage.  I'm very pleased with this setup and it made installation a breeze.  I still need to design a latch to hold the door open if it is disengaged during a power outage.  In that situation, I can open and close the outer doors manually until power is restored and the door can be re-engaged.


Clockwork Coop Version 1 Mechanics First Try

Since the micro controller pin functions had been determined and DC motors selected, it was time to work on the door mechanism.  I designed a simple mount for the DC motor and a spool for it to hold a length of 20 pound test fishing line.  The door itself was made from 3/8 plywood.  I also made a wooden frame and guide rails so the door could be lifted/lowered by the motor.  I designed a mechanism to lock the door in place when it was fully lowered.

During testing, things didn't work out well.  The lift line was not precisely centered and caused the door to tilt as it was lifted and lowered.  Although, I suspect mild warping of the wood rails may also have played a role.  This meant the door would catch and stick when it was being lowered.  Similarly, the locking mechanism was often misaligned and caused multiple errors. Fortunately, I had programmed several error-detecting algorithms and it was easy to identify the problems when they occurred.

But, even though several fixes were made, the door remained unreliable.  So, I decided to see if there was a better path forward.

Clockwork Coop Version 1 Micro controller Capabilities

In order to design the mechanics, first we need to decide what sort of motors and sensors will drive the doors.  And, in order to decide on that, we need to know what capabilities our microcontroller has.  I'm using a Moteino R4 from lowpowerlabs.com.  And 5 pins on that controller are dedicated to running the transciever.  There are also 2 extra analog pins than a normal Arduino (A6 and A7) so I'll use one of those for light sensing.  This leaves 13 multipurpose pins left over (D3-D9 and A0-A5).

I decided to use two limit switches to detect each door's open and closed state.  This would require a total of 4 pins.  I considered using a single switch for each door but decided it would be too difficult to detect errors with only a single switch.  Imagine, for example, if I had used a single switch to detect open and closed.  This is easily accomplished by placing a switch near the top of the door and placing contacts on the door that would trigger the switch when it was either fully opened or fully closed.  But, what happens if the door experiences a mechanical failure while opening that causes it to drop back into the closed position?  The same switch would be triggered but the software would assume the door was now fully opened.  Even using known opening and closing times doesn't help since the door could drop into place just as it reached the point where it would indicate open.  Nope, we will need 4 pins to sense door state which means we are down to 9 available.

One of the door control requirements was to manually control the door locally.  Since I'll have 2 doors, two buttons will be used for this purpose.  This requires 2 more pins reducing the remaining count to 7.  If I had more doors, I might consider using an I2C keypad (this also requires 2 pins).

The indicator light and interior light require 2 more pins bringing us down to 5 pins.

With 5 pins, I could control a single stepper motor using the stepper.h library included with the Arduino IDE.  But that's not enough for 2 doors unfortunately.  However, if I had been clever at the time, I might have included a demultiplexer to route the 4 stepper control pins to the correct motor using the 5th available pin.  But I wasn't.  Instead, I abandoned the idea of using a stepper motor and considered using a DC motor instead.  I would control the DC motor using an L293E H-Bridge.  The Bridge required 2 input pins per motor (on/off and forward/backward) and could control up to 2 motors.  Additionally, I could get feedback about the motor performance from the sense pins.  This required 2 Analog pins and could be provided by one of the extra pins on the Moteino and one of the Analog multipurpose pins.  This was the initial plan.





Tuesday, December 6, 2016

Clockwork Coop Iterations

Finally, let's talk about versioning.  This project has a lot of requirements and I'd prefer to get things working before I get them "right".  So, I've divided the project into several iterations with explanations.  Here they are:

1)  Manual Local Control.  The gate to access the chicken run is, perhaps, not in the most convenient location.  And, while local door controls would still require more trips to the coop than I'd like, at least it's a shorter trip and doesn't involve fumbling with the gate.  Additionally, this is the version where the mechanical aspects of door control will play their biggest part and be the most time-consuming.

2)  Manual Remote Control.  Once all the mechanical bits are figured out, the next thing to attack is eliminating all those extra trips.  Remote control will do just that and will focus on the creation of the remote base station.

3)  Fully Automated Control.  Now that the coop controller and base station are talking, remotely configuring the coop controller to fully operate the doors automatically (based on the day/night cycle) is the next task.

4)  Lighting control. Establishing the length of darkness each night is really about optimizing egg production during the winter months so that will be version 4.  Additionally, if the previous versions are complete, this should just be a software update.

5)  Environment controls. This version focuses on reporting the various environmental measurements to the base station so the user can take action when needed.


A Clockwork Coop

Now that we can send information and move things, there are so many things we can do.  I decided the first project will be to free up some time and offer convenience maintaining a small flock of backyard chickens.

There are a variety of ways to keep chickens  but I have opted for a small coop with a fenced and netted area for them to roam.  This protects them from predators (including bald eagles in my area) and meets my municipality's legal requirements (chickens cannot roam freely here).  

Chickens naturally return to the coop to roost at night and they are let out to roam in their run during the day.  But, letting them out in the morning and then locking up after them at night takes time.  And, in the Puget Sound area, it rains occasionally.  Since I'd rather not fumble with locks after dark or in the early morning (or while it's wet or cold) and since I'd like to have fewer visits to the coop each day, I think an ideal first automation project is to control the opening and closing of the coop doors.

Before we dive right in, let's consider some goals.  To make things simpler, I've divided goals into 4 parts:  Door control, Lighting Control, Environment monitoring, and user interface.

Door Control
1)  Doors shall be tamper resistant when closed (so predators won't get in).  To be more specific, since the doors open like a portcullis, a predator should not simply be able to lift it open.
2)  The motors should not need to draw power in order to maintain the door in an open or closed state.
3)  A method for manually controlling the door should be available at the coop site.
4)  A method for disengaging the door from electronic control (in the case of a power outage for example) and latching it open will be available.
5)  A way of detecting when to automatically open and close the doors (at daybreak and nightfall) will be available
6) Detection of daybreak and nightfall will be robust and not influenced by temporary conditions such as shadows or bright lights.
7)  An easily visible indicator light will alert the user to the current door state.  Open, closed, transitioning, and error conditions will be indicated.

Lighting control
1)  An interior light will be provided.
2)  The light will be operated remotely (no local manual control)
3)  It should be configured to turn on some period of time after nightfall (establishing a night-length)
4)  It should turn off when the coop opens at daybreak.

Environment montioring
9)  Feed and water levels as well as temperature and humidity will be monitored and reported to the user.
10)  A heater will warm the coop if the interior temperature is too cold.
11)  Ammonia levels will be monitored and reported to the user.

User Interface
12)  A remote base station will be provided it will:
13)  Report all door and environmental conditions mentioned above.
14)  Provide manual door and light controls.
15)  Allow the user to manage configurable parameters (for example, what light level will determine daybreak and which door will open)
16)  Add timer control to the coop opening and closing.
17)  Keep time accurately (no more than a minute drift every 2 weeks.
18)  Display everything in an intuitive easy-to-read manner.



Monday, November 21, 2016

Motors are for Moving

Now that we can move information around, let's talk about moving stuff!  I'll discuss three motor types and my strategy for using them.

First, servo motors.  Servo motors can operate in at least two modes (continuous or positional) but I'll focus on the positional mode here.  A servo motor in positional mode rotates to a set position based on an input signal.  This signal is typically a 50Hz square wave (20 millisecond period) where the time spent at Vcc varies between 1 and 2 milliseconds.  If that last sentence didn't make a lot of sense, there's no need to worry.  The Arduino platform makes this very easy.  Just include servo.h in your code and write a value between 0 and 180 to rotate the motor to a position between 0 and 180 degrees.  Follow this link or this link for more details.

Next are DC motors (not the brushless kind, that's a different post).  DC motors are either on or off and run either forward or backward.  However, most motors should not be connected directly to a microcontroller for a variety of reasons including insufficient power to drive the motor and possbile damage to the controller.  Instead, the microcontroller should send signals to some sort of motor driver.  There are a variety of ways to do this.  For my purposes, I chose to write a new library that takes advantage of the L293 quadruple half-H driver chip.  Once the library is included in the code, just call methods to run the motor forward, backward, or off.

Finally Stepper motors. If you want to know more about stepper motors, check out this wikipedia article.  I use bipolar stepper motors with 4 wires and therefore, a microcontroller would need 4 outputs to control it (through some sort of driver of course) if you used the stepper.h library included with the Arduino platform.  However, there are drivers that only need 2 inputs to turn the motor and I chose the A4988 driver for my purposes.  However, I was unable to find a good control library that met all my needs so I created one with the following features:

1)  Configurable velocity and acceleration/deceleration.
2)  Interrupt driven motor steps (so the microcontroller can do other things.
3)  Methods for executing some number of steps.  These are either blocking or non-blocking (done in the background)
4)  Methods to wait for the motor to finish its current task.
5)  Continuous mode.  This allows the microcontroller to start the motor and then do other things.  During this time, the motor will not stop regardless of the number of steps it makes.  The microcontroller can stop or decelerate the motor later but the number of steps executed will likely be unknown
6)  Configurable capacity for multiple motors
7)  RPM mode.  Instead of doing some number of steps, do some number of rotations.

I used the timer 1 interrupt to control the motor (since Arduino uses timer 0 and node communications uses timer 2).

This took a fair bit to develop (particularly getting the timing for deceleration right.  I must have tried at least 3 different ways of doing that).  And, the interrupt that manages the motor takes a fairly long time unfortunately (most interrupts are short).  However, most things seem to work well in spite of the time consuming interrupt.  Here is the library.


Thursday, November 17, 2016

A Cordial Chat Between Digital Friends

I realized that many of my projects would need to be wireless and that I wanted a consistent and flexible way to communicate between microcontrollers.  So I developed the Node Network Object which can be included in any Arduino sketch.  Since I first developed it, I've created a few different flavors and I have updated it as the hardware changed.  But, a number of things have remained consistent.

1)  A readable text-based format for sending and receiving messages.  Let's say I wanted to send a message between two microcontrollers about the environment.  I'll title the message "environment" and perhaps I'll send 3 numbers indicating temperature, humidity and light level.  With the text based protocol the message would look something like this:

     environment|temperature:45;humidity:60;light:1013

That's a lot of text to send for 3 numbers!  So let's abbreviate to keep things small (and therefore quick).

     env|T:45;H:60;L:1013

And, since the labels for each number are optional (they're nice when auto-connecting to a host computer but that's another post). the entire message could be VERY short:

     e|45;60;1013

In the future I want to add the ability to send data objects.  The new message might look like this:

     e|o:042D3C03F5

It looks longer, but it's actually a few bytes smaller than the previous message since each byte is represented by two characters when I write it out.  Here, "o" would be a reserved label indicating an object.  The next byte (0x04 in this case) would indicate the object size in bytes (a maximum of 255 bytes) and the following bytes would be object data.

2)  Easy setup.  When the node library is included, only a few lines of code are needed to get everything working.
a)  Call nodeInit with the encryption key, the network ID, the node ID, and the transceiver type:

 node.nodeInit("MYENCRYPTIONPASS", 10, 2, RF69_915MHZ);

b)  Register command handlers.  These provide places for different commands to be processed and they look like this:

 node.handler.registerCommandHandler("env", environmentUpdate, "T,H,L");

In this case, when the controller receives an "env" message, it will call the method "environmentUpdate" and expect data fields T, H, and L.

3)  Easy handling.  The command handler methods take the following format:

int environmentUpdate(char* message, int length){
  node.handler.setMessage(message, length);  //do this if you want to use values in the message
  char* value = node.handler.getNextMessageField(); //do this for every value and label
  int num = atoi(value);  //convert the values you want to use
  return 1;
}

When a registered command is received, it's associated command handler gets called so the message can be processed.

4)  Easy scheduling.  Since the radio is a shared resource, it needs to be scheduled if you want to send out a message.  Whenever part of your program needs to use it, just call the addQueueEvent method on the node:
node.queue.addQueueEvent(sendEnvironment, 0, 3, 45, 60, 1013);
The first parameter is the method to call, followed by the number of milliseconds to delay before calling it (0ms in this case but it can be up to 60 seconds).  The next parameter is the number of optional values to pass to the sendEnvironment function.  The maximum number of these parameters is configurable and I recommend keeping it small.

5)  Simple Sending.  Event methods look like this:
void sendEnvironment(unsigned int values[])
Values passed in will be in the values array and MUST be positive integers.  The job of the send method is to create a string as seen in #1 above and place it into the node's radio buffer and remember the message size in bytes (use sprintf for this).  Then call sendToNode.  Your message code might look like this if you wanted to send the message to node 1:

void sendEnvironment(unsigned int values[]){
  int msgSize = sprintf(node.getBuffer(),"env|T:%i;H:%i;L:%i",values[0],values[1],values[2]);
  node.sendToNode(msgSize,1);
}

6)  Loop maintenance.  Once all the above is set up on both the sending and receiving end, each microcontroller must make continuous calls to the "nodeLoop" function.  This works much like the standard arduino delay function and takes an argument for the number of milliseconds to wait.  I do not recommend a value under 300 milliseconds.  During this time, messages will be received and processed, queued events will be triggered and called, and messages will be sent.  An example Arduino loop method might look like this:

void loop(){
   //read the temperature
   //read the humidity
   //read the light
   //put the send environment event in the queue

   //wait one minute
   node.nodeLoop(60000);
   //even though we wait a minute, a lot can happen if messages are received.  Especially
   //messages that require a response.
}

This microcontroller would send its environment data every minute (see #4 and #5 above) and the other would have a method to handle that data (see #3 above).  More complex interactions can be achieved if one microcontroller periodically requests the data and the other only sends it upon request.

Ok, that is a LOT.  You should be able to find a short video showing how quickly this sort of interaction can be written from scratch here.  The code repositories are located below:

Node Code
Command Handler Code
Event Queue Code
RFM69 Library (from lowpowerlabs.com)

Also, documentation can be found here.






       


Tools of the Trade

While my educational background includes a lot of engineering and a fair bit of biology, my professional experience is in software development.  The one thing I've learned from all this is that tools are always changing.  So, we should expect that the tools I talk about here won't necessarily be the same tools I'll use in every project.  But let's talk about the tools I'm using to get a decent level of control now.

Arduino
Yes, Arduino.  These small microcontrollers are in nearly every electronics project you find online these days.  And, there are several good reasons for that.  They are simple to use, flexible, and have a great community of fellow users who are eager to support new users.  Programming is also simple and uses the c/c++ language.  And, with several cheap clones available, they are pretty inexpensive too.

Moteino
Moteino is an Arduino variant that is about the size of two quarters (smaller if you don't solder on all the headers).  Currently in revision 4, these micro controllers contain an RFM69 transceiver for wireless communications and may optionally include a 4mbit flash chip.  I chose this variant for its small size and integrated wireless capability.

Electronics
I use a basic multi meter that can measure ohms and volts DC.  I don't think I've ever used it to measure amps and rarely use it for AC voltage.

I use a variable DC power supply and rarely exceed 12V.

I use a 200MHz Oscilloscope.  I do a fare bit of debugging during development (how long does that interrupt take anyway?) and there's just no better tool than an oscilloscope for some situations.

Fabrication
I use a 3D printer - extensively.  Seriously, my desk is littered with early prototypes, half-baked ideas, and a few spectacular failures that serve as my own personal warning to never do THAT again.  Hmm...  Maybe I should clean this place up?  And, since I'm primarily a programmer, I like the free Openscad software package to design parts.  Do YOU NEED a 3D printer?  Well, probably not.  I bet I could get away with using wood for a lot of the things I make but 3D printing parts is often very satisfying and, if done properly, produces a nice result.

Soldering Iron
This is a must for any electronics project.  While I'm developing, I use a solderless breadboard so I can make changes easily but, when it comes time to deploy, I solder a permanent circuit together.

Introduction

Welcome to A Clockwork Garden.  This blog is about a variety of science and engineering projects which will focus on the garden (well, mostly).

Gardens are amazing things.  Most people think of a garden as a small-to-modest sized space in which to grow vegetables in their back yard.  Gardeners improve their soil with compost, fertilizer, tilling, and weeding.  They plant seeds in the spring and watch them sprout an grow.  Their care continues until the harvest is ready and fresh fruits and vegetables make it to the dinner table.

This is certainly ONE type of garden.  But there are others too.  For the purpose of this blog, a garden is a purposeful effort to control an environment so desirable living things will grow.  While fruits and vegetables are still important, our garden list now includes everything from microbes to mammals!

But, as a gardener of any type can tell you, this can take a lot of time.  And, if your environment needs fine control, it can be a full time job - just ask a research microbiologist!  So, why not automate some of the more mundane, time consuming tasks?  Instead of laboring over fruits, enjoy the fruits of your machine's labor.

This seems like a noble goal (and it's probably a theme in any Utopian science fiction story).  The problem is it takes an enormous amount of time to automate any task.  And, when you add in maintenance on the machines, small-scale automation doesn't often save time.  But, sometimes it makes a particular garden possible.  And, for me, it makes gardening that much more fun.