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.