Wiki

Case Status
Log In

Wiki

 
PM2+InterfaceSpec
  • RSS Feed

Last modified on 6/13/2019 1:08 PM by User.

Tags:

PM2+InterfaceSpec

(copied from concept2.com before website redesign 2019)

This interface specification describes how an RS-232 serial enabled device can communicate with the Concept2 PM2+ Monitor. An external device can receive distance, pace, time and heart rate information from the PM2+. The document is intended to aid experienced programmers who already possess a working knowledge of a programming language and RS-232 communication.

Requirements

To interface with a PM2+ Monitor running with microcode v141 or v138, an RS-232 device needs to be set to run at 9600 baud, 8bits, no parity, with one stop bit. Connect the serial cable to the top jack on the back of the PM2+ Monitor as it would be connected if you were using E-Row. Please make sure the serial communication is set up on your machine.

Contents

This document first outlines the commands and data formats that are supported by the PM2+ Monitor. A description of the status byte follows at the end of this section. Following this section is an example of serial communication between a PC and the PM2+.

Two examples of sample code are included with this document. The first sample is PALM source code that has been used in a Palm application. The second example is a Windows based routine that has been compiled and run under Borland C++ Builder 4.0. These examples are meant to illustrate the interface protocol and are not meant to be examples of exemplary programming.

At the end of this document is a description of the physical connections that describes how to physically connect the PM2+ to a PC. A serial cable should have been included with your purchase of a PM2+, but additional cables can be ordered from Concept2.

Concept2 Interface Specification Support

Support will be provided solely through an online forum/web page, FAQ or through email. Concept2 does not provide support for the PM2+ interface specification.

Command/Data Sequences

The notation "0x" followed by two numbers or letters (A–F) indicates a hexadecimal byte value.

Send Receive Distance
0xB0   To receive distance data from the PM2+, send these bytes.
0x00    
  Status Byte
DistanceLSB
Distance1
Distance2
Distance MSB
See Status Byte Info
Floating point representation of distance in meters.
Send Receive Pace
0xB1
0x00
  To receive pace data from the PM2+, send these bytes.
  Status Rate
PaceLSB
Pace1
Pace2
PaceMSB
Integer representation of stroke rate in Strokes/min.
Floating point representation in seconds/meter.

 
Send Receive Time
0xB3
0x00
  To receive elapsed time data from the PM2+, send these bytes.
  Status Byte
TimeLSB
Time1
Time2
TimeMSB

Floating point representation of elapsed time in seconds.

 
Send Receive Heart Period
0xB2
0x00
  To receive heart period data from the PM2+, send these bytes.
  HrLSB
HrMSB
Integer representation of heart period. Heart rate = 576,000/heart period.
Status Byte Mask First Byte received in a distance query
END_OF_WORKOUT
END_OF_STROKE
WORK_DISTANCE
WORK_TIME
LOW_BATTERY
0X01
0X02
0X04
0X08
0X40
If set, end of workout has been reached
If set, end of stroke has been reached
If set, erg is set for a distance workout
If set, erg is set for a time workout
If set, get a new battery

The only bits that need to be monitored are END_OF_STROKE, END_OF_WORKOUT and WORK_DISTANCE. The other bits are used to run a race, which is not covered in a published specification.

Updates to erg PACE occur at the end of each stroke, so monitor the END-OF_STROKE status bit to know when to read this value. You can read pace continuously, but it only changes once per stroke. The END_OF_STROKE status bit is cleared when the pace value is read. It is reset on the next end of stroke event.

If the erg has been set for a distance workout (WORK_DISTANCE is set), you will need to monitor the END_OF_WORKOUT bit. When this bit is set, the value in the distance field (normally distance during the workout) will now report the actual time to complete the specified distance in seconds. This situation only occurs at the end of a distance workout. See example of serial communication.

Sample PM2+ Communication

Get distance, pace and heart rate data from PM2+

Send Receive Pace
0xb0
0x00
  Query Distance
Erg number (always zero for a single erg)
  0xc4
0xcb
0x00
0x2c
0x42
erg status: (distance workout)
float distance
float distance
float distance
float distance (43.0 meters complete)
0xb1
0x00
  Query Stroke Pace
Erg number
  0x2d
0x9a
0x41
0x51
0x3e
erg stroke rate
float pace
float pace
float pace
float pace (0.2)
0xb2
0x00
  Query Heart Rate
Erg number
  0x00
0x00
int heart period
int heart period (0)
0xb0
0x00
  Query distance
Erg number (always zero for a single erg)
  0xc5
0x40
0xa1
0xc9
0x41
erg status: (distance workout) (end of workout)
float distance
float distance
float distance
float distance (25.2*)
*Note: This value is seconds to complete the workout distance because this is at the end of a distance workout.

Physical Connections

When viewed from the back of the PM2+, the following table describes the pins for the top communication jack, J2, where pin 1 is the right most pin. The table also assumes the use of the Concept2 provided cable and computer serial port connectors (either 9 pin or 25 pin).

PM2+ RJ-11 Pin PM2+ Signal Description DTE Signal Description RS232 9 Pin
(DTE device)
RS232 25 Pin
(DTE device)
1 +12V (see note)   n/c n/c
2 Signal Ground Common Signal Ground Common 5 n/c
3 Received Data Transmitted Data (TD) 3 2
4 Transmitted Data Received Data (RD) 2 3
5 Signal Ground Common Signal Ground Common n/c 7
6 12V Return (see note)   n/c n/c
Note: When powered by an external 9 volt power supply, the RJ-11 pins 1 and 6 are used to supply 12V to power downstream PM2+'s that are daisy chained together. Since this power supply is not normally used, a standard 4 pin RJ-11 phone line can be used instead of the 6 pin cable supplied with the PM2+.

Equations

Power (watts) = 2.80 / Pace (sec/meter)³

The calories are calculated from the power (in watts) assuming a 25% efficiency in conversion of human energy to flywheel energy and a 300 calories/per hour cost to move the body up and down the slide (this is based on a 175 lb person):

Kcals/hr = Power (watts) x (4.0 x 0.8604 Kcals/watt) + 300 Kcals/hr

 

 

Ancient code samples:

 

Code Samples

 
 

Code samples are provided for the following:

  • PALM OS 3.5 Code (Uses OS 3.5 Libraries; Metrokwerks Codewarrior)
  • Using the win32api calls. This routine compiled and run under Borland C++Builder 4.0.

PALM OS 3.5 Code (Uses OS 3.5 Libraries; Metrokwerks Codewarrior)

void GetData(char command)
{
UInt32 baud=9600; //baud rate
static char msgdata[10], //data to send to PM2+
readbuffer[32]; // receive data buffer
static UInt16 *refNum; //port ID of serial port
Err checkst, //holds the result of whether serial port opened correctly
error;
unsigned short rcvdata; //no. bytes retrieved

msgdata[0]= command; //send query command—could be 0xb0, 0xb1, 0xb2
msgdata[1]= 0x00; //send address of indoor rower, 00 for single connection
checkst= SrmOpen (0x8000,baud, refNum); //open the serial port
// (0x8000 is port address of com1)
if (checkst==0) //make sure port opened
{
SrmReceiveFlush( *refNum, 1); //flush any garbage
SrmSend ( *refNum, &msgdata, 2,&error); //send command bytes
if( SrmReceiveWait( *refNum, 5, 50) == 0) //wait for 5 byte response
{
rcvdata = SrmReceive (*refNum, &readbuffer[0], 5,0,&error); //put data into buffer
}
else
{
HandleTimeout(); //if timeout occurs probably want to take PALM offline
}
SrmClose(*refNum); // close port after use

ProcessData(&readbuffer[0]); //look at data
}
else
{
ErrFatalDisplayIf( 1, "Serial Port can't be opened"); //can't open port
}
return ;
}
void ProcessData(char *readbuffer)
{
char status;
char floatbytearray[4];
float *floatvalue;

status = readbuffer[0];
floatbytearray[0] = readbuffer[4]; //convert from Intel to Motorola byte ordering
floatbytearray[1] = readbuffer[3]; //because PALM uses a Motorola based processor
floatbytearray[2] = readbuffer[2]; //Windows machines don't have to reverse the bytes
floatbytearray[3] = readbuffer[1];

floatvalue = (float*) floatbytearray; //convert 4 byte array into a floating point number
CheckStatus(status);
Display(*floatvalue);
}

Using the win31api Calls

This routine compiled and run under Borland C++Builder 4.0.
void getdistance(void)
{
HANDLE hComm = NULL;
COMMTIMEOUTS ctmoNew = {0}, ctmoOld;
char tempfloatarray[4];
char InBuff[100];
unsigned long int dwBytesRead;
char status;
float *ergdistance;
DCB dcbCommPort;
// OPEN THE COMM PORT.
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING, 0, 0);
if(hComm == INVALID_HANDLE_VALUE)
AppQuit(); //quit on port failure—insert your own routine
// SET THE COMM TIMEOUTS.
GetCommTimeouts(hComm,&ctmoOld);
ctmoNew.ReadTotalTimeoutConstant = 100;
ctmoNew.ReadTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &ctmoNew);
// SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
// THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST.
// IF YOU WANT TO LATER ADD CODE FOR OTHER BAUD RATES, REMEMBER
// THAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING.
// ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING.
dcbCommPort.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcbCommPort);
BuildCommDCB("9600,N,8,1", &dcbCommPort);
SetCommState(hComm, &dcbCommPort);
TransmitCommChar(hComm, 0xb0); //transmit distance query
TransmitCommChar(hComm, 0x00); // erg address—always zero
ReadFile(hComm, InBuff, 5, &dwBytesRead, NULL);
//read the serial port
if(dwBytesRead)
{
status = InBuff[0];
tempfloatarray[0] = InBuff[1];
tempfloatarray[1] = InBuff[2];
tempfloatarray[2] = InBuff[3];
tempfloatarray[3] = InBuff[4];
ergdistance = (float*)&tempfloatarray;
}
if(hComm)
{
SetCommTimeouts(hComm, &ctmoOld); //restore old settings
CloseHandle(hComm);
}
}

 

 

FAQ:

  1. What can I do with the PM2+ Interface Specification?

    Using an RS-232 interface, the protocol specification outlines the command and data exchanges needed to extract distance, time and pace information from the Concept 2 PM2+ monitor. This information is sufficient to reproduce the PM2+ Monitor display. From there it's just a matter of using your creativity.

  2. How do I program the PM2+ Monitor from an RS-232 enabled device?

    The commands released in this specification only allow devices to query and receive the data required to replicate the PM2+ Monitor display.

  3. What programming language should I use and what platforms are supported?

    Any programming language that will allow you to use RS-232 communication should suffice. The normal platform would be a PC to PM2+ monitor. Peripheral devices such as PALMs are also supported, but a special cable adapter will probably be needed in this case. More specifically a NULL MODEM and a female-female gender changer will be required.

  4. Can I get sample programming code?

    Yes. See the interface specification document. This code is known to work.

  5. How do I get support?

    This FAQ is the primary support channel. Additional questions may be emailed to info@concept2.com.

  6. Can I sell my program?

    Yes, but please direct your customers to call you for all support issues related to your product.

  7. I send a command sequence, but nothing comes back.

    Check your cable and plugs. Check your (PC) serial port settings. Serial port should be set for 9600 BAUD, 8 bits, no parity, hardware flow control off.

  8. I am able to receive the data, what do I do with it?

    See the interface specification. You will have to write a function/ procedure to interpret the data packets.

  9. USB (Universal Serial Bus)? Firewire?

    No, we do not support USB or Firewire. Only RS-232 communication is supported.

  10. I'm using Hyperterminal and I type a "0 x B 0 0 x 0 0" and nothing comes back.

    In order to receive a response, you need to send a byte with a hexadecimal value of 0xB0, followed by a byte with the value of 0x00 (zero).