Following is a very detailed description of my microcontroller
based device multiplexing/interfacing system. Warning: it is
a very long message and may be sleep inducing :)
Earlier this week I was describing my microcontroller based
device multiplexing system. One of the comments (by Eric) was
that it seemed to be quite a heterogeneous collection of parts.
>From a hardware (processor) perpective it is, but from a software
(protocol) perspective it is very homogeneous and is actually
quite simple. I thought I'd share some more details on what I
have done so far, and plans for enhancement. I thought that some
of you might find this interesting, and also figure that I might
get some interesting and useful feedback.
First, some background history. I have always wanted to have the
abilty to interface many non-standard input/output peripherals
and multiple sensors and/or data acquisition devices to my
wearable. My earlier approaches to this were centralized (as
per Eric's comment) running on the pentium CPU, connected to
many serial ports. In an earlier design, I specifically looked
for a carrier board with four buffered serial ports for this
reason (to attach many devices). I used the Cell Computing
Mighty Mite (CardPC carrier) because it had 4 serial ports. But
I discovered quicky that even 4 ports were not enough. The ports
were quickly used up by the twiddler, GPS receiver, ricochet
modem, and serial LCD display. I wanted the abilty to interface
all of these devices plus many more (primarily sensors). I
looked into adding more serial ports via a multi-port PC/104
card, but it was too big, bulky, and expensive. I also tried
expanding the number of serial ports with PCMCIA serial cards,
this worked but also had some disadvantages. I did not want to
use up a PCMCIA slot just for RS232, in fact I wanted to
eliminate PCMCIA altogether to save weight and bulk on my core
CPU enclosure. I thought about separating a PC/104 perpheral
card (either a multi-port serial card or dual PCMCIA module)
via PC/104 cables, thus "flattening out" and distributing the
hardware on my body, but the necessary cabling is way too
bulky (since there are 104 wires between the modules and
connectors are bulky).
Prior to using the Advantech PCM-5822, I had a system based on
CardPC. It started with two modules, a Mighty Mite carrier
board and dual PCMCIA PC/104 module. This was not bad from a
weight/bulk perspective but had no audio. In order to provide
audio support I added a PC/104 Crystal/MM audio card, but that
made the overall system way too big. I then replaced the Mighty
Mite carrier board with a new carrier board with dual PCMCIA
slots onboard. This was an improvement since it eliminated the
PC/104 PCMCIA module, but it was bigger (longer and wider) than
the Mighty Mite carrier (and the board is now obsolete). I was
still not happy having a whole PC/104 module for audio. At the
time I could not find any PCMCIA or USB audio devices, so I
moved to the Advantech PCM-5822 with audio onboard. This was
very desireable for weight/footprint since it gave me (almost)
everything I needed in a single 4 x 6 inch module. The challenge
was that I only had two RS232 serial ports. Two good things
happened at the same time: twiddler moved to PS/2 and ricochet
moved to USB, therefore it was possible to get by with only
two serial ports for GPS and serial LCD display. But this left
me with no free ports for adding sensors or other devices. I
could of course go back to adding a multi-port serial card
and/or dual PCMCIA module, but I don't want to do that for
four reasons: it's too expensive, it's too big, it's too power
hungry, and it's overkill (I don't need anywhere near 115.2k
baud, most of the devices I want to interface only require a
measly 9600 baud. I therefore decided to use microcontrollers
to multiplex multiple devices on a single RS233 serial port.
This has proved to be an interesting and powerful distributed
approach. Here are some details on the design.
My first goal was to connect a microcontroller to one of the
serial ports and connect a GPS receiver, LCD display, and IR
decoder (for infrared remote control). This was actually
surprsingly easy to do since all three are devices that use
simple serial communications. The first design simply took any
data from the host (CPU) and sent it to the LCD display, and
took data from both the GPS and IR decoder and sent them to
the CPU (with some simple protocol codes to distinguish data
types). Although this was simple it proved to be quite powerful.
I recently added more devices including temperature, humidity,
and barometer sensors, a bank of A/D converters, and an LED
bar graph display. All of these devices are connected to a
single RS232 port and sharing the low band width (19200 baud)
connection with the CPU. One small microcontroller acts as a
router, routing requests to the appropriate peripheral pins
and passing data between the devices and the CPU. To get an
idea on the complexty of multiplexing these various devices,
here is an overview of the devices and their protocols:
1) The SGX-120L text/graphics LCD from Scott Edwards
Electronics is already an RS232 serial device. It connects
at 9600/8N1 and has its own set of control odes. It requires
only one pin on microcontroller (receive data). Any text
sent along this channel will display on the LCD, and there
are a set of control codes (CTL-letter) and escape codes
(ESC-letter-number) to control features like backlight,
cursor positioning, and graphics commands. The LCD display
required RS232 level data, so I added a MAX232 level
converter between the microcontroller and display.
http://www.seetron.com/sgx120_1.htm
2) The Motorola Oncore GPS receiver is an OEM module that
aleady has data transmit and receive serial ports for TTL
connection to a microcontroller. These are directly wired
to general purpose pins on the BX24. The GPS receiver can
operate in NMEA protocol format or in Motorola binary
format. There is also an ASCII string command, which is
the simplest protocol, and this is what I am using. To
get a GPS reading, all you need to do is open up a
9600/8N1 serial connection and send a command (@@eq)
along with checksums per the motorola format specs. You
get back a simple ASCII string containing the most
important GPS data (position, time, date, etc).
http://www.motorola.com/ies/GPS/products/prodgt.html
3) The Radio Shack 276-137B IR Detector Module is very easy
to interface. It connects to one of the general purpose
pins on the microcontroller and is a simple serial device
operating at 893 baud, 8N1. To read data all you do is
open the port and listen. The IR decoder sends codes each
time a button is pressed on the IR remote control, and
there is a unique code for each button on the remote.
http://www.hometownvariety.com/credcarunrem.html
4) To add sensors for humidity and barometer, I used a kit
from www.phanderson.com called the serial weather kit.
The kit includes a pre-programmed PIC microcontroller
already set up to interface weather sensors. It is
possible to interface wind speed and rain guage devices,
but these are not practical for wearables, so I am using
the kit for just humidity and barometer data. All I had
to do was assemble the electronics and connect my BX24
microcontroller to the IO pins on the pre-programmed
PIC. To get a reading I simply open a 9600/8N1 serial
connection and send any character. The PIC returns an
ASCII string containing the sensor readings.
http://www.phanderson.com/weather/index.html
5) To add sensors for multiple temperatures, a bank of
12-bit A/D converters, and an LED bar graph driver, I
used another kit from www.phanderson.com. Like the serial
weather kit, it includes a pre-programmed PIC. This kit
can address up to 256 DS1820 temperature sensors (along a
single twisted pair) but I am only using seven of these.
The A/D ports are set up with filter capacitors and
resistors and are terminated with screw terminals on the
wearable for easy dynamic attachment of a varety of
sensors. The general purpose ouputs of this kit drive the
LED bar graph in my case, but they could also be used to
drive relays or could be read as general purpose logic
level inputs. Interfacing the PIC is easy, it's just a
9600/8N1 serial connection. To get readings you send
text with a simple protocol of text commands.
http://www.phanderson.com/t64.html
If you look at the protocols for all of these devices, you
can see that although the technologies are diverse, they all
operate on simple serial connections, most at 9600/8N1, and
all operate on simple ASCII based data and commands. This
makes it easy to interface them all to a microcontroller and
ultimately to applications running on the CPU. Here is a
diagram showing how my components are laid out physically.
It shows the pin connections for all devices connected to
a single BX24 microcontroller attached to the CPU.
Pentium CPU Rx <----- pin 1
RS232 Port Tx -----> pin 2
Motorola GPS Rx <----- pin 11
Receiver Tx -----> pin 12
Text/Graphics <------ Max232 Level Rx <----- pin 5
LCD Display Converter
IR Decoder Tx -----> pin 13
Pressure Sensor <---> PIC Weather Rx <----- pin 8
Humidity Sensor <---> Microcontroller Tx -----> pin 9
Temp Sensors <---> PIC Sensor Rx <----- pin 6
A/D Converters <---> Microcontroller Tx -----> pin 7
LED Bar Graph <----
Once these various devices are phyically connected, the
challenge becomes one of software protocols. Communication
with any given device is easy, simply open a serial port on
the desired pin(s) and request data. For example, to get a
GPS reading, the BX24 configures its COM3 port to pins 11
and 12 at 9600/8N1 and sends a command out pin 11, then the
GPS send the data on pin 12. Programming for any single
device is easy, but managing all of them is a bit more
challenging. In order to simplify the communications, I
designed a simple protocol of control codes to identify
requests coming from the CPU. The protocol consists of an
escape character (ASCII 27) followed by a CTL-letter
combination specifying the device, and in some cases an
additional parameter. The codes look like this:
ESC CTL-D [Data] - send command to LCD display
ESC CTL-L [DevceID][State] - send command to LED display
ESC CTL-T [DeviceD] - request temperature reading
ESC CTL-A [DeviceID] - request ADC reading
ESC CTL-G - request GPS reading
ESC CTL-H - request Humidity reading
ESC CTL-B - request Barometer reading
Establishing this command protocol made programming easy on
both the microcontroller and CPU. The BX24 just sits there
and watches for incoming data from the CPU on the RS232
serial port (pin 2). It reads the data one byte at a time
and checks if the byte is an escape character (ASCII 27)
indicating a command (not data) from the CPU. When escape
is detected it reads the following byte to determine which
function is being requested (for example hexadecimal 7 is
CTL-G which indicates a GPS request). When the control code
is read, the BX24 opens a serial port on the appropriate
pin, and leaves it that way until another escape code is
detected. All subsequent data will then route through the
BX24 to the selected device. For example, if the CPU sends
ESC CTL-D, the BX24 microcontroller sets up pin 5 as the
ouput port, and all subsequent data from the CPU routes to
the LCD display. If later the CPU sends CTL-G the port is
configured for pins 11 and 12. The control codes for the
specific device are programmed on the CPU (not the BX24
microcontroller), and the microcontroller simply acts as
a router. The BX24 also uses these same ESC CTL-# codes
to wrap data, so the CPU knows what kind of data is being
received on the serial port. For example if the received
data begins with ESC CTL-G the CPU knows it is GPS data
and invokes the proper data parsing routine. Aside from
managing connections and inserting control codes in return
data, the BX24 also formats all return data to be comma
delimited in the same way. This makes it very easy for the
CPU to identify (by ESC CTL code) and parse (by comma
delimiters) incoming data into variables.
Establishing these "handshaking" or "routing" codes was
only half the battle in multiplexing. The codes are simple
enough that they can be manually keyed in a serial terminal
like minicom or hyperterminal (which is good from a generic
protocol perspective). But the next challenge is one of
timing, priorities, and coordination. Some of the devices
are polled (sensors and GPS) while others receive commands
(LED and LCD displays). These are easy to manage, but
interrupt devices (like the IR decoder or a keypad) need
special attention. In the case of commands coming from the
CPU, the task is easy, just watch for the ESC CTL-# code
combination and open the appropriate port. The problem is
that only two serial ports can be open at the same time on
the BX24 microcontroller, and one of them is always
connected to the host CPU. This means that only ONE of
the attached devices can operate at a time. My approach
therefore is to follow these simple rules.
- When no requests are coming from the CPU, always
default to watching the IR decoder port for interrupts
from the user. When IR data is detected, block all
other requests until the received IR data is sent to
the CPU.
- Always watch for commands from the host CPU, but only
keep the serial ports connected to peripherals long
enough to process the command, then default back
to watching for IR data.
On the host side of things I created Java interfaces to all
of these devices. This makes it very easy for any application
(local or remote) to access the functions and data. I created
two Java applications to manage these connections, one is a
device proxy server wich receives commands and sends them to
devices, and the other is a proxy listener which receives
data from devices and passes them to an application. Here
are a couple of examples of the Java interfaces:
TextDisplay.writeln("hello world from LCD display")
The Proxy Server opens a serial output connection to the
BX24, sends the ESC CTL-D code, and then sends the text
down the port. The BX24 receives the control code, opens
up pin 5 as output, sends the text to the display, times
out, closes the LCD port, and defaults back to watching
for IR data on pin 13.
GpsRecever.getPosition()
The Proxy Server opens a serial output connection to the
BX24, sends the ESC CTL-G code, and sends the GPS command
down the port. The BX24 receives the control code, opens
up pin 11 as output and pin 12 as input, and sends the
GPS command to the receiver. The GPS receiver sends the
data back on pin 12, and the BX24 passes the data to the
CPU, times out, closes the GPS port, and defaults back
to watching for IR data on pin 13. On the host CPU, the
proxy listener receives the ESC CTL-G code indicating
GPS data, parses the data into variables, and passes
the data on to te requesting application.
Now that I have completed this basic framework for device
multiplexing, I am planning to do some more enhancements
to make a better, cleaner interface. The goals are to
separate processing based on communication connection
types (polled/interrupt/process), reduce the amount of
data sent across the host communication port, and allow
for better prioritizing of tasks. On the microcontroller
side of things, I plan to create separate tasks for
each of the following:
- Interrupt Devices - This currently includes only the
IR remote control, but will soon also include a small
matrix keypad a couple of buttons/switches, perhaps
eventually small potentiometers or joysticks. These
devices are being separated from the others because
they are interrupt devices that must take priority
over all others when in use. Also, whenever the other
devices are passive, the system must watch for
interrupts from these devices. By placing them in a
separate multitasked subroutine I can control the
priority of CPU cycles that they receive, and also
can give them exclusive access to all CPU cycles
when in operation. Data from these interrupt style
devices are passed on to the proxy listener which
in turn can pass events to applications. The Java
approach allows any application (local or remote)
to subscribe to listening to any device.
- Process Devices - These currently include the LCD and
LED displays, but could also include other outputs
like audible signals or relay control. Requests are
managed through the device proxy server on the CPU,
and devices are connected by the BX24 microcontroller
on demand. Timeouts are set up so that as soon as any
given command is processed, the system returns contol
immediately to the interrupt devices. On the CPU side
all of these services are remote interfaces, allowing
any process (local or remote) to invoke them.
- Polled Sensors - The current approach is to have the
CPU (not microcontroller) make requests for sensor
data. This works fine, but tends to make the overall
system harder to program, and introduces a lot of
serious timing/coordination problems for both the
interrupt and process devices. I am therefore making
a choice to have the BX24 automatically cycle through
all sensors repeatedly and send them to the CPU. This
reduces overhead (band width) of incoming commands and
makes the prioritizing of CPU cycles much easier.
Whenever both the interrupt and process devices are
passive (no current activity), the BX24 will poll the
GPS, ADC, Temp, Humidity, and Barometer sensors and
send them to the proxy listener automatically. New
commands will allow programs to start and stop the
polling and to select the polling frequency. One very
nice benefit is that the proxy listener on the CPU
always has the most recent data from all of the sensors,
allowing very fast acquisition from any local or remote
application, without affecting the interrupt and
process devices.
On the CPU side of things, I could have a single proxy
server app manage both requests and responses, but I am
intentionally separating these. The proxy device server
is only an invoker, and the listener only receives data.
Both are remote servers allowing control/monitoring by
any process (local or remote) on the internet. The proxy
listener in particular will be interesting, since it will
allow multiple processes to register to be notified of
any given event, or even a threshold of sensor data.
For example a remote app could respond to my GPS coords
exceeding specified bounds or call a doctor if my body
temp goes above or below acceptable olerances. The same
kind of abstraction of services will be done on my home
and vehicle systems, allowing some very powerful
notifications/messaging among remote systems. The final
challenge will be creating the framework that connects
between my "proxied" devices and the applications that
use them. I think I will try out the jAugment framework
for this. My first target apps will be GPS logging and
mapping, time/location stamping of sensor data, and
remote monitoring and notificaitons.
This comment is targeted to Marcus Wolschon, the author
of the jAugment framework, who is seeking testers for
his wearable system. My low level device architecture
would make a very good testbed for jAugment. I suggest
that we try to set up the same device framework on your
system (I can help you do that quickly), then we can
work together on the creating of a wearable application
framework for all of these devices. One of the really
cool things is that we could demonstrate powerful
remote interactions between our wearables from across
the world (or at least from across the pond). For
example you should be able to read my sensors and
display on your text LCD and vice versa. If we work
together we can iron out the bugs/features in both
jAugment and my device interfacing/multiplexing code,
create useful apps for everyone else, and test the
whole system for general public release. Let me know
if this sounds interesting to you.
If anyone else has any questions, feedback, or suggestions
relative to this muxing and interfacing, by all means fire
away. If you are interested in adding some of all of these
features to your wearable, stay tuned, I will be making a
cookbook including schematics, build tips, source code,
and applications for all of this.
-- Java Jacket's Doug Sutherland
------------------------------------------------------------
Grow your own Wearables: http://wearables.los-gatos.net
What I'd like is to have you call me and my jacket answers
------------------------------------------------------------
--
Subscription/unsubscription/info requests: send e-mail with subject of
"subscribe", "unsubscribe", or "info" to
Wear-Hard Mailing List Archive (searchable): http://wearables.blu.org
please, Please, *PLEASE* don't subscribe through a forward/false domain
From Wear-Hard Mailing list Archive (WH)
Maintained by R. Paul McCarty
Archive created with babymail