Graphic showing peak-to-peak heart beat

Hacking my own firmware

Over the years several people have asked if the HRMI could return the interval between HR pulses. Since Sparkfun sells the HRMI with the original firmware loaded, you have to download the new firmware from here and load it yourself using a PIC ICSP programmer (if this is problem, email me and we can work something out).

This custom firmware removes the averaging algorithm and only returns the period (in milliseconds) between pulses from the Polar RMCM01 OEM receiver. It also includes the analog and utility port functions (the analog ports now return all 10-bits).


New firmware. version 1.0
  1. Source Code (PIC Assembly)
  2. Listing File
  3. HEX file for programming
Original firmware. version 1.1
  1. Source Code (PIC Assembly)
  2. Listing File
  3. HEX file for programming


The new firmware operates in a similar manner as before with the following exceptions.
  1. Averaging mode (and selection between Averaging and Raw modes) has been removed
  2. Some commands and responses have been modified slightly
  3. Response data is now comprised of 16-bit fields (this affects the I2C interface)
  4. The history buffer is now 16 entries long

A typical output from a command like "G8" looks like

0 38 844 844 845 844 843 850 852 855

indicating the time between heart beats has been in the range of 844 - 855 milliseconds (70 - 71 bpm). Compute bpm = 60000 / [value in milliseconds].


Please see the manual for the original firmware for a more detailed description of communicating with the firmware. This is just a summary. All serial commands are terminated by the linefeed return character (0x0D).
Get Analog Value

Serial: A [CH]
I2C: 0x41 [CH]
Reads the specified analog input channel (0 - 3). Generates a response with a value 0-1023:

Serial: [Value]

I2C Read of 2 bytes: [ADC 9:8] [ADC 7:0]
Set Utility Port Dir

Serial: D [N]
I2C: 0x44 [N]
Sets the utility port I/O directions. [N] bits 4:0 specify the direction mask. A bit value of 0 sets the associated port pin to an output. A bit value of 1 sets the associated port pin to an input. [N] has a value of 0 - 31.
Get HR Data

Serial: G [N]
I2C: 0x47 [N]
Returns heart rate period data from the history buffer. [N] specifies the number of values to return 0-16. Generates a multi-field response:

Serial: [Status] [Count] [HR1P] [HR2P] ... [HR16P]

I2C Read of 2N+4 bytes: [0x00] [Status] [0x00] [Count] [HR1P 15:8] [HR1P 7:0] ... [HR16P 15:8] [HR16P 7:0]

  • Status : Bit 1 set indicates no valid data received, clear indicates valid data.
  • Count : Count value of last HR value pushed into history buffer (lets you identify new data).
  • HR1P is the period (in milliseconds) of between the two most recent heart beat pulses.
Get Utility Port

Serial: I
I2C: 0x49
Reads the utility port pins. Generates a response with a value 0-31:

Serial: [Value]
I2C Read of 2 bytes: [0x00] [Value 4:0]
Get Mode

Serial: M [CH]
I2C: 0x4D [CH]
Reads the current utility port I/O direction. Generates a response with a value 0-31:

Serial: [Value]
I2C Read of 2 bytes: [0x00] [Dir 4:0]
Set Utility Port

Serial: O [Value]
I2C: 0x4F [Value]
Sets the value of all utility port pins configured as outputs. Value ranges from 0-31.
Set Mode

Serial: S [Mode]
I2C: 0x53 [Mode]
Sets the power-on configuration. Setting bit 2 of Mode causes the firmware to store the current utility port directions and output values to eeprom for use at power-on. All other bits are ignored.
Get Version

Serial: V
I2C: 0x56
Gets the firmware type and version.

Serial: [Type] [Version]
I2C Read of 4 bytes: [0x00] [Type] [0x00] [Version]

Type = 2
Version starts with the value 1


  1. This firmware measures the pulses that come from the Polar OEM receiver. I cannot say specifically what part of the actual ECG data that Polar is detecting. You must be aware of this when deciding how much to trust the data.
  2. The PIC is running with an internal clock that has an accuracy of +/- 2% over 0-85°C.
  3. I have not tested the I2C interface but expect it to work (obviously let me know...)