Reading sensor values and controlling the MSP using IPC
Introduction
CMU's IPC package is a collection of software that facilities message passing between programs, including those on different hosts. It supports both publish/subscribe and request/response semantics. The msb-server and lsb-server can publish the sensor readings they receive from the sensor boards over IPC. Additionally, many parts of the MSP can be controlled by sending IPC messages. You can easily develop your own applications to receive and send messages. Applications can either be message-driven or periodically poll for new sensor readings.
IPC application requirements
Initializing IPC
All IPC applications must call msp_ipc_initialize(argc, argv) before using any other IPC functions.
Subcribing to messages
Most IPC applications then subscribe to various messages by using the functions defined in msb_interface.h and lsb_interface.h (e.g. msb_subscribe_accel_message). When subscribing to a message, you must pass a pointer to a structure used to store the message, the function to be called that will handle the message, and if multiple messages are received between IPC polls, whether you want all messages (MSP_SUBSCRIBE_ALL) or just the latest (MSB_SUBSCRIBE_LATEST). You can also specify MSB_UNSUBSCRIBE to stop receiving messages.
Message handlers
IPC message handlers receive data in structures specific to the message type. These structures are defined in msb_messages.h and lsb_messages.h.
Receiving and dispatching messages
If your application is entirely message-driven, simply call IPC_dispatch() after subscribing to all of the messages you're interested in. You can also periodically poll for and dispatch IPC messages by calling IPC_listen, which takes the number of milliseconds to wait for a message as an argument.
Querying system state
In addition to subscribing to messages, you can also query the system for various bits of information about its state, including the sampling rates. While you can use the IPC functions directly to do this, it is recommended that you use the wrappers defined in msb_interface.h and lsb_interface.h (e.g. msb_request_schedule). The structures passed to these wrappers are defined in msb_messages.h and lsb_messages.h.
Controlling the system
Many aspects of the MSP can be controlled using IPC messages. For example, you can set the MSB LEDs, start and stop logging, and adjust the sampling rates. Again, it is advisible to use the wrappers defined in the *_interface.h files.
Linking to the IPC libraries
IPC applications generally require libglobal and libipc to be linked in. In addition, you'll need to link in the library for the sensor board you are using (e.g. libmsb_interface). See the example Makefile below for an example.
A simple IPC example
This simple example shows the bare minimum required to receive sensor readings from the MSB. It displays accelerometer readings along with their timestamps.
msb-ipc-demo.c: <c>
- include <stdio.h>
- include <msp/msp.h>
void msb_accel_handler(msb_accel_message *data) { int i;
for (i = 0; i < data->num_samples; i++) { printf("Accel data received: X: %f, Y: %f, Z: %f, Timestamp: %d %d\n", data->sample[i].accel[0], data->sample[i].accel[1], data->sample[i].accel[2], data->sample[i].time_counter, data->sample[i].interrupt_counter); } }
int main(int argc, char *argv[]) { msb_accel_message data;
msp_ipc_initialize(argc, argv);
msb_subscribe_accel_message(&data, (msp_handler_t)msb_accel_handler, MSP_SUBSCRIBE_ALL);
IPC_dispatch();
return 0; } </c>
Makefile:
include ../Makefile.conf MODULE_NAME = "MSB-IPC-DEMO" MODULE_COMMENT = "MSB/IPC Demo" CFLAGS += IFLAGS += LFLAGS += -lmsb_interface -lglobal -lipc SOURCES = msb-ipc-demo.c PUBLIC_INCLUDES = PUBLIC_LIBRARIES = PUBLIC_BINARIES = msb-ipc-demo MAN_PAGES = TARGETS = msb-ipc-demo msb-ipc-demo: msb-ipc-demo.o # rules include ../Makefile.rules
Inter-host communication
One of the big advantages of IPC is that you can easily pass messages between applications running on different hosts. central is the main application of IPC that all components connect to over TCP/IP. Applications can run on different hosts by simply defining the environment variable CENTRALHOST on them and pointing it to the name of the host central runs on.