comments 23

Hacking a Blood Pressure Monitor

I’ve been meaning to hack my blood pressure monitor for a while, and I finally got around to doing it! So, the idea is to mod a regular electronic blood pressure monitor to make it wireless and connected to the Internet, much like iHealth BP5 or Withings’. That makes detecting trends in your blood pressure much easier, since you can chart the data and even correlate it with other health data, such as how much sleep you’ve been getting, your weight or your level of activity. The model I have is the EW3106 from Panasonic. It’s quite old but from what I’ve seen the design hasn’t changed much throughout the years.

panasonic-upper-arm-blood-pressure-monitor_5352544

The other part of the solution is the ESP8266. It’s an awesome little WiFi module. It has a TCP stack and only uses about 20% of it’s CPU resources, which means you can run your own software on it, with no need for an external MCU. Some cool guys have added support to the Arduino environment, which makes it really easy to use. And when you consider it costs little more than $4 it’s really a no-brainer.

The ESP8266

Since the unit has a feature to store measurements (the blue M/R button), I figured it would probably have a memory chip connected to an I²C bus.  My idea was to, whenever the user decided to save a new measurement, retrieve the data stored by the MCU, make sense of it and push it to the cloud.

Disclaimer

warning_sign_boldShould you choose to attempt this project on your own, keep in mind you’re modifying a medical device and that CAN interfere with its accuracy and reliability. Remember that a WiFi device emits RF which can affect other devices. If you choose to modify it, don’t use it as a medical device anymore. Use this information and code at your own risk. I cannot be held liable if, knock on wood, your house burns down or your dog dies!

 The insides of the the EW3106

This type of blood pressure monitor is known as an oscillatory blood pressure device. The way it works is it inflates the cuff so the pressure around your brachial artery is high enough that it collapses, completely blocking the flow of blood. Then, it starts slowly releasing the pressure until the unit can hear the blood “wooshing” through the compressed artery. That’s your systolic pressure. It then keeps on releasing the pressure until it cannot hear it anymore. That’s your diastolic pressure.

The unit was quite a hassle to open. I hate these plastic hooks, it’s hard to open without breaking them or damaging the plastic, even though they make a lot of sense from a manufacturing point of view. Some elbow grease and a bit of patience and it came off. This is how the monitor looks inside. There’s a PCB with the LCD on top, two switches, an air pump (the metal part in the left upper corner) and a valve (yellow thing, lower right corner). When you press the button the valve closes and the pump inflates the cuff, while the MCU samples a pressure transducer connected to the cuff. The MCU can be seen on the top side of the board, along with two smd potentiometers, which are probably used to calibrate the unit.

IMG_20150817_181140728
IMG_20150817_181246285

On the bottom side of the board you can see the pressure transducer with tubing attached. And there it is at the top! An I²C EEPROM. You can’t really see it in the picture, but it has the marking L02W104 on it. I looked for a part that would make sense with that marking, and came up with the BR24L02W from Rohm. From what I gather L is the operating temperature range (-40C to 85C), while 02 means a 2 Kbit chip, or 256 bytes. 104 probably refers to the lot. Anyways, with that figured out I went on to tapping the I²C bus.

IMG_20150817_181436298(1)

 

Sniffing the I²C Bus

Using the datasheet as a reference I hooked up some thin wires to the bus. That’s SDA (data) and SCL (clock). In case you need a primer on how an I²C bus works, check this Wikipedia article. One thing to keep in mind is that the chip works with 3.3V logic, so plan accordingly and make sure you don’t fry it.

IMG_20150817_185316250

The next step is hooking up a logic analyzer to that bus, so we can listen to what’s going between the MCU and the memory chip. A logic analyzer is a great tool to have on your bench. It allows you to sample digital signals and helps you make sense of it. Again, Wikipedia is your friend. I use it a lot more than my oscilloscope, and it’s also much cheaper. This is the one I have:

IMG_20150817_205706607

It’s the Scanalogic-2 by Ikalogic, and that one is a kit version that you buy and assemble at home. It’s quite cheap at 33 Euros. You can also buy it assembled for 49 Euros. It’s USB and you can download an application from the manufacturer for free, it’s called ScanaStudio and it has lots of useful things like protocol decoders. Anyways, this is how things look once it’s hooked to the I²C bus. The third wire you see is ground.

IMG_20150817_204925039

The next step was sniffing the communication between the MCU and the memory chip. In order to do that I set the trigger, started the logic analyzer and asked the monitor to save a new measurement. This is what it looks like. The green signal is the clock line while the red one is the data line. In this chart you can see the MCU writing data to the memory chip.

I2C Signal

Making sense of the data

write_only

 

 

That is what’s going on in the chart above. I know it’s obvious, but anyway, the bytes are in hex format. Here you can see the start condition, the MCU addressing the memory chip for writing (50) and sending 5 bytes. The first byte (1C) is the address in the memory chip that the MCU wants the data written to. The next 4 bytes are the one we are are most interested in.  The second byte (62) is the pulse, which is 98 beats per minute in decimal. The third byte (53) is your diastolic pressure: 83 mmHg. The fourth and fifth bytes together form your diastolic pressure. An unsigned byte gives your a range of 256, but the unit can read a systolic pressure of up to 280 mmHg, making it necessary to use two bytes for that. Instead of using a big endian or little endian pattern, the scheme used was to store half of the systolic pressure in the fifth byte and use the fourth byte as flag that indicates if the number is odd instead of even. 80 means the flag is set, 0 means it isn’t. So in the case below, we have 44h which translates to 68 decimal. Multiply that by two and we get 136. Since the flag is set, we add 1, making it 137 mmHg. A little high, I know! But I was running around when I took the measurement :o) I guess this convoluted way of using the two bytes was chosen because it’s an 8 bit MCU and it didn’t need the full range of the 16 bits. I deduced that protocol by comparing the values to the measurements seen in the display.

On to the next step, I needed a way to get that data into the ESP8266. My first idea was to “eavesdrop” the bus while the MCU was talking. While that is certainly possible, it turned out to be a little more complicated. Sniffing messages not addressed to you is not regular feature of the hardware serial interfaces implemented in MCUs. It might be possible with a certain combination of configuration registers, but honestly, I didn’t look into it. I just wanted to use Arduino’s wire library, if possible. Another brute-force way would be to bitbang the protocol, but that’s not very efficient or clean. So I went a different route: I decided I would watch the bus for activity, wait a while, and try to read the new values straight off the memory chip, in a master-slave configuration. The I²C bus supports multi-master (both the MCU and the ESP8266 acting as masters). The trouble now would be to know where in the memory the new value was stored. For that I needed more data.

writeSteps

Paying closer attention to what the MCU was doing before writing the data, I noticed it would always read from FC before doing it (steps 1 & 2). That address turned out to contain the count of entries written to the memory. In the sample seen here there were 7 entries. So, to store new data, the MCU simply multiplied that by 4 bytes (the size of the entry), which gave it the offset for the new entry: 1C, which it uses in step 5. You might wonder what steps 3 & 4 are for, and honestly, I don’t know. It might be the software revision, as the MCU always writes the same data (AA FF) to the same address (7C), whenever it wants to store a new entry. For our purposes that is inconsequential. Having seen that, I decided to do a full memory dump to see what else it could tell me:

dump

That is the full 256 bytes of the EEPROM. It’s not from the same moment as the steps above, so the data won’t match, but that’s not important. Bytes FC and FD are 00 and 02, respectively, which means the count was 2 at that moment. You can see that pattern is actually repeated 4 times in the last 8 bytes, which I imagine is for redundancy purposes, since the count is rewritten every time a new entry is stored. Flash memory can wear out wear in as low as 3000 cycles, so that’s a good idea.

Anyway, that solves our problem of knowing where to read the newest data. Read FC (or any of the redundancy addresses) and multiply it by 4.

Hooking things up

This is the very simple schematic of the circuit:

schematics

I used an LDO regulator (78R33) capable of 1A. The ESP8266 draws up to about 300mA when transmitting, so plan accordingly. The nice thing about this regulator is that it has an enable pin. That turned out to be very handy because by hooking it to a 3.3V line in the main PCB we get a remote control for the ESP8266: it automatically turns on and off with the blood pressure monitor. The led is for giving some feedback to the user: it lights up once a connection is established with the WiFi network, and blinks once data is pushed to the cloud (see code below). The capacitor is a simple power supply decouple.

enable_pin
This is the pad the 78R33 enable pin is connected to (+).

Ok, Where Does That Data Go?

There are a million ways to store your data in the cloud, such as a flat file in a shared server, a MySQL database in a VPS, or any of the several IoT data services available. After a quick search I decided to use data.sparkfun.com, which is an anonymous, public and free service kindly provided by SparkFun. It’s based on Phant, an open source IoT logging tool created by SparkFun, so you can host it yourself if you wish. Pushing data is as simple as appending it to an URL. It might be worth mentioning I’m not using https and as such your data is subject to eavesdropping. Doing SSL/TLS on a microcontroller is hard work, since they’re usually so constrained on memory and processing power. If you want your data to be private, get creative… maybe do some kind of client side encryption/obfuscation or a local proxy server/router.

Anyways, using data.sparkfun.com is as simple as creating a stream and pushing data like this:

http://data.sparkfun.com/input/PUBLIC_KEY?private_key=PRIVATE_KEY&FIELD1=VALUE1&=FIELD2=VALUE2

That’s all there is to it, really. Check out the docs. You can then fetch your data using CSV, JSON or JSONP and do whatever you want with it. You can also download in SQL format later on if you wish. Later on we’re gonna plot this data using Google Charts.

Coding

Alright. Now we get to coding. Have in mind this is not production-ready code, in case you’re thinking about buying a huge lot of monitors, modding them and selling on eBay (hey, if you do, cut me in 🙂 I’m kidding, this is OSS/OSH). For instance, you need to reprogram the ESP8266 if you need to change the WiFi SSID or password. There are clever ways to do that without reflashing it, but I’m avoiding scope creep . Well, check out below the activity diagram for what is in the code. The code is available on GitHub.

ActivityDiagram

 

Show Me The Money!

Ok! Here’s video proof of the thing after it’s all done. The led lights up once it connects to the network, and blinks after pushing the data to the cloud.

 

The data

This is what the data could look like if you plot it using Google Charts, for example.

Wrapping Things Up

Well, this is what I had to share with you! I hope you enjoyed. It feels like writing this post actually took me longer than building and coding everything 🙂 Remember the disclaimer, be responsible and don’t use this as a medical device. Your comments are welcome!

Regards,

Eduardo

23 Comments

  1. Pingback: Push Blood Pressure Data To The Cloud Via ESP8266 | Hackaday

  2. Pingback: Tech News / Push Blood Pressure Data To The Cloud Via ESP8266

  3. Rafal

    Hi,

    Nice write up. I have a question related to online charts. I went thru the documentation posted on sparkfun site.
    especially interesting for me is:
    http://phant.io/graphing/google/2014/07/07/graphing-data/
    i would like to put a chart made from my stream on my google pages site. And here I am lost – which part of code shoud be used on my gogle pages site to insert there the chart – like your chart of blood pressure on your site…

    • steinhorst

      Thanks Rafal!

      The link you mentioned has a nice tutorial on doing that. The section “Putting it All Together” has an example html page you can use, just make sure to replace the value of the javascript variable “public_key” with your own public key from Sparkfun Data and to change the column names and types to reflect your data. In case you’re not talking about that using Google Charts with data from Sparkfun Data, you could change the ajax call for another json/jsonp service, or even input the data manually by adding rows with your data. Hope that helps. Regards!

      • Rafal

        Eduardo,
        I understand uC, but web designing/programming is too much…
        when I try to cupy/paste sparkfun example to my google pages page , i have message about not allowed code in page.
        but if someone will do example, I could rework it…
        the goal achievable – example of chart on google pages is here:
        https://sites.google.com/site/sircharlesruns/home

        the question is how to do it, even with sparkfun example data…
        I suppose you don’t use googlepages , so most probably don’t know the answer, but anyway, maybe someone will answer…

  4. Pingback: Hacking a Blood Pressure Monitor - Electronics-Lab

  5. Pingback: Push Blood Pressure Data To The Cloud Via ESP8266 | Ad Pub

  6. Pingback: Hacking a Blood Pressure Monitor | Electronics Infoline

  7. Tobi

    Hi Edu,

    First of all thank you very much for this idea and project. I am currently trying to also upgrade my Panasonic monitor with the ESP8266-12 module.
    I’m just having a few issues with the I2C connection using GPIO 0 and 2 pin on my ESP-12 module.

    If I use GPIO 4 and 5 for i2c, everything is totally fine and works perfectly, but I saw you are using GPIO 0 and 2 in your implementation and I also tried this (because if this would work, I could use a cheaper ESP-01). But when I connect the ESP12 to the EEPROM IC by using GPIO 0 and 2 the M/R button on the monitor is no longer working properly. Well, sometimes it’s working but most of the times this will cause a reset and loss in all data stored on the EEPROM IC. I’m just wondering if you can still properly use your M/R button on the monitor or do you have the same issues?

    To reproduce the issue it’s enough to have at least one stored value and press the M/R button when the device is off. Then check if the value is displayed and turn the device off using the power button. Then repeat the procedure by pressing M/R again and so on… After repeating this procedure a few times, pressing M/R will no longer display anything and the memory is cleared.

    If you have the same issue I’m fine, but if you do not have this error I need to find out why 🙂

    Thanks,
    Tobi

    • steinhorst

      Hi Tobi, thanks for your comment, I’m glad this project has been of use to you!

      I’ve just tried reproducing the error you’ve been getting but it doesn’t happen for me. M/R works as expected. I can’t see why using GPIO 0/2 vs 4/5 would cause a different behavior, unless they have a different pull-up/down configuration internally. One thing that comes to mind is that maybe the ESP8266 is trying to use the bus at the same time as the monitor’s MCU. That happened to me as I was developing the code and it caused crashes and random behavior much like you described. What I do in the code to avoid a collision is attach an interrupt to the SDA line and wait for activity. Once it happens, I delay for 500ms just to be sure the monitor’s MCU is done doing it’s business and only then do I take the bus and address the EEPROM chip. While waiting for the interrupt, SDA is set as input and as such is in high impedance mode. If you set it as output while the MCU is trying to talk it might not be able to drive the line down properly, which would cause problems.

      Cheers!

      • Tobi

        Hi Edu,

        Thanks for your reply. Since I’m using your source code I also rely on the interrupt on the SDA line and have a delay of 500ms. I just checked that.
        Could you please let me know what “enable pin/trigger” you exactly used to turn on your voltage regulator (where do you attach on the mainboard)? Is your ESP also powered on by pressing the M/R button, or only if you start a measurement? Maybe I used a bad “enable pin” for my voltage regulator?

        Thanks Tobi

        • steinhorst

          Hey Tobi, I updated the post with a photo to you show what the enable pin is connected to. Indeed to ESP is powered on by pressing the M/R button as well. If you Panasonic BPM model is not exactly the same as mine it might behave a bit differently… other than that, if you’re using my code and the same ESP module it should just work, I guess :). Did you change anything in the code? Delays, etc? If you did it might be worth it trying to run with the original code and see if the problem persists.

          Hope it works out for you! This projected turned out to be very useful for me.

          • Tobi

            Hi Edu,

            First of all I wish you a great new year ahead.
            I just would like to update my post here to let you know that I found out what caused the issue in my setup. Since I was using GPIO 0 and 2 on my ESP-01 module this caused a problem on the I2C bus. During boot/power up of the ESP8266 pins 0 and 2 are in some kind of floating state. So they are switching between LOW and HIGH for about 500ms until they are stable and really usable. It seems like this floating state caused some interferences on the I2C bus which resulted in a EEPROM reset some times. Now I have implemented a little bit more logic to only turn on the ESP-01 module after a few seconds have passed after I turned on the blood pressure monitor.

            This solved my issue instantly. For me it’s still a mystery why this issue does not occur in your setup – maybe because you are using the ESP-12 module, idk. But nevertheless I could find a solution and thanks again for your project idea and your support!

            Tobi

          • steinhorst

            Hi Tobi,

            you’re welcome! Great new year to you too!

            I’m glad you solved the issue, and thanks for link and the heads up. I might not have faced the same problem due to the different module, a different bootloader version, or something else. One problem I’ve been having now is that the batteries are draining too fast while in standby. I measured a 3mA current while in standby, which is not acceptable for a battery powered device. I guess it’s because of the voltage regulator/enable pin scheme. I’ll update the post once I get around that issue.

            Edu

  8. Cat

    Thank you for this excellent tutorial! The explanations and photos are so helpful. I’ve never done anything like this before, but you have inspired me to look into it more. Do you have any recommendations on online courses/resources to get up to speed on the hardware side? I have a lot of software background. Thanks again.

    • steinhorst

      Hi Cat!

      Thanks for the feedback! There’s really a world of stuff you can study on the hardware side of things, depending on what you’re interested in. Since you have a software background I’m guessing you’d be interested in microcontrollers. The Arduino really is a terrific platform for learning, I’d recommend you get some experimentation kit, like this one from Adafruit, follow some tutorials and build some projects. There’s A LOT of resources on Arduino related projects. Hackaday is an awesome general hardware hacking blog. For some more in-depth electrical engineering stuff there’s a great YouTube channel called EEVblog, by an Australian guy called Dave. Best regards!

  9. Tobi

    Hi Edu,
    Regarding the 3mA while in standby. I’m using a different voltage regulator in my circuit without enable pin (since I did not have the one you mentioned in your post). I was using the well known AMS1117 3.3V regulator and I designed a very simple “turn on circuit” using two transistors (NPN and PNP) connected together. I haven’t measured the power consumption in standby to be honest but in theory there should not be any current flowing if the transistors are not turned on. This is just an idea for you, but you might find a better possibility. Nevertheless here is a schematics view of my “power on circuit”: http://i.imgur.com/9VOgDrA.png – If you need fore information feel free to let me know (also by email ranger81 a-t dsuclan d-o-t de).

    In a few weeks I’m also going to produce a small video about my blood pressure hack and post it to YouTube. I’ll let you know once this is done.

    Thank you,
    Tobi

    • steinhorst

      Hey Tobi,

      thanks for the circuit! I´m using it too. I gave up on the enable pin for the KIA78R33. I´m guessing the 3mA are really just it´s standby current (when disabled) really, even though it´s not listed in the datasheet. Either that or I have a defective unit :). Anyway, the transistor switch is working wonders now, standby consumption is around 1.5uA. Batteries should last a long time now. Thanks!

      Edu

  10. Pingback: Building a Smartphone Controlled Wake-up Light – Edu Steinhorst

  11. Kim

    Hi my blood pressure monitor comes with a RX, TX GND pin and i connected it on a FTDI232rl and it does not work. im trying to connect SDA and SCL pin of 24c01wp on my FTDI232rl (rx,tx) can u help me how.

    • steinhorst

      Hi Kim, SDA and SCL are for the I2C protocol, not UART. FTDI232rl is an UART to USB translator. In order for you to read the contents of that flash chip you need an I2C capable microcontroller such as an Arduino.

Leave a Reply

Your email address will not be published. Required fields are marked *