Saturday, December 15, 2012

Really Nice Gauges

Recently I was shown an extremely nice set of gauges by a fellow on the Arduino forum, graynomad.  They were metalic looking and had a great set of parameters to mess with.  Well, I couldn't resist, and decided to figure out how to use them and somehow get them on this site.

Well, I sort of got it working.  It seems that Google (Blogger) has a problem with iframes, and that's pretty much the only way to include one of these.  The problem is that it messes with the scrollbar in Chrome, their own browser.  I'm not sure how they show up in IE, except they won't show up at all in IE8 because it doesn't support canvas.  For something this complex, the canvas is the only practical solution short of using something like Flash.

So, if you're using Chrome, look over to the right where the scrollbar is, notice it doesn't look right?  If you put your mouse over there and click, you'll see that it actually works, but just doesn't look right.  I don't have a solution to this yet.

But, let's look at the gauge.  Notice it has an LCD display and a moving hand.  When my energy usage goes above the red indicator (it's on the dial), the little red LED will light up.  These are all parameters that can be set for the gauge.  I chose the brass look simply because it fit my taste, there are many, many combinations possible.  The gauge is sort of real time.  What I do is update it every 10 seconds from my datastore at Cosm which is updated every 60 seconds.  So, every minute or so, it will be updated to reflect the current power usage at my house.  I plan on working with these gauges quite a bit more; they're just too nice to leave alone.

So, if you want to use them also, or just admire the tremendous amount of work that went into creating them, they're known as the SteelSeries and apparently were initially designed for weather displays.  Just go to Google and start looking.  If I gave a URL, it would be the wrong one or outdated or something, so check it out yourself.

And, sorry about your scrollbar; it'll come back when you go leave this page.

Thursday, December 13, 2012

Let's Talk About Septic Tanks

Nice subject....right?  Since I live out in the sticks, there are no services here except power and phone.  I have my own well, propane tanks, and septic system.  Since it's a relatively new septic system, it has all the new and improved features.  This usually means there is more to worry about and take care of, and at least in my case, this is certainly true.

My first problem came a few years ago when sewage backed up into the house.  Since I had only a general idea where the tank was actually located, the service guy had to hunt a while to find the access ports on the tank.  See, newer septic tanks have two access points for different stages of sewage treatment and both of them have to be pumped out.  When he uncovered it, I found out I had a filter inside the tank.

Yes, there is a filter that stops solids from making their way out into the leach field.  The filter had plugged up and was not releasing fluid into the leach field.  That filled the tank and caused me to have a mess in the bathroom.  Nice.  So, obviously, the tank filter needed to be cleaned and the tank pumped out to restore service.  So, I had the service company install risers with nice green covers on them to allow (relatively) easy access to the septic tank so I could clean the filter.  Total bill, around $800.  Not something I wanted to repeat very often.  Here's a picture that illustrates the kind of thing I'm talking about:
All you see at ground level is the green plastic covers.  Just remove these to service the tank.  Here is what the filter looks like:
To clean it, just grab the blue handle, pull the filter out, and bang it around.  Once you knock the debris off, rinsing it is easy, just spray it down with a water hose.  Here is the basic configuration of the tank and the various parts inside:
Except I have a riser on both sides so each tank can be easily pumped out.  Notice the 'sanitary tee' on the inlet side?  That causes problems as well; more on that below.

Fast forward a year.  I had company with kids and the darn tank filled up again.  I opened the wonderful new access points, and sure enough, the tank was full again.  Called the same service company and they came out and cleaned it out for me again.  I chose this solution to get the house working again since I had company at the house that needed to use the bathroom.  Total bill, $340.

A couple of weeks ago, it happened again.  This time I didn't have company, so I went out and cleaned the filter.  The tank immediately started to drain into the leach field and drop the level, and by the next day, it was back to a normal level.  No costs, this is the way to do it.  However, about four days later the house backed up again.  When I opened the access point, the tank was at the proper level, and the filter was clean.  What the heck was up with that?

Seems when the tank was full, a clot of toilet paper formed on the inlet side and had turned to concrete.  See, what happens is that the 'sanitary tee' caught all the toilet paper and allowed a plug to form on the inlet.  When I lowered the level of the tank, the plug hardened and I had a new problem to deal with.  I spent most of the day with a water hose and jet nozzle breaking up the plug and restoring septic service to the house.  This needs some solution that doesn't require me to remember that the darn filter needs to be cleaned, and a way of clearing the pipes that doesn't entail a days work with a water hose.

So, I bought one of these:
This is a hose and special jet that you hook to your power washer and run through the sewer system to clear out clogs.  It won't work on tree roots or cave ins, but it will clear most clogs quite nicely.  Since I had never used one before, I was skeptical, but it did a great job.  It pulls itself along breaking up stuff and washing it down the sewer line.  If it stops at a bend or a clog, just pull it back a little bit and let it go; it will work its way through the clog and around the corner after a couple of tries.  Really nice tool.  Total time to clean out the pipes was around 30 minutes and most of that was figuring out how to hook the device up to the power washer.

But, to prevent the problem from sneaking up on me and flooding the bathroom was still a problem.  With a little searching I found out that there were floats that are specifically designed to tell you when the septic level rises.  I got one of these:
This is a normally closed float switch.  I chose normally closed so that I would know that the level was OK by a closure and it would open when the level got too high.  This way I knew the switch was OK and wouldn't have to wait for the sewer to back up to find out the switch was broken.

Total cost for both items: $150 including shipping.  I consider this a wise investment since now I can tell if the tank is rising and clean the filter long before it backs up into the house.  I also have a way of clearing the pipe easily each time I open up the tank to prevent the toilet-paper-turned-to-concrete-plug problem.  Sure, I could just clean the filter every six months or so, but who remembers that kind of thing?  Especially since this is probably the nastiest job one can take on around the house.  'Sanitary tee' ?  Who the heck thought of that name?

I haven't hooked the float into the house network yet, but that will come over the next month or so.  That's a problem that I already know how to deal with.  I plan on having a little light come on somewhere inside the house that I can't ignore; heck, I may have it send me email also.

I have the coolest septic tank in the area.


Friday, December 7, 2012

Alternatives to Cosm (Pachube), Part 2

(edited heavily on Dec 11, look below to see why)
Previously <link> I discussed the possible use of Sen.se as an alternative to Cosm.  This is becoming important to me because Cosm seems to be slowing down over time.  The users on their forum have brought this to the developers attention and there have been responses, but I'm having trouble loading a single day of data without a server error and failure to display the data.  So, I just tried out another offering emoncms.org.  It's pretty darn compelling.

The problem with most of the services that I've investigated though is there just isn't enough documentation on what it does, how it does it, where it stores the data, etc.  This is somewhat true of emoncms, but at least there's enough (including its forum) to actually use it.  It took me most of an afternoon to prowl through enough documentation and user comments to get it working.  The part that held me up the most was finding out how to get my data to the service.  It turns out that it's relatively easy to have an Arduino send the data to the service and then construct graphs and things using emoncms tools.

However, there are a number of odd problems relating to embedding their graphs into a blog page.  When I first put this page up I had a multigraph and a gauge that showed real time usage.  The problem was that using the scripts turned off the scroll bar for the page.  That's a bit unacceptable, so I edited the page to remove the visual display.  There are also a few display problems when using their dashboard, but it mostly works.  Here's the link to my dashboard with gauges and graphs that indicate real time data <link>.

Like I said, this is a very compelling site.  One problem may be that this site is open source and maintained by a community of interested users.  That means that it will grow quickly and capabilities will be added as they are thought of and users make the changes (unfortunately, it's the same for bugs).  That makes it somewhat unpredictable.

I can deal with that.


Like I said though, it's a bit tough to find out how to send data from an Arduino to the site.  I got it to work with minimal trouble after searching a lot on the site and its forum.  Here's a code snippet to illustrate how to do it:


The Arduino Sketch

void sendEmoncmsData(){
  char dataBuf[100];

  if(emoncms.connected()) // already trying to get data, just leave
    return;
  // construct the data buffer so we know how long it is
  strcpy_P(Dbuf2, PSTR("{RealPower:%d, PowerFactor:0.%d, PowerVoltage:%d.%02d, PowerFrequency:%d.%02d, InsideTemp:%d, OutsideTemp:%d}"));
  sprintf(dataBuf,Dbuf2,
    (int)round(realPower),
    (int)(powerFactor*100),
    (int)rmsVoltage,
    (int)(((rmsVoltage+0.005) - (int)rmsVoltage) * 100),
    (int)(frequency),
    (int)(((frequency+0.005) - (int)frequency) * 100),
    (ThermoData[0].currentTemp + ThermoData[1].currentTemp)/2,
    (int)round(outsideSensor.temp));
    Serial.println(dataBuf); // take this out when you've got it working
//    return;  // so you can see the buffer before you actually send it
  strcpy_P(Dbuf,PSTR("emoncms Connecting..."));
  Serial.print(Dbuf);
  if(emoncms.connect()){ // set a limit on how long the connect will wait
    strcpy_P(Dbuf,PSTR("OK..."));
    Serial.print(Dbuf);
    tNow = now();
    strcpy_P(Dbuf,PSTR("GET http://emoncms.org/input/post?apikey=secretnumbers &json="));
    emoncms.write(Dbuf);
    emoncms.write(dataBuf);
    emoncms.write("\n");
    emoncms.stop();
  }
  else {
    strcpy_P(Dbuf,PSTR("failed..."));
    Serial.print(Dbuf);
    emoncms.stop();
    while(emoncms.status() != 0){
      delay(5);
    }
  }
}

See, it's a simple json interaction that names the variable that you want to save data for.  emoncms will create the data store and name it for you.  All maintenance for the data can be done from their site.

This could well become my new cloud storage for data.

Friday, November 23, 2012

Battery Charging - Part 5 (Harbor Freight item 42292)

Yes, I finally assembled and tested the various ideas into a single box for my float charger for lead acid batteries.  This project has been going on for over a year now and may be getting close to having a nice working prototype.  I incorporated a voltage display and an XBee set up to transmit analog readings into the mix.  So, what happens is you plug the charger into the wall and the XBee comes on, samples the voltage before the output diode and sends it to whatever device you set it up to talk to.  This way I can monitor the battery state of charge remotely without even having to go into the garage.  Here's an interior view of the charger:


On the lower left is the charging circuit that I came up with based (roughly) on the Harbor Freight 42292; at the top, stuck to the side is a series 2 XBee plugged into a breakout board; and on the right is the voltmeter display.  This is all enclosed in a plastic rectangular enclosure.  When assembled it looks like this:


Of course, since the XBee is a 3.3V device, I had to add a power supply for it.  I took the power directly from the float voltage and used an AP1117T33 regulator.  When I first started testing the combination, it got pretty hot pretty quickly, even when it wasn't hooked to a battery.  A little checking (I unplugged the XBee) told me that the XBee and its two LEDs were sucking enough power to heat it up, so I enabled sleep on the XBee.  This way, it would be off most of the time and only turn on to take a couple of measurements and transmit them.  This totally solved the problem.Here's the schematic I eventually settled on.  

If you're following this, you'll see that it's a simple variable supply that I set to 13.4V with resistor R2 which feeds a 3.3V supply to power the XBee.  The voltage divider R4, R5 sets the level that is in the 1.2V analog input range of the XBee.  Since these regulators sometimes tend to oscillate, I added capacitors C1 and C2 just to make sure I didn't drive the XBee nuts.  That's also why I added the resistor R6, to keep it away from reset.

To set it up, I put a 1K resistor across the output and set the voltage using R2 to 13.4 volts.  Then I centered the pot R5 and checked what was being transmitted.  By adjusting the pot, I was able to get a nice reading at the receiving end which I translated back into voltage and can display with an XBee connected Arduino.

There's a little jitter in the XBee readings caused by transients.  I can solve that two ways, add a capacitor on pin 20 of the XBee or do a rolling average on the receiving device.  I haven't decided which to do yet. I'm leaning toward a rolling average, but experience will tell me if it even needs to be fixed.  Here's a short sample of the Arduino output I set up.  Obviously, this isn't what I'll eventually use, but it's nice to be able to see the charger out in the garage:

A fun item I noticed is that the circuitry for monitoring the battery and transmitting the value can be separated from the charger.  That way I could hook a device to the battery and it would transmit the voltage to something that could alert me to go attend to the darn thing.  I may pursue that for something in the future.

No, I'm still not done.  This thing was a real pain to build.  It came up from several prototypes and kept getting more complex and looks like a mess because of this.  I think I may journey into getting a custom PC board made to put the thing together with since I want at least five of them.  Also, since I now have a box that will hold it, I'm going to mount the components on the lid with a wire to the display on the box part.  That way I can actually screw stuff down so it doesn't bounce around over time.

Monday, November 19, 2012

Apple Device: "Charging is not supported with this accessory"

I don't have a single Apple device in my house, no iPad, iPhone, iPod, iAnything.  I don't even have any apples.  However, the little wall warts I bought <link> have a bad reputation because they don't work on some iDevices.  While it's true that they don't, it really isn't their fault, it's Apple's.  This is the message:
Notice that it doesn't say that the device is the wrong voltage, wrong polarity, or wrong anything else?  That's because the device just doesn't meet the Apple standards of being made by Apple specifically for a particular Apple device.  They really, really want to lock you into buying your stuff from them and them alone.

My little chargers are fine and will work with Apple stuff with a simple modification that I won't do since I don't need to charge Apple devices.  What Apple did was use the D- and D+ (the two middle pins on a standard type A usb plug) to supply specific voltages that Apple could look at to tell if the charger was one of theirs.

Well, this little trick didn't last long before the engineers that make battery extenders and chargers figured it out.  Obviously, they grabbed a real apple charger and ripped it open to see what kind of shenanigans Apple was up to.  One manufacturer Lady Ada wrote up a nice description of what was happening and how she worked around it for one of her products, the MintyBoost.  She has a nice description of how she overcame the problem and made her stuff work <link>.

This also explains over 90% of the complaints on the web about various iDevices not working with a charger.  Basically, these two voltages (D1 and D2) are tiny and can vary a lot based on contact resistance, length of cable, net draw of the device, etc.  Basically any darn thing at all.  For example some of the solutions are to turn off the iPhone, plug the cable and charger into the phone, plug the charger into the wall, turn on the phone, repeat a number of times to allow the gremlins to align correctly.  And, this occasionally works.  Another solution is to lower the screen intensity, put the phone in airplane mode, then hook up the charger. There's always someone that says you need a new cable, better charger, or hold your mouth differently.  In the case of the iPhone, there was an OS update that caused a significant number people to have charging problems.  The fix for many of these non-technical folk was to go to the Apple store and get a new device or have a new part installed that will work.  Of course there are the Apple cultist that insist that only a new Apple charger will solve the problem.

But people, electrons are electrons and it isn't you or your device when a problem like this turns up, it's Apple exercising their control over their cult.  Annoying.

Don't despair yet.  There are ways to get around this problem that actually make sense.  No, you don't need to wet a Qtip with perfume and clean the contacts, letting it air dry for an hour(this is a real suggestion), there are much more mundane solutions.  For example, this site <link> talks about a little connector that has Apple plugs on both ends and works around the problem.  However, the darn thing is too expensive (I'm not a fan of this solution, but some of you might be).  There are several other similar devices out there that solve the problem.  You can also solve the problem by building something yourself (gasp !); I know this goes against life philosophy of the myriad teenagers that talked their parents into getting this cool new gadget, but life isn't fair.

Just cut a USB charging cable that mates with the device and add a little voltage divider.  The schematic of the changes is:
If this picture doesn't look familiar, take another look at Lady Ada's description, it was taken directly from there.  See, Apple uses the voltage divider to set specific voltages on D+ and D- to identify their devices.  Other manufacturers don't do this kind of thing unless they're trying to meet the USB charging standards, and for a low price device it isn't worth the effort or cost. Just another effort of Apple to wrangle you into their pen.

So, you ask, "What do you care, you don't own an Apple device?"  I don't, but my less fortunate friends, neighbors, and relatives do.  They get really annoyed when their devices won't work on one of my chargers when they come to visit, and they hate it when a charger stops working and gives them this silly, non descriptive message.  Also, I found zero, nada, explanations of what was going on to help people with this problem.  That annoyed me more than anything else, so I decided to post it here and a couple of other places, hoping that poor souls that are eating up Google cpu cycles could, at least, understand the problem better.

Soak a Qtip in perfume and clean the contacts?  Really?

Sunday, November 18, 2012

Tiny Power Supplies for Micro Controller Projects

When you build micro controller projects, eventually you want to do something real that will have to work long term.  For this you need a power supply that is small, maybe small enough to put in a light switch, ceiling fan, or dryer control panel.  These things are hard to find.  I've spent hours on Google trying to find really small 5V supplies with some success, but never fitting my needs.  Nice little supplies that you have to buy in 100+ quantities, nice little supplies that cost US $50, etc are out there, but who wants to invest that kind of money in a technology that changes almost daily?

In a few project postings I describe how I cut the guts out of a wall wart like this:
These little devices work great as microcontroller power supplies.  The one above will put out up to 2A and doesn't seem to get hot doing it.  I've had several in service, out in the weather for two years.  At a cost less than US $5 each (usually with free shipping) they are a fine solution.  I've taken the supply out of the plastic case and installed it into devices like this <link>:
The little board in the upper left is the guts of the wall wart.  I've even used the entire wall wart as a mounting platform for another device:
This device <link> has an XBee mounted on the side of the wall wart transmitting temperature every minute or so.  All-in-all, a pretty useful device repurposed from the iPad craze.  However, technology moves on and I want to try a couple of ideas that would work better if I had an even smaller power supply.  I asked on a couple of forums and was pointed to one of these:
I already had two of them charging mobile devices in the house so I decided to gut one of them and see what was inside:
This little supply is TINY. Yes, I had to cut the case off with a Dremel to get to the guts; the top was seriously glued to the bottom and refused to come off. The two board with connecting cable configuration could create a problem mounting, but nothing I can't overcome, and the wires to the AC pins might give me a problem, but it couldn't be too hard to solve; I like this.  So, looking around the web to see what kind of deal I could get on them I found them for US $1 on Amazon.  Yes, you read that right, a single dollar, with free shipping.  So:
Here's my pile of stock devices.  

Since supply and demand act on everything, the price at Amazon has gone up to US $1.45 as of this writing and could go either up or down based on activity, but they are still a bargain.  

Even with this solution available, I'm still searching for possibilities.  The rough requirements for the supply are: minuscule size, 5V at a least an amp (relays, you know), easy to mount, things like that.  

To you suppliers out there, there's a market here that you aren't exploiting.  SparkFun, Lady Ada, Itead, etc. are you listening?  You folks in China, what are you waiting for?

Saturday, November 10, 2012

Using the XBee Library Part 2

Previously, I talked about using Andrew Rapp's XBee library on a project and posted an example.  This is the second example I've been working on.  The objective is to understand the library well enough to re-implement some of my devices using the library because I'm getting tired of doing my own parsing of the basic packet.  Yes, I have finer control, but I've found I don't really need finer control.  So, here is an example of using the code on an Arduino 2560 with the XBee connected to Serial3.  This leaves me two unused serial ports to play with since I'm using the main serial port as my debugging and status port.

The Arduino Sketch
/*
XBee RX test for a Arduino Mega2560 using Serial3 as the XBee serial
input for a Series 2 XBee.  I took Andrew Rapp's receive example and modified
it heavily.

I wanted to experiment with and better understand how to use his XBee
library for an actual project.  With the inclusion of support for SoftwareSerial
so that the XBee can be put on digital pins leaving the Arduino serial port
available for debugging and status, the library's usefullness shot way up.  These
changes also allow for the use of the additional serial ports on a Mega2560

This is a HEAVILY commented example of how to grab a receive packet off the
air and do something with it using series 2 XBees.  This example also supports
a remote XBee end device sending analog data.  Series 1 XBees are left as an
exercise for the student.
*/

#include <XBee.h>

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle
ZBRxResponse rx = ZBRxResponse();
ZBRxIoSampleResponse ioSample = ZBRxIoSampleResponse();

void setup() {
  // start serial
  Serial.begin(9600);
  // and the third serial port
  Serial3.begin(9600);
  // now that they are started, hook the XBee into
  // the third serial port
  xbee.setSerial(Serial3);
  // I think this is the only line actually left over
  // from Andrew's original example
  Serial.println("starting up yo!");
}

void loop() {
    // doing the read without a timer makes it non-blocking, so
    // you can do other stuff in loop() as well.
    xbee.readPacket();
    // so the read above will set the available up to
    // work when you check it.
    if (xbee.getResponse().isAvailable()) {
      // got something
      // I commented out the printing of the entire frame, but
      // left the code in place in case you want to see it for
      // debugging or something.  The actual code is down below.
      //showFrameData();
      Serial.print("Frame Type is ");
      // Andrew calls the frame type ApiId, it's the first byte
      // of the frame specific data in the packet.
      Serial.println(xbee.getResponse().getApiId(), HEX);
   
      if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
        // got a zb rx packet, the kind this code is looking for
     
        // now that you know it's a receive packet
        // fill in the values
        xbee.getResponse().getZBRxResponse(rx);
     
        // this is how you get the 64 bit address out of
        // the incoming packet so you know which device
        // it came from
        Serial.print("Got an rx packet from: ");
        XBeeAddress64 senderLongAddress = rx.getRemoteAddress64();
        print32Bits(senderLongAddress.getMsb());
        Serial.print(" ");
        print32Bits(senderLongAddress.getLsb());
     
        // this is how to get the sender's
        // 16 bit address and show it
        uint16_t senderShortAddress = rx.getRemoteAddress16();
        Serial.print(" (");
        print16Bits(senderShortAddress);
        Serial.println(")");
     
        // The option byte is a bit field
        if (rx.getOption() & ZB_PACKET_ACKNOWLEDGED)
            // the sender got an ACK
          Serial.println("packet acknowledged");
        if (rx.getOption() & ZB_BROADCAST_PACKET)
          // This was a broadcast packet
          Serial.println("broadcast Packet");
       
        Serial.print("checksum is ");
        Serial.println(rx.getChecksum(), HEX);
     
        // this is the packet length
        Serial.print("packet length is ");
        Serial.print(rx.getPacketLength(), DEC);
     
        // this is the payload length, probably
        // what you actually want to use
        Serial.print(", data payload length is ");
        Serial.println(rx.getDataLength(),DEC);
     
        // this is the actual data you sent
        Serial.println("Received Data: ");
        for (int i = 0; i < rx.getDataLength(); i++) {
          print8Bits(rx.getData()[i]);
          Serial.print(' ');
        }
     
        // and an ascii representation for those of us
        // that send text through the XBee
        Serial.println();
        for (int i= 0; i < rx.getDataLength(); i++){
          Serial.write(' ');
          if (iscntrl(rx.getData()[i]))
            Serial.write(' ');
          else
            Serial.write(rx.getData()[i]);
          Serial.write(' ');
        }
        Serial.println();
        // So, for example, you could do something like this:
        handleXbeeRxMessage(rx.getData(), rx.getDataLength());
        Serial.println();
      }
      else if (xbee.getResponse().getApiId() == ZB_IO_SAMPLE_RESPONSE) {
        xbee.getResponse().getZBRxIoSampleResponse(ioSample);
        Serial.print("Received I/O Sample from: ");
        // this is how you get the 64 bit address out of
        // the incoming packet so you know which device
        // it came from
        XBeeAddress64 senderLongAddress = ioSample.getRemoteAddress64();
        print32Bits(senderLongAddress.getMsb());
        Serial.print(" ");
        print32Bits(senderLongAddress.getLsb());
     
        // this is how to get the sender's
        // 16 bit address and show it
        // However, end devices that have sleep enabled
        // will change this value each time they wake up.
        uint16_t senderShortAddress = ioSample.getRemoteAddress16();
        Serial.print(" (");
        print16Bits(senderShortAddress);
        Serial.println(")");
        // Now, we have to deal with the data pins on the
        // remote XBee
        if (ioSample.containsAnalog()) {
          Serial.println("Sample contains analog data");
          // the bitmask shows which XBee pins are returning
          // analog data (see XBee documentation for description)
            uint8_t bitmask = ioSample.getAnalogMask();
            for (uint8_t x = 0; x < 8; x++){
            if ((bitmask & (1 << x)) != 0){
              Serial.print("position ");
              Serial.print(x, DEC);
              Serial.print(" value: ");
              Serial.print(ioSample.getAnalog(x));
              Serial.println();
            }
          }
        }
        // Now, we'll deal with the digital pins
        if (ioSample.containsDigital()) {
          Serial.println("Sample contains digtal data");
          // this bitmask is longer (16 bits) and you have to
          // retrieve it as Msb, Lsb and assemble it to get the
          // relevant pins.
          uint16_t bitmask = ioSample.getDigitalMaskMsb();
          bitmask <<= 8;  //shift the Msb into the proper position
          // and in the Lsb to give a 16 bit mask of pins
          // (once again see the Digi documentation for definition
          bitmask |= ioSample.getDigitalMaskLsb();
          // this loop is just like the one above, but covers all
          // 16 bits of the digital mask word.  Remember though,
          // not all the positions correspond to a pin on the XBee
          for (uint8_t x = 0; x < 16; x++){
            if ((bitmask & (1 << x)) != 0){
              Serial.print("position ");
              Serial.print(x, DEC);
              Serial.print(" value: ");
              // isDigitalOn takes values from 0-15
              // and returns an On-Off (high-low).
              Serial.print(ioSample.isDigitalOn(x), DEC);
              Serial.println();
            }
          }
        }
        Serial.println();
      }

      else {
        Serial.print("Got frame id: ");
        Serial.println(xbee.getResponse().getApiId(), HEX);
      }
    }
    else if (xbee.getResponse().isError()) {
      // some kind of error happened, I put the stars in so
      // it could easily be found
      Serial.print("************************************* error code:");
      Serial.println(xbee.getResponse().getErrorCode(),DEC);
    }
    else {
      // I hate else statements that don't have some kind
      // ending.  This is where you handle other things
    }
}

void handleXbeeRxMessage(uint8_t *data, uint8_t length){
  // this is just a stub to show how to get the data,
  // and is where you put your code to do something with
  // it.
  for (int i = 0; i < length; i++){
//    Serial.print(data[i]);
  }
//  Serial.println();
}

void showFrameData(){
  Serial.println("Incoming frame data:");
  for (int i = 0; i < xbee.getResponse().getFrameDataLength(); i++) {
    print8Bits(xbee.getResponse().getFrameData()[i]);
    Serial.print(' ');
  }
  Serial.println();
  for (int i= 0; i < xbee.getResponse().getFrameDataLength(); i++){
    Serial.write(' ');
    if (iscntrl(xbee.getResponse().getFrameData()[i]))
      Serial.write(' ');
    else
      Serial.write(xbee.getResponse().getFrameData()[i]);
    Serial.write(' ');
  }
  Serial.println();
}

// these routines are just to print the data with
// leading zeros and allow formatting such that it
// will be easy to read.
void print32Bits(uint32_t dw){
  print16Bits(dw >> 16);
  print16Bits(dw & 0xFFFF);
}

void print16Bits(uint16_t w){
  print8Bits(w >> 8);
  print8Bits(w & 0x00FF);
}

void print8Bits(byte c){
  uint8_t nibble = (c >> 4);
  if (nibble <= 9)
    Serial.write(nibble + 0x30);
  else
    Serial.write(nibble + 0x37);
     
  nibble = (uint8_t) (c & 0x0F);
  if (nibble <= 9)
    Serial.write(nibble + 0x30);
  else
    Serial.write(nibble + 0x37);
}

It was actually pretty easy to convert my previous example to the 2560; I just changed the port in setSerial() to Serial3 instead of newsoftserial and it worked.  This left me a little time to play with capturing an I/O packet and taking it apart.  The code to handle an I/O packet is in this example.

I wanted the I/O packet because I have an XBee outside on a pole measuring the temperature that sends I/O packets periodically and I want to set up a battery monitor for my lead acid batteries to keep track of their state of charge.  You don't need an Arduino hooked to an XBee for these purposes, but you do need to be able to receive and decode the packets.

Once again, feel free to grab the code and modify it for your purposes.

Tuesday, October 30, 2012

Using the XBee library

Recently Paul Stoffregen created a new software serial library for the Arduino, then he modified Andrew Rapp's XBee library to use it (as well as the older, but really great, SoftwareSerial libray).  Suddenly, the XBee library is something that could be really useful.

See, the XBee library has traditionally been hooked into the hardware serial lines on Arduino Pins 0 and 1.  That means getting debugging information out of the device combination of an Arduino and an XBee is an exercise in frustration and annoyance.  Sure, you can use blinking lights to tell you what is going on, but this is the 21st century.  I have always written my own code to handle the XBee interaction because I wanted the serial port to provide status and control when I was working on a project.  Additionally, Andrew's library is heavily c++ and all the classes, inheritance, and instances confused the heck out of me.

However, maybe with the inclusion of a modified software serial port, and the capability to use the additional ports on an Arduino Mega, now is the time to take a serious look at using it.  I mean, if you have a mega, you can now put the XBee on Serial1 and keep Serial and Serial 2 for other things; this is just the ticket for converting RS485 into XBee packets to send over the air where you don't have wires.  Heck, I can think of dozens of things.

So, here is my first voyage into the use of the library.  I haven't linked in Paul's new serial library yet, I will on a future example, but I just wanted to understand what was going on and how to, at least, receive a packet and do something with it.  I took one of Andrew's library examples and modified it substantially to include many of the things I need in using an XBee and commented the heck out of it so others stood a chance of understanding what was going on.  It's amazing how few examples are out there that actually show what you need to do to do something along these lines.


The Arduino Sketch

/**
I took Andrew Rapp's receive example and modified it to be completely
unrecognizable.

I wanted to experiment with and better understand how to use his XBee
library for an actual project.  With the inclusion of support for SoftwareSerial
so that the XBee can be put on digital pins leaving the Arduino serial port
available for debugging and status, the library's usefullness shot way up.

This is a HEAVILY commented example of how to grab a receive packet off the
air and do something with it using series 2 XBees.  Series 1 XBees are left as
and exercise for the student.
*/

#include <XBee.h>
#include <SoftwareSerial.h>

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle
ZBRxResponse rx = ZBRxResponse();

// Define NewSoftSerial TX/RX pins
// Connect Arduino pin 2 to Tx and 3 to Rx of the XBee
// I know this sounds backwards, but remember that output
// from the Arduino is input to the Xbee
#define ssRX 2
#define ssTX 3
SoftwareSerial nss(ssRX, ssTX);


void setup() {
  // start serial
  Serial.begin(9600);
  // and the software serial port
  nss.begin(9600);
  // now that they are started, hook the XBee into
  // Software Serial
  xbee.setSerial(nss);
  // I think this is the only line actually left over
  // from Andrew's original example
  Serial.println("starting up yo!");
}

void loop() {
    // doing the read without a timer makes it non-blocking, so
    // you can do other stuff in loop() as well.
    xbee.readPacket();
    // so the read above will set the available up to
    // work when you check it.
    if (xbee.getResponse().isAvailable()) {
      // got something
      Serial.println();
      Serial.print("Frame Type is ");
      // Andrew call the frame type ApiId, it's the first byte
      // of the frame specific data in the packet.
      Serial.println(xbee.getResponse().getApiId(), HEX);
   
      if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
        // got a zb rx packet, the kind this code is looking for
     
        // now that you know it's a receive packet
        // fill in the values
        xbee.getResponse().getZBRxResponse(rx);
     
        // this is how you get the 64 bit address out of
        // the incoming packet so you know which device
        // it came from
        Serial.print("Got an rx packet from: ");
        XBeeAddress64 senderLongAddress = rx.getRemoteAddress64();
        print32Bits(senderLongAddress.getMsb());
        Serial.print(" ");
        print32Bits(senderLongAddress.getLsb());
     
        // this is how to get the sender's
        // 16 bit address and show it
        uint16_t senderShortAddress = rx.getRemoteAddress16();
        Serial.print(" (");
        print16Bits(senderShortAddress);
        Serial.println(")");
     
        // The option byte is a bit field
        if (rx.getOption() & ZB_PACKET_ACKNOWLEDGED)
            // the sender got an ACK
          Serial.println("packet acknowledged");
        if (rx.getOption() & ZB_BROADCAST_PACKET)
          // This was a broadcast packet
          Serial.println("broadcast Packet");
       
        Serial.print("checksum is ");
        Serial.println(rx.getChecksum(), HEX);
     
        // this is the packet length
        Serial.print("packet length is ");
        Serial.print(rx.getPacketLength(), DEC);
     
        // this is the payload length, probably
        // what you actually want to use
        Serial.print(", data payload length is ");
        Serial.println(rx.getDataLength(),DEC);
     
        // this is the actual data you sent
        Serial.println("Received Data: ");
        for (int i = 0; i < rx.getDataLength(); i++) {
          print8Bits(rx.getData()[i]);
          Serial.print(' ');
        }
     
        // and an ascii representation for those of us
        // that send text through the XBee
        Serial.println();
        for (int i= 0; i < rx.getDataLength(); i++){
          Serial.write(' ');
          if (iscntrl(rx.getData()[i]))
            Serial.write(' ');
          else
            Serial.write(rx.getData()[i]);
          Serial.write(' ');
        }
        Serial.println();
     
        // So, for example, you could do something like this:
        handleXbeeRxMessage(rx.getData(), rx.getDataLength());
/*
        // I commented out the printing of the entire frame, but
        // left the code in place in case you want to see it for
        // debugging or something
        Serial.println("frame data:");
        for (int i = 0; i < xbee.getResponse().getFrameDataLength(); i++) {
          print8Bits(xbee.getResponse().getFrameData()[i]);
          Serial.print(' ');
        }
        Serial.println();
        for (int i= 0; i < xbee.getResponse().getFrameDataLength(); i++){
          Serial.write(' ');
          if (iscntrl(xbee.getResponse().getFrameData()[i]))
            Serial.write(' ');
          else
            Serial.write(xbee.getResponse().getFrameData()[i]);
          Serial.write(' ');
        }
        Serial.println();
*/
      }
    }
    else if (xbee.getResponse().isError()) {
      // some kind of error happened, I put the stars in so
      // it could easily be found
      Serial.print("************************************* error code:");
      Serial.println(xbee.getResponse().getErrorCode(),DEC);
    }
    else {
      // I hate else statements that don't have some kind
      // ending.  This is where you handle other things
    }
}

void handleXbeeRxMessage(uint8_t *data, uint8_t length){
  // this is just a stub to show how to get the data,
  // and is where you put your code to do something with
  // it.
  for (int i = 0; i < length; i++){
//    Serial.print(data[i]);
  }
//  Serial.println();
}

// these routines are just to print the data with
// leading zeros and allow formatting such that it
// will be easy to read.
void print32Bits(uint32_t dw){
  print16Bits(dw >> 16);
  print16Bits(dw & 0xFFFF);
}

void print16Bits(uint16_t w){
  print8Bits(w >> 8);
  print8Bits(w & 0x00FF);
}

void print8Bits(byte c){
  uint8_t nibble = (c >> 4);
  if (nibble <= 9)
    Serial.write(nibble + 0x30);
  else
    Serial.write(nibble + 0x37);
     
  nibble = (uint8_t) (c & 0x0F);
  if (nibble <= 9)
    Serial.write(nibble + 0x30);
  else
    Serial.write(nibble + 0x37);
}

I tried to get all the major items out of the packet so they could be displayed and even included a tiny routine to illustrate using the received data.  This is what it looks like running:


You have to use the scrollbar at the bottom to see all of the message, but I wanted it that way instead of worrying about wrapping around.  I also put in print routines for the hex data; I love being able to see it in both hex and ascii.

Grab it, modify it to your purpose, and have fun.

Monday, October 22, 2012

Monitoring My XBee Network

In the previous post <link> I wrote about how I discovered broadcast mode can cause problems as you increase the number of nodes.  That led to a method of monitoring each node to see what it was actually doing, and by watching each of them in turn, seeing how the traffic patterns work out.

Well, I left it kind of up-in-the-air on exactly how I did it.  Basically, I used the examples that Akiba of Freaklabs released for various functions and created a sniffer of sorts.  This is necessary because the XBee only sends out the serial port data intended for the particular radio module you're plugged into.  That's what makes broadcast mode so useful, you can see all the traffic and chase problems.  With a Freakduino Chibi board, you can monitor all the devices on your network at once, but that is way too much information to try to wade through.  By setting the Chibi board to promiscuous mode and then writing code to filter by address, you can watch any node in the network to see what is going on with that particular device.  This makes it possible to see its traffic even though you aren't using an XBee.

Here's the code I came up with:

The Arduino Sketch
/*
This sketch enables promiscuous mode on the Freakduino boards and then
filters by device address to watch a particular node.

I had to change the buffer size in the chibi library for promiscuous mode
because, being set to 1024 with another buffer for the packet to be manipulated
caused the board to run out of RAM.  Just go into the chibi library and
find the receive buffer in chb_buf.h and set it to what you want.  I used the
value 500, and it seems to work fine

Before using this sketch, also go into the chibiUsrCfg.h file and
enable promiscuous mode. To do this, change the definition:

#define CHIBI_PROMISCUOUS 0
to
#define CHIBI_PROMISCUOUS 1

When not using promiscuous mode, disable this setting by changing
it back to 0.
*/

#include <chibi.h>
#include <avr/pgmspace.h>
#include <MemoryFree.h>

/*
Addresses of devices in my network
                    Long     Short
Garage Controller 407A 38AF  A019
Power Monitor     4031 566B  CD6B
Controller        4055 B0A6  97FA
Status Display    406F B6B5  9BE8
Pool Controller   4079 B2BD  9370
Temp1             406F 7FAC  1B1E
House Clock       4055 B094  0
Acid Pump         406F B7AF  7D58
*/
char *deviceName[] = {"Garage Controller",
                       "Power Monitor",
                       "Controller",
                       "Status Display",
                       "Pool Controller",
                       "Temp1",
                       "House Clock",
                       "Acid Pump"};
uint16_t deviceAddress[] = {0xA019,
                         0xCD6B,
                         0x97FA,
                         0x9BE8,
                         0x9370,
                         0x1B1E,
                         0x0,
                         0x7D58};
uint16_t listenTo;
byte Pbuf[500];
char Dbuf[50];
int longest = 0;

void showMem(){
  strcpy_P(Dbuf,PSTR("Mem = "));
  Serial.print(Dbuf);
  Serial.println(freeMemory());
}

/**************************************************************************/
// Initialize
/**************************************************************************/
void setup()
{
  // Init the chibi stack
  Serial.begin(115200);
  chibiInit();
  strcpy_P(Dbuf,PSTR("\n\r***************I'm alive**************"));
  Serial.println(Dbuf);
  unsigned int choice = 0;
  Serial.println("Pick a device to listen to");
  for(int i = 0; i < sizeof(deviceName)/sizeof(deviceName[0]); i++){
    Serial.print((char)(i + 'A'));
    Serial.print(" - ");
    Serial.println(deviceName[i]);
  }
  Serial.print("> ");
  // this only accepts a single character for the device choice.
  // that's because the chibi board runs at 8MHz on the internal clock and
  // internal clocks aren't accurate.  This means the higher baud rates sometimes
  // have problems.  When I worked on this I couldn't get the board to accept more
  // than one character correctly at baud rates over 57K.  Works fine at 9600,
  // but I want to output the data far faster than that.
  while(1){
    if(Serial.available() != 0){
      char c = Serial.read();
      Serial.write(c);
      Serial.println();
      choice = toupper(c) - 'A';
      if (choice < sizeof(deviceName)/sizeof(deviceName[0]))
        break;
      else {
        Serial.println(" oops, try again");
        Serial.print("> ");
      }
    }
  }
  listenTo = deviceAddress[choice];
  strcpy_P(Dbuf,PSTR("Starting Radio, Result = "));
  Serial.print(Dbuf);
  Serial.println(chibiSetChannel(12),DEC);
  strcpy_P(Dbuf,PSTR("Listening to "));
  Serial.print(Dbuf);
  Serial.print(deviceName[choice]);
  strcpy_P(Dbuf,PSTR(" at address "));
  Serial.print(Dbuf);
  Serial.println(listenTo, HEX);
  showMem();
}

/**************************************************************************/
// Loop
/**************************************************************************/
void loop()
{
  // Check if any data was received from the radio. If so, then handle it.
  if (chibiDataRcvd() == true)
  {
    int len;
    uint16_t senderAddress;
 
    // send the raw data out the serial port in binary format
    len = chibiGetData(Pbuf);
    if (len > longest)
      longest = len;
    senderAddress = chibiGetSrcAddr();
    if (senderAddress == listenTo && len > 0){
      strcpy_P(Dbuf,PSTR("From: "));
      Serial.print(Dbuf);
      Serial.print(senderAddress,HEX);
      strcpy_P(Dbuf,PSTR(" Len: "));
      Serial.print(Dbuf);
      Serial.print(len);
      strcpy_P(Dbuf,PSTR(" Longest: "));
      Serial.print(Dbuf);
      Serial.println(longest);
      for (int i= 0; i < len; i++){
        uint8_t nibble = (uint8_t) (Pbuf[i] >> 4);
        if (nibble <= 9)
          Serial.write(nibble + 0x30);
        else
          Serial.write(nibble + 0x37);
     
        nibble = (uint8_t) (Pbuf[i] & 0x0F);
        if (nibble <= 9)
          Serial.write(nibble + 0x30);
        else
          Serial.write(nibble + 0x37);
        Serial.print(' ');
      }
      Serial.println();
      for (int i= 0; i < len; i++){
        uint8_t nibble = (uint8_t) (Pbuf[i] >> 4);
        Serial.write(' ');
        if (iscntrl(Pbuf[i]))
          Serial.write(' ');
        else
          Serial.write(Pbuf[i]);
        Serial.write(' ');
      }
      Serial.println();
    }
  }
}


A couple of things to keep in mind.  The Chibi board is only running at 8 Mhz, so it can't keep up with unlimited traffic flying through the air at 250Kb forever.  If you spend too much time in the code checking and decoding, you'll miss packets.  The Chibi library sets a buffer size of 1024 to handle packets being received to help with this, but you'll have to reduce this size because the MCU only has 2K of ram to begin with.  I point this out in the code.  The maximum size of a packet is 127 bytes, so make your parsing buffer longer than that.  I print the maximum packet length in the code above, and have never seen a packet larger, so it appears the library is working fine for separating the packets.  I also put a routine in the code to monitor  memory usage.  Use this to keep track so you don't run out with the various buffers and such.

Here's a sample of the output using the serial monitor from the Arduino IDE:


It doesn't wrap around, but that could be easily added.  I just use the scroll bar on the bottom to move around.  I output the hex values as well as the ascii so I can recognize the various packets as well as decode the binary portions of the data.

So, as your network grows, or you have problems right off the bat, consider this combination of things as a possible tool to help you get past it.  Of course, you're welcome to grab the code and modify it to your particular network and need for monitoring.

Saturday, October 20, 2012

More About XBee Broadcast

I discuss the usefulness of XBee broadcast here <link>, but there is a problem with this I didn't foresee.  It seems that, if you get enough devices, the network gets flooded and becomes unreliable.  You see, the beauty of XBees is that they implement mesh protocol such that you can have a message forwarded from XBee to XBee until it reaches its destination many hops away.  This is a really good thing because an XBee at the far end of the house can communicate with another one at the opposite end.

I tested this several times by separating a couple of XBees to where they couldn't communicate, then completed the circuit by simply placing one in the middle to forward the data.  This means I can go from my barn to my controller with a message without worrying about how far it is, or getting a high power version of the XBee.

The problem comes when a broadcast is transmitted by a device far away and is echoed by several of them to assure it gets to its destination.  The Zigbee packet gets a little larger with each hop since it carries the routing information along with it and eventually, the channel is flooded with messages bouncing around.

Introducing the Freakduino Chibi.

I found this when I bought a new device to take a look at the network.  This little device <link>  is an IEEE 802.15.4 radio mounted with an Arduino compatible MCU.   The little device can be programmed to listen in promiscuous mode such that it hears all the packets in range, and at my house this means almost all the devices can be monitored.  There's also the possibility of hooking this into WireShark, but I couldn't get that to work reliably.  What I did was simply set up a small program that will listen to any of my devices individually to see what traffic is passing through it and just sat back and observed what was going on one device at a time.

The Acid Pump would send a broadcast that was echoed by several devices trying to forward the message to some other device effectively more than doubling the traffic for each device.  When they were all doing things, the channel was flooded with superfluous repeated messages such that collisions were constantly happening.  There just wasn't enough dead air time for any of them to transmit.  I lost messages because they overlapped each other and checksums were bad because the devices overlapped at times.

I'm still a big fan of broadcast, it definitely has its place.  For example, a new device that you want to carefully monitor for a few days to be sure you got the set up correct, or a device that is having some problems and needs to be monitored.  However, don't go nuts with it like I did. So, what you can do is set your code up to transmit in broadcast initially to get the bugs out then change it to a specific address when you're comfortable that it is working correctly.  Then get a Freakduino Chibi to check it from time to time or when you suspect something might be wrong with it

As you can see, it is a little bigger than an Arduino, but that's OK since it has an optional enclosure that houses it nicely:
This is the combination I bought.  Then, I took his example code, modified the heck out of it such that it could watch a particular device (even if the device was transmitting to a specific address) and was able to troubleshoot my network.  

Of course it isn't perfect.  The Freakduino only runs at 8MHz, so it's entirely possible for it to be unable to keep up with the traffic on a heavily loaded network like mine used to be, and there are probably a couple of problems with the library he provides to get you going, but that's the kind of thing we're best at.

So, I was able to cut the traffic down on my network by a huge amount, and I can monitor any device to see what is actually happening.  Now, I have bandwidth to add even more devices.

Thursday, October 18, 2012

Alternatives to Cosm (Pachube)

There are a few alternatives to Cosm for handling devices that report over the web. I'm currently playing with Sen.se (open.sen.se) and it has some really cool features that I haven't seen before. See, I'm very interested in monitoring and controlling my house. I want to be able to tell if it's too hot, what the appliances are doing, is the darn garage door open, that kind of thing. I don't want to spend months learning how to create charts, pretty switches, or automatic backups for data stores. That's why services that connect devices on the web will someday be important. Someday, services like Sen.se and Cosm will be very important to the operation of devices. Anyway, Sen.se has a method of connecting to the data I'm already sending to Cosm. By adding a feed to my Cosm account I can use the Sen.se controls and displays to monitor my house. Cool, really cool. For example, here is a graph I put together in a few minutes using their tools (scroll down past it for more):


The chart will change based on the items I'm charting so you can see the latest data a minute or so after it gets posted on the Cosm site.  Additionally, it's interactive.  You can put your pointer over the control and see individual values and turn off parts of the chart.  There's also a problem putting more than one control on a blog page. They seem to interact with blogger and each other such that you can't get them to work together.  At least not yet (Sen.se is a beta site).

But isn't the chart cool?

Monday, October 15, 2012

Dogs and Rattlesnakes

After dealing with the second dog I've had bitten by a rattlesnake <link>, I decided people needed more information about snake avoidance.  There are a ton of sites out there that all espouse, what they say, is the right way to train a dog to avoid snakes.  There is a ton of misinformation and I just want to clear it up for people so they don't have the same problems I did.  There are a number of wrong things to do and a few right ones and I believe I have the experience now to tell the right from the wrong.  I've interviewed around twenty people who have used various trainers with varying results, and although they didn't realize they were being interviewed, they pointed out the various shortcomings.  Frankly, it's best to get the assistance of a professional snake trainer.  Very few people keep poisonous snakes around the house to be used for training dogs.  I'll start off with a few items that are very important.

When you arrive at the trainer, the cages for the snakes should already be set up.  The trainer should have done this before you got there; if they are not set up, leave and come back after they are.  The reason for this is the dog will see the cages being set up and associate any training to the cage, not the snakes inside.

The snakes MUST be alive and active.  A dead snake smells wrong and doesn't move around.  There's no point at all teaching your dog to avoid a dead snake. You want the dog to see the snake moving, hear its rattle, and realize this is another animal.

The trainer should have an empty cage for the dog to inspect.  This assures the dog that the cages are harmless.

The dog owner should be the one to walk the dog and participate in the training.  There are a couple of reasons for this.  The most important being that the owner knows how the dog will behave when it encounters a snake.  Each dog will behave a little differently from yelping and running away to just carefully skirting the snake.  You want to know the behavior in case of an encounter while on a walk through the woods.

The trainer should use a radio controlled shock collar.  Some people condemn this kind of tool as inhumane. Frankly, they are being silly.  You would MUCH rather your dog get a harmless shock than a snake bite.  Other methods, such as a water spray or loud noise just don't have the impact of a shock that isn't associated with a human in any way.  Besides, my dog loves getting sprayed with water.

So, a perfect session would consist of the trainer telling you what is going to happen and walking you through the steps first.  Then, you walk the dog over to the empty cage so it can be inspected and the dog gets familiar with the cages.  Then you walk by a cage with the snake in it.  The dog will get interested in the snake, go over, and inspect it.  When the trainer is assured that the dog has the scent, sight, and sound of the snake, the dog will get a shock.  Both you and the dog then run away from the snake to safety.  After a couple of  'good boys' you walk towards another cage with a snake or two in it.  The dogs reaction will vary a lot on the second cage.  Some dogs will want to go after the next snake, but most will shy away and not approach.  The last step is to allow the dog to wander freely (no leash) as you walk by the snake cages.  Your animal should not approach the snakes and may even warn you to stay away.

You see what is happening.  The dogs inherent curiosity will cause it to go to the snake and sniff around, the shock will tell it that this thing hurts, and running away will show the dog that it's OK to get away from harm. The empty cage will make sure the cage isn't a factor in the training; your dog will not be afraid of cages.  The live snake moves around, rattles, and probably will strike the side of the cage during the session.  You have safely exposed your pet to a dangerous situation and taught it how to respond.

The trainer should offer a second session a few weeks after the first to assure both you and the dog that the training has taken hold.  Personally, I like to take the dog back yearly to walk by the cages to be sure the little guy remembers those things are bad, and refresh my memory of the dog's behavior in this situation.

There are trainers that insist that dead snakes work just as well.  This simply isn't true.  You'll have a dog carefully trained to avoid dead snakes; not very useful.  There are other trainers that insist that they walk your dog through the course.  Their reasoning for this is the timing of the shock correction.  If it is given at the wrong time, you may not get the best results.  While this is true, it's really easy to tell the proper time for the correction.  Simply wait until the dog's entire attention is on the snake.  All of us with dogs know when that point happens; we've pulled our dog out of enough gopher holes to be quite familiar with it.  A snake trainer can easily tell while they are standing at the side watching us walk our dog up to the snake cage.  Special measures should be taken to keep the dog from associating the cage with the correction.  That's why an empty cage is a good idea at the start of the training course.

The first dog I had bitten by a snake was a loving little silky terrier.  He just wanted to play and was bitten on the side of his head.  Even though I got him to the vet within thirty minutes, he died.  I've had every dog since snake trained to protect them as much as possible from this particular danger.  The second dog that was bitten is detailed on the previous entry of this blog.  This little guy was just too young for the training and unlucky.  However, he not only survived the bite, he is totally recovered, and had his first training session just this morning.  In both cases, the vet bills were quite high; many, many times the cost of the training.

Several times now I have been with a trained dog when we encountered a rattlesnake in the wild.  In all cases, the dog alerted me to the danger before there was a possibility of a bite.  Think of snake training as a way of teaching the dog to warn you of danger when out for a walk or a run.  This means that a snake trained dog can warn children of danger when it's outside playing with them.  It certainly beats sit, roll over and beg for utility and usefulness and makes the cost of training sound worthwhile doesn't it?

This is the best training a person can give their pet if they live where such an encounter is possible.  If you live in Manhattan or the center of LA, it may not be necessary, but if you live in the suburbs skirting farm country or take your dog camping, consider doing this to protect your pet.

Monday, October 1, 2012

I love the desert, but....

Look at the picture below:


See the rattlesnake?  Here's a closer look:


If you look closely enough, you'll see the holes in its head from the 22 caliber snake shot rounds that killed it. This snake was hiding up against the side of my house inside the yard.  I discovered it when I went to pick up a toy my Irish Terrier puppy had left when he ran around the house.  It was dark and the snake's natural camouflage made it nearly invisible.  It didn't rattle until I actually almost stepped on it in the dark.

Yes, it did strike my dog.  The little guy was huddled up against the door into the house suffering from shock.  I grabbed the dog and headed straight for an emergency Vet's office.  

In answer to all comments about snake training, snake vaccines, watching my dog closely, keep it on a leash, etc.  The little guy is a little less than four months old.  The youngest the snake trainers will take him is 4 months and I already had an appointment for later this month.  The snake vaccine is usually given in February so it will be strongest in the spring when the snakes come out.  He was inside a fenced yard playing around my patio.  Crap like this sometimes happens no matter how many precautions you take.  And, yes, I often carry a handgun to handle situations like this, but neither I nor the puppy saw the snake in time to prevent the strike.  The handgun made short work of any possibility of this snake causing any further problems.

This is a picture of the little dog when he first came to live with me:


And here he is a couple of days ago, watching me fill his food bowl:


Fortunately, I've been overfeeding him and have gotten his weight up to almost 15 pounds so there was some body mass there to help with the snake venom.  He goes on a couple of half to three-quarter mile walks almost daily to build up some muscle and bone strength so he was very healthy.  And, he has every vaccination known to veterinary science, except snake, so opportunistic canine diseases are unlikely.

Barkley (his name) has been in the vet hospital now for over twelve hours, received lots of fluids, some narcotic pain killer, and two (and counting) vials of antivenin.  He's mostly out of shock and doing well considering the circumstances.  I'm going to go visit him in a few minutes because they are scheduled to do blood work on him soon to see how he's doing.  I want the results first hand.

So, you folks that have an aversion to handguns and people that carry them, think about this a while and what you would have done if it had been your dog.

Or child.

Update Oct 1, 2012 9:30PM:  Barkley can't come home tonight because his clotting factors are not good enough.  He'll have to stay tonight and may be able to come home tomorrow.  He's mostly alert and wants attention so I spent about a half hour in the floor with him hooked to an IV to let him know I was still around and hadn't abandoned him.  Last night when I left him, his head looked a lot like a bowling ball from the swelling; that has reduced a lot and he's eating.  I got another patient's person to take a picture of the little guy:


The red bandage is to protect his IV and the cone is because he kept trying to chew it.  They call it a 'No Cone' because they get tired of telling them 'NO' when they start chewing at the equipment.  He's eating and recognized me the minute I walked in the door.  Looks good for the little guy.

I'm going to get a flashlight now and wander around the house to see if there are any more snakes hanging around.

Update 2 October, 2012 12:25AM:  Got a call from the vet and Barkley's clotting factor improved and he said I could come get him.  The little guy is home running around chewing on a rawhide bone.  When I went to pick him up, he literally ran over to me.  This was far, far different from the little puppy in shock from a rattlesnake bite that I took to the hospital Sunday night. I may post a picture of him with the remaining swelling, but first Barkley and I are going to bed.

Don't ever say anything bad about an emergency veterinarian.

Update:  I put together a blog post about snake avoidance training <link>, do this if you have any worries at all about your dog.  If you take long walks in the wilderness or take it camping with you, it would be a really good idea.