Saturday, October 13, 2012

Using a Wiki for Technical Documentation

If you still produce technical documentation as PDF files then let me introduce a very cool tool to you. It's called MediaWiki. It's the engine behind a little site you might have heard of, WikiPedia. It's pretty easy to get up and running, and is totally free.

Most people think of wikis as user generated content, but these are also handy for documentation projects where there are few authors but many readers. Most good documentation has two types of content: specifications and examples. The specifications explain how the thing works and are "locked down" as changes are restricted. The examples section is more free-flowing and it is desirable for users to add their own examples. The nice thing is that MediaWiki can be used for both. For specifications you can protect pages so that only a select group of users can make changes to them while at the same time leaving the example pages untouched.

Using a Wiki to Reduce Support Costs

In any product, a support call or email is typically "how do I do X?" and the user may or may not have actually tried to research the problem first. When receiving a request like that the knee-jerk reaction is to explain to the user in a response how to solve the problem. But that only works that one time, and the next time that someone has the same question you'll have to answer the question again. Now many companies turn to user forums, hoping in vain that users will search through the forums for the answer before asking again. But few do, as forums are often full of questions and rarely full of answers.

The better way to answer a support question is to answer the question by creating a Wiki page. This has several benefits. First, the next time that someone asks the same question you can answer the inquiry by sending the user a link to the article (whilst also kindly reminding him to RTFM first). Second, it's a little easier to find a Wiki article due to the organization and searchability of a Wiki site. Finally, it encourages others to add on to the page, increasing the quality of the answer.

Wiki Advantages

There are a few key advantages of using a Wiki to document a product rather than plain PDF files.


While you can add links in a PDF document, the Wiki format naturally lends itself to creating links, not just within the document but also to external links too. This can make it much easier for users. For a Zigbee Product Wiki, anytime I used a Zigbee term I made it a link to one page that explains what that term means. Hyperlinking can also reduce redundancy in documents.


Another benefit of the wiki format is that you can assign one or more categories to a page. This makes it easy for users to find related content. It's quite easy to do, and allows users to navigate the site easier.

Easier to Maintain

One of the challenges of maintaining traditional documentation is often "who has the most recent word file" for the document. There is also a huge barrier to making any changes, as then the file has to be re-generated and uploaded somewhere. With a Wiki you always have the most recent version of the document on hand. You can create protected pages where users cannot modify the content, which is great for interface specifications.

User Generated Content

How often have you read through a datasheet and thought "why didn't they include more examples?" What would be better is for users to create examples and add it to the page. The best example of this is the MySQL documentation where the user section is as valuable (if not more so) than the official section.


With PDF documentation of course you can include images, but with a Wiki you can include almost any type of media, including videos or other file formats. In the Zigbee Wiki I mentioned previously I wanted to explain to the reader how two ICs communicate. I included an image of a logic analyzer screenshot, but then I also included the logic analyzer capture file. Users can download this and then get in-depth information about how the ICs communicate.

Wrapping Up

So, the next time you need to create documentation for your project, consider using a Wiki. It will take a bit of thought to get up and running but will be much easier to maintain, in addition to the other benefits I mentioned above.

Wednesday, September 19, 2012

Testing Battery Pulse Characteristics

Low power wireless devices typically sleep most of the time and then wake up to send a message and then go back to sleep again. In a previous post I discussed battery selection for low power wireless devices. One issue with using coin cells is that they have poor pulse characteristics, and this performance varies across manufacturers.

To figure out which battery will work for you (and get a feel for battery life) you will need to run a test. This test will involve pulsing the battery, waiting, and then pulsing it again; continuing until the battery voltage under load will no longer be sufficient for your product.

Pulse Waveform
First, you need to get the waveform of what a typical pulse looks like. The easiest way is to supply your circuit through a one-ohm resistor and capture a typical pulse on an oscilloscope. Below is an example.

To test battery life you will need to be able to reproduce this current draw. So, measure the current pulse. You don't need to get that fancy; just measure the width and height of the main pulse. For example, it may be 30mA for 5mSec. To reproduce the pulse you will need a suitable circuit. A simple MOSFET and load resistor will work. For 30mA at 3V use a 100 ohm resistor (V=IR).

Pulse Generation
To generate the pulses you can use an arbitrary waveform generator, or if it's just simple on/off, you could even just write code to do it on a microcontroller development board if that's easier. For the most accurate estimate of battery life as measured by number of pulses you will want to allow as much "recovery time" as possible for the battery between pulses. Obviously you can't wait too long though; if you pulse every 6 seconds and your battery lasts for 45,000 pulses then this will take 3 days to measure. Typically we will run a "slow" test and "fast" test simultaneously to see if wait time has any affect.

Remember that you need to measure the voltage of each pulse too to ensure that it it above your threshold voltage. This can be done in a few ways:
  • Analog DAQ, like those from National Instruments, although often these are not fast enough
  • Multimeter with output, like an Agilent 34410A DMM. This is what we used with good results. Some custom processing of the output may be required though.
  • Custom code on a microcontroller. Come to think, it might just be the easiest way, especially if you are using the microcontroller to generate the pulses too.
Whatever option you select, record how many pulses it took before failing. It might also be good to record a typical voltage measurement (like voltage readings every millisecond of the pulse) so you can see how it fades.

Test Strategy
For good measurement accuracy, perform the test on a sample of identical batteries, not just one. Five or so is sufficient. If you see lots of variability then you know to definitely not use that vendor. Test batteries from a few different vendors and use this information to determine which battery is best for you.

You also now have a good indication of real battery life and which vendor's battery is best for you. When calculating total battery life be sure to include sleep current consumption as well as the current consumed by receiving any data too.

Monday, September 17, 2012

Battery Selection for Zigbee and Low Power Wireless

Low Power Wireless Standards include Zigbee, Bluetooth Low Energy, Dash7, you name it. Often times the newest wireless standard makes a claim like "lasts 4 years on a coin cell battery!" This is usually in the earliest days of the standard before anyone has actually tried it.

Battery selection for low power wireless standards is very important. These systems typically need to run for a long time (months, if not years) and have many demands. Our ideal battery for these systems:
* Lots of capacity (measured in amp-hours)
* Small size
* Excellent peak current capability (a wireless node can pulse up to 100mA)
* Fairly flat voltage curve
* Very low self-discharge
* Dimensional stability (doesn't swell)
* Low cost
The challenge is that we're asking quite a lot from a battery. We want it to discharge very little while the device is sleeping but then also to discharge in large pulses when we transmit. Usually batteries that have excellent peak current capability have a higher self-discharge rate, and vice-versa.

When starting a new project, people will often leap into creating a fancy battery lifetime spreadsheet, showing how based on estimated current consumption the battery will last something like 13.7 years or so. If only it were so! Unfortunately reality is quite a bit different. Battery lifetime is usually quite a bit shorter and often people don't quite know why.

One of the biggest reasons why is internal resistance. This causes the battery's output voltage to drop under load, limiting the effective amount of current that can be delivered. In general, the larger the battery, the smaller the internal resistance. This is one reason why coin cells don't work well in low power wireless devices - they have too high of internal resistance and therefore cannot supply enough peak current. They'll work fine for data-logging or applications where the peak current is low (below 10mA) but for wireless devices that pulse at 30-100mA they will start to fade. Most coin cells are not specified at all for pulse current, let alone that much. Even worse, the pulse current capability will be different for different vendors' batteries. That means that Energizer may be able to handle a 15mA pulse but Maxell might be able to do 20mA pulses. It all depends on the coin cell size, geometry, etc.

My favorite battery for low power wireless devices is the Energizer L91 (AA size) or L92 (AAA size). These lithium batteries have low self-discharge, nice voltage curve, good peak capability, and you can buy them in most grocery stores.

Next I'll talk about how to test different batteries...

Friday, September 14, 2012

The Joy of Bit-Banging, part 2: RX

I previously discussed how to implement the Tx side of a bit-bang serial port, in The Joy of Bit-Banging, part 1: TX. This time I'll describe how to implement the receive side. This implementation uses blocking waits, as a result it should not be used unless you can tolerate delays.

In this implementation the receive pin is P2.5

Required definitions, etc:
#include "msp430x24x.h"
//Timings calculated using DCO_8_MHZ - modify if different oscillator speed or different hardware
#define BIT_LENGTH_9600 160
#define HALF_BIT_LENGTH_9600 76
#define BIT_LENGTH_19200 75
#define HALF_BIT_LENGTH_19200 27

/** Simple delay for bit width. Used in transmit and receive. */
void delayFullBit() {for (unsigned int i = 0; i < BIT_LENGTH_19200; i++) ; } //104uSec delay

/** Simple delay for 1/2 of bit width. Used in receive. */
void delayHalfBit() {for (unsigned int i = 0; i < HALF_BIT_LENGTH_19200; i++) ; } //104uSec delay

#define TOGGLE_DEBUG_PIN() (P4OUT ^= BIT5)  //debugging only

Output function:
* Blocking UART receiver. Called by BIT_BANG_RX_PORT Interrupt Service Routine upon detection of start bit (high to low transition).
* BIT_BANG_RX_BIT should be configured as high-low edge triggered interrupt.
* Receives a byte and then processes it.
* @note BIT_BANG_RX_PORT, BIT_BANG_RX_BIT, DISABLE_BIT_BANG_RX_INTERRUPT(), and ENABLE_BIT_BANG_RX_INTERRUPT() must be #defined. Modify accordingly for other hardware.
* @pre Oscillator configured for 8MHz
* @pre A high-to-low transition has occurred on BIT_BANG_RX_BIT
* @return the byte received
char bitBangInput()
    unsigned char receivedBitIndex = 0;
    unsigned char receivedByte = 0;
    delayHalfBit();     //Since this method was called on detection of an edge, need to wait until we're in the middle of the bit width.
    //Read this start bit - should be zero
        //error - re-enable interrupt and return  

    for (int i =0; i    {
        receivedByte |= (BIT_BANG_RX_PORT & BIT_BANG_RX_BIT) ? (1 << receivedBitIndex) : 0;     //Sample the bit, and if '1' then increase receivedByte accordingly
    //THIS IS STOP BIT (line should be back high)
     //error - line is low; should be high because this is stop bit  
    //all bits have been received!
    return receivedByte;

Thursday, September 13, 2012

Implementing I2C

Lately I've been doing a lot of I2C development. In just about every way you can do it. Over the course of a month I've had to write code to communicate with an EEPROM and two sensors via:
  • MSP430 using USCI
  • MSP430 using bit-bang
  • Stellaris using StellarisWare
  • Stellaris using bit-bang
Over the course of that experience I've gotten to know the I2C protocol very well. I won't go into the details of the protocol; there are plenty of sources for that.

When you're first getting started, the best way to verify the i2c interface is configured correctly is to not connect the peripheral, but just watch the i2c signals to see that they are being toggled correctly. By definition I2C is not a push-pull interface but uses open drain I/O. It's really quite elegant, as it prevents a bus conflict if one IC outputs a '1' and another outputs a '0'. As a result if you want to see anything you will need external pull-up resistors. I like to first develop code first without the peripheral ICs, just the pull-up resistors. This way you can connect a logic analyzer to the two signals and verify that your code is working correctly. This is especially important if you are implementing a bit-bang solution and need to check that the GPIOs are configured correctly.

If you are using a hardware based solution then it is fairly straightforward; configure the baud rate, etc. and the hardware does all the signaling. The hard part is determining how to use the various hardware registers to get the desired output. This is much easier if you're using StellarisWare, as it handles all the register settings for you.

If you're implementing a bit-bang solution, there are two ways of doing this. The first is with simple delays; the second is using a timer interrupt. I've done both. There both take about the same amount of time to implement. The first way is simpler but requires hand-tuning the amount of delay between bits to ensure the correct baud rate and a 50% duty cycle. Using a timer is a bit more elegant as you're not waiting the processor but requires a state machine to iterate through the various steps. If you're using a StellarisWare it includes a nifty little softI2c implementation that can be used decently easily.

The first test you should do is to just do a simple write of 4 bytes or so, and observe it on the logic analyzer. Of course the ACK bit will not be pulled down since there's no peripheral IC but you'll at least be able to observe proper timing and framing behavior. After you get that working also verify that reads work too.

After you get basic interfacing working, the next step is to write a simple address tester. This just writes to an address and checks to see if the write is acknowledged. This function is handy for verifying that the I2C peripheral is attached properly. This function can also be used for acknowledgment polling if you're implementing an EEPROM or FLASH interface. These types of memories take a few milliseconds to write and you must check that they are no longer in their write cycle before trying to access them again.

Once basic functionality is working you can implement the basic read/write routines. Write is easier since it's a single step operation. Reading typically requires two steps: First writing an address (e.g. register or memory address), then doing a repeat start, and then doing a read.

Since I2C has a fairly low bit rate (100kHz or 400 kHz under normal conditions) it can take awhile to write or read a lot of bytes (6mSec to read a full 64B page from an EEPROM at 100kHz). If you're using the I2C interface in a simple sensor it's fine to wait while communicating since you're not doing anything else until you receive the result. However, that would waste quite a few clock cycles; 160k if using a 25MHz clock. If you're using an RTOS or would otherwise like to minimize wait states then you'll want to implement it differently. In this case you should use DMA or at least an interrupt driven approach.

A few miscellaneous I2C hints:

Logic Analyzer
I2C is much, much easier to troubleshoot with a Logic Analyzer since it will parse the serial data stream and show you the I2C start, stops, and data. I really like one from Saleae, they're USB based and great for microcontroller use.

Mission Critical
I've had occasions whereby one of the peripheral ICs would get into a funky state and cause the I2C bus to lock up. If you're dealing with mission critical application or you just have an extra GPIO pin then I recommend controlling the power of each peripheral IC from the GPIO. That way you can "reboot" a peripheral IC if there is an issue.

Repeat Start
Several peripherals require you to implement a repeat start condition. This isn't well documented in the processor's documentation and you may need to do a bit of research to find out how to do it.

Tuesday, August 7, 2012

Checking out the new Cortex-M4 ARM core

I've been using the Luminary Micro Cortex-M3 core for awhile now. It's pretty cool, and has some nice power to it for when you're running more advanced stacks. I also started developing on TI's new Cortex-M4F Stellaris processors. The benefits of the new processors:
* Faster - standard up to 80MHz (though single-cycle flash only up to 40MHz)
* Floating Point processing
* Same or lower cost than the comparable Cortex-M3 processor
* Lower power - uses 65nm process instead of the 250nm process used on the M3 line

The best part of Stellaris (both old and new) isn't the chip, it's the software. StellarisWare is a hardware abstraction library for these processors and makes firmware development MUCH faster. It is pretty comprehensive (very few things you can't do in stellarisWare) and reasonably well documented.

The downsides of the Cortex-M4F:
* No Ethernet support
* Weird low power mode - "hibernation" but it doesn't keep the RAM alive, so you have to save your application variables
* Higher power consumption than MSP430.