Bookmarks

After playing with Xbee connected to a PIC I decided to transfer the design from the protoboard to make it more pretty and compact. The following board contains Xbee connectors, PIC18F26K20, bypass caps and Vpp limiter to use with old programmers/debuggers. I wrote several articles describing the circuit and it’s capabilities, see “Related posts” for more information.

As usual, Eagle files are available from download section. The PIC code written for Xbee protoboard will work here with very little modification. This board is good as a base for more complex sensors which require MCU on-board.

I am working on several applications for this board and will be posting results here this summer.

I just took delivery on a batch of MAX3421Es from Maxim. They are available for sale in the store for $8.00.

The MAX3421E makes the vast collection of USB peripherals available to any microprocessor, ASIC, or DSP when it operates as a USB host. For point-to-point solutions, for example, a USB keyboard or mouse interfaced to an embedded system, the firmware that operates the MAX3421E can be simple since only a targeted device is supported.

This controller is supported by open source firmware that I’m developing for 8-bit microcontrollers, including PIC18s and Arduino.

Human interface device AKA HID is likely the most simple class for USB host to interact with. Reports are easy to parse and timing is not critical. In addition to that, HID standard defines simplified variety of the protocol, called “boot protocol”.

Modern USB keyboards, as well as mice, support boot protocol. It was designed to be used by PC BIOS during POST setup. No report parsing is necessary; as soon as device is put into configured state, it’s interrupt IN endpoint starts generating fixed-format 8-byte packet. This packet contains basic information about peripheral events. For keyboard, such packet contains information about modifier keys (control, shift, alt ) plus keys pressed. Mouse would give state of up to three buttons, plus amount of travel in X and Y direction since last poll.

Look at the code, function HIDMprobe or HIDKprobe. This function is called during enumeration to configure device which was just attached. By default, HID peripheral is configured to talk report protocol. In order to change it to boot protocol, host has to send “Set protocol” request with single data byte set to 0. After this is done, device starts generating interrupts( i.e., host can start periodically polling interrupt endpoint for new data.

It is worth mentioning that not all HID devices support boot protocol. Interface subclass set to 1 indicates that boot protocol is supported for this interface.

The first byte in 8-byte packet from a keyboard contains states of modifier keys – Control, Shift, Alt, and Windows. The next byte is reserved, it’s state means nothing to us. Last 6 bytes is a keyboard buffer – it contains so-called HID codes of keys being pressed since last poll.

All data on USB bus is transferred under host control. Even though some transfers are called IN and some other OUT, they all start at the host. There are four types of transfers, the most interesting of which is control transfer. This type of transfer is used all the time in communication with every class of devices. In this article, I give a short description on programming control transfers.

Control transfer consists of three steps( or stages ): setup, data, and status. Some of them carry necessary data in setup packet itself and don’t have data stage at all. Good example of such short request is “Set address” – the information to transfer is just one byte and is sent by filling a certain setup packet field.

Even though USB specification defines several different destinations for the transfer, such as device, interface and endpoint, on the lowest level each packet address consists of two parts – device and endpoint. Some endpoints are IN or OUT only. Other, such as “default control pipe” AKA endpoint 0, are bi-directional. Before each transfer can be sent out, peripheral address must be loaded into MAX3421E PERADDR register.

A couple of updates. First, second prototype for the breakout board arrived from BatchPCB (pictured on the right ). I placed an order for the first batch with PCBcart, it is supposed to be here in 2 weeks. Also, I made this prototype public at BatchPCB, this is the product link. The prototype has a little defect – the USB connector is placed a little bit too close to resistors; however, it’s totally buildable, just make sure you insert USB connector last, when the rest is soldered and checked.

Second, I created a code repository for the project. From now on, all firmware development will be posted there. The hardware files don’t change that often; they will still be hosted here in downloads section.

At present, the code doesn’t do much past enumeration. From USB point of view, it knows how to generate control and bulk-IN transfers; bulk-OUT is going to be written together with mass storage client driver code, which is going to be next big step. Also, it is probably buggy and this is my reason for publishing it – “given enough eyeballs, all bugs are shallow”. If you try the code and it doesn’t work, let me know. Or better yet, fork a code, fix it and let me know what you fixed and why.

In previous article I wrote about ways to build the project. Picture on the right shows one built on a piece of protoboard. The PIC is clocked at 64MHz using internal oscillator and SPI clock is 16MHz. It works well.
I’d like to start describing the code with an overview of a project layout. All project-related definitions are contained in project_config.h file. Types like BYTE, WORD, BOOL are defined in Generic_Types.h, the rest goes to a header file with the same name as .c module.

At present, the code consists of SPI functions, MAX3421E register read/write functions, MAX3421E event handler, and a small CLI used primarily to aid in debugging. SPI functions are explained in Interfacing LCD via SPI article, take a look if you haven’t already. In this article I will be talking about MAX3421E low-level routines.

Xbee module supports two modes of operation – transparent mode and API mode. To create simple point-to-point links, Xbee works nicely in transparent mode without much coding. However, if your goal is to build a network consisting of more than two devices, AT mode becomes too difficult to bear. You will spend almost all the time switching in and out of command mode, wasting time and draining batteries in the process. On the other hand, in API mode commands and data travel in specially formatted frames and no switching is necessary. Another advantage of API mode is that serial speed on transmitters doesn’t have to match – one can be configured for 115200bps, another for 2400bps, third left with default 9600bps. There is another nice feature called remote command; you can remotely request the state of Xbee module pins, for example, or change an output pin level. It means that for simple measuring and control applications no MCU is even necessary at the sensor.

API mode requires re-flashing module firmware and some extra coding on both sides of the link. I started with upgrading the firmware. Picture on the right shows X-CTU screen with serial speed drop-down expanded – along with loading API firmware I’m changing the speed of coordinator Xbee to 115200.

First of all – breadboards are evil. Sure, they are handy. But when you spend a whole day chasing glitches which drive your logic analyzer crazy, it’s not fun. I moved my Xbee setup on a protoboard; picture on the right shows the result. The capacitor on Xbee VDD pin is essential – the module generates pretty strong spikes every time it starts transmitting and without the capacitor one should expect to see glitches every 250ms or so. The manual recommends bypassing VDD using 1uF and 8.2pF caps in parallel; I’m using 0.1uF here and it works well also.

In the previous article, I talked about switching in and out of command mode on an Xbee module running AT firmware. You can do exciting things with AT commands; however, when you interact with the module via RF link, how are you supposed to see the output of an AT command? In command mode, all output goes back to the PIC USART, so we need a method to capture it and send back to us.

The following function is called from CLI. It queries every AT command, stores the result, and sends it back after going back online. The usual way of doing that is to switch to command mode, issue all the commands capturing output to a buffer, then switch back online and send the buffer contents back. PIC18 doesn’t have enough RAM to hold such a big buffer, that’s why this function queries one command at a time. Because of that, the function is quite slow – the guard time before sending “+++” is one second plus it needs to wait for RF transmission of previous result to complete before switching to command mode for the next query. It takes approximately 3 seconds per query and querying about 60 commands takes 3 minutes.

In the previous article, I described a simple wireless setup using a pair of Xbees connected to PIC microcontroller and serial port of a Linux machine. After finishing the article, I continued working on the project and that’s what I have found so far.

First, using router firmware in Xbee module is bad for your batteries. In this configuration power consumption is steady 40ma. In addition to that, sleep is not working. After loading end device firmware power consumption dropped to 5ma on average and I was able to use Sleep pin. Measured current in sleep mode is less than 1ua – not bad. Second, PIC18F4520 is not the best PIC for sensor applications. Newer K-series PIC18s with their internal 1.2V reference, such as PIC18F26K20, are much better. In addition, they can be clocked up to 64MHz, and they are cheaper. At the time of this writing PIC18F26K20 in DIP package sells for less than $4 in single quantities on Mouser.

As I mentioned in the previous article of this series, the schematic of MAX3421E board differs very little from datasheet reference design. It consists of MAX3421E itself, MAX4793 USB current-limiting switch, MAX6349 3.3V regulator, plus a dash of resistors, capacitors and connectors. Some parts are optional; for example, if you prefer leaving USB power line (called Vbus) unrestricted, don’t solder MAX4793. Also, if you don’t mind using 2 power supplies – 5V to supply Vbus, and 3.3V for MAX3421E, then leave MAX6349 unpopulated as well. Alternative power pins are provided on the board.

The 3.3V regulator can also be substituted with LDOs from other manufacturers either “drop-in”, like ones from National Semiconductor (example: LP3990) or with minor modification – cutting a trace or two (example: TC1040 from Microchip). Look for LDO in SOT-223 package and check pin assignment against MAX6349 datasheet.