December, 2011

Comparison between ZigBee and Bluetooth Low Energy

Both ZigBee and Bluetooth Low Energy are designed for ultra-low power wireless communicating devices. Below are some of their major differences:

  ZigBee Bluetooth Low Energy
Range 10-100m 50m
Networking topology
  • Local Area Network (LAN)
  • wireless mesh network
  • Up to 64k devices
  • Personal Area Network (PAN) or Body Area Network (BAN)
  • wireless star network
  • pair with up to 7 slaves
  • Direct Sequence Spread Spectrum (DSSS)
  • Continue trying to send packets until successful packets delivery.
  • Frequency Hopping Spread Spectrum (FHSS)
  • Adaptive frequency hopping to find clear channel to help save battery life.
Bit rate ~100kbps ~200kbps
Setup time 20ms 3ms
  • 868MHz in Europe
  • 900-928MHz in US and Australia
  • 2.4GHz worldwide
  • 2.4GHz
Hardware support In some consumer electronics and remote controls Most of the handheld devices support Bluetooth. BLE dual-mode is going to be included in all new devices.
Power consumption* 185.9uW/bit 0.153uW/bit

*      Reference:

Read More

Radiation concern

One of the concern about the monbaby device is radiation safeness, especially it is going to be used on the little babies who are more sensitive to environmental stimulus.

Radiation of radio frequency (RF) devices are measured by Special absorption rate (SAR). It  is a measure of the rate at which energy is absorbed by the body when exposed to a radio frequency electromagnetic field. It is defined as the power absorbed per mass of tissue and has units of watts per kilogram (W/kg). A general rule of thumb is, higher emission power would increase the SAR measurement.

Here are some sample facts and measurement of SAR for different RF devices:

  • Cellphones in US are limited to 1.6W/kg by regulation
  • Apple iPhone 4 : 1.17W/kg
  • Baby monitors  range between 0.01-0.08W/kg
  • Bluetooth devices about 0.001W/kg
  • There is no public measurement data found for BLE yet, but given BLE has even lower power emission than Bluetooth, the SAR number should be very insignificant to be compared.

Bluetooth technology has such an insignificant radiation that in fact, this is one of the reason why a lot of bluetooth earpieces came out in the market after cellphones become our daily routine, to reduce the radiation we are exposing to when making calls.

Bluetooth and Bluetooth low energy technology are both using 2.4-2.5GHz band, which is the same as the common FM radio.


Read More

The BLE Prototyping Hardware: TI CC2540 – DEV KIT

Texas Instrument manufactures an integrated BLE chip called CC2540. This chip contains not only the bluetooth LE radio, but also programmable 8051 core. They provide complete development tools, and they come in two forms:

  1. CC2540DK
  2. CC2540DK-MINI

The larger of the devkit CC2540DK contains general-purpose development / evaluation board called SmartRF05EB. These boards are also used for their line of wireless modules created by ChipCon (subsidiary of TI). As such, it’s compatible with other wireless evaluation modules CCxxxx.

The CC2540DK kit comes with two CC2540EM evaluation modules  and two SmartRF05EB  boards. The SmartRF05EB contains lots of peripherals such as LCD, Joystick, LEDs, Potentiometer, switches, etc.. In addition, it has necessary components to flash and debug the target chip. The target chip is any compatible CC device as previously mentioned, which is surface mounted onto the evaluation module PCBs.

A noteworthy aspects about this kit

  • Only BLE hardware implementation that has coupled host microcontroller in a single chip (SoC: System On Chip)
  • Significant sofware stack for interfacing with the hardware
  • Development project workspaces available for testing on IAR Workbench
  • Bluetooth v4.0 compliant profile implementations and examples

In order to test out different examples provided with TI’s ble stack download, several other tools need to be setup:

As for this writing, this is the only dev kit that provides both the hardware and the necessary software stack to test out BLE functionality in a single package. The only downside is that the software stack is written only for IAR Workbench, which requires license to create compiled hex beyond 4Kb (free version limit). We would love to see an opensource version of the software stack written for compilers such as SDCC.

The Chip

There are 2 variants of CC2540 : CC2540F128, CC2540F256. The only different between the two is the flash space as the name indicates. (128kB vs 256kB). This chip has all major peripherals and hardware capability of modern microcontrollers, as you can see from the functional diagram below. Some highlights:

  • USB controller
  • 2 hardware UART
  • Hardware encryption engine
  • bunch of timers
  • ADC’s go upto 14bit resolution


Next, the CC2540′s pin labels in the current package:


The evaluation module that houses the actual CC2540 chip has all of the IO pins brought out to accessible debug headers. Most of the IO ports are routed to the first SMD socket (evaluation module socket), and is accessible from one of the debug headers located on P18 on SmartRF05EB.


Connectors for Peripherals

The pins that are brought out via evaluation module connectors are mapped to various peripherals on SmartRF05EB board. The mapping is as follows. On my rev 1.8 board, these pin outs correspond to board connectors P5 and P6, respectively. More details can be found on SmartRF05EB board’s user guide.


The probe connectors give access to these pins, but the mapping from the EM -> Probe pinouts are not straight forward. The probe pin mapping is as follows:


To access a specific pin on from CC2540, we need to do a little mapping of the ports specified from the tables shown above. For example, the IO pin P0.1 from CC2540 corresponds to EM_BUTTON1/EM_LED4_SOC at EM connector pin 5. The same pin corresponds to  the pin 7 on the prob connector. I wish the mapping of the pins from the debug headers to the actual chip was more straight forward. I had to trudge through 3 different technical documentations to find this.

I’ll be connecting the pulsesensor to pin P0.7, which corresponds to EM_POT_R (potentiometer) on pin 17 @ P5 on the EM connector and pin 17 @ P18 on the probe connector. In order to disable the onboard potentiometer, I needed to take the jumper off on connector P10 on SmartRF05EB, at position 33-34. The connector P10 is where you can sever or link each individual peripheral that connects to the evaluation board housing CC2540.

Read More

Heart Rate Measurements via Pulsesensor

The Sensor

pulsesensor Pulsesensor is an open-source heart rate monitoring sensor built to work with the Arduino. The underlying mechanism uses periodic sampling of ADC value from the light intensity sensor, and signal filtering to detect the peak-to-peak length in the data. The current Arduino code requires relatively high rate of sample polling, and thus prone to heavier power consumption compared to low-powered designs.

While the method used to detect the pulse is not new, the pulsesensor is the first open source product we’ve seen for heart rate sensors. As such, we felt the product was a good fit for our first prototype design for Monbaby. However, the platform we will be using isn’t Arduino. Hence, we will need to examine the algorithm used, and understand its pros and cons. There should be other signal filtering algorithms that are appropriate in finding out peak-to-peak length in the noisy raw data from the light intensity sensor. Once the signal processing algorithm is fully understood, we can then reimplement the logic within the CC2540 software stack.

The Algorithm

The latest release of pulsesensor code is posted in its entirety below. This code is meant to compile under Arduino IDE. Hence, it’s missing headers and normal format of typical AVR firmware C source. It uses the timer interrupt every 1ms to read the analog value from the sensor. It averages out the readings at every 300 run, and de-means the raw signal by subtracting it by the calculated mean.

This normalized (de-meaned) data is then refined further. A signal processing method called “Butterworth filter” is used to reduce the noise in the normalized raw data. I have yet to read more about the algorithm, but it seems akin to ARIMA time series model, where the predicted value (Y_hat) is a function of past values and the forecast error term (residual) between the real and prediction values. The way Butterworth filter is used, however, is through “Band-Pass” filtering process. It defines low-pass and high-pass bands that eliminate frequencies that are outside of those bounds. We will be reading more about these signal processing techniques in the coming days.

>> Pulse Sensor Digital Filter <<
This code is the library prototype for Pulse Sensor 
    >>> Pulse Sensor purple wire goes to Analog Pin 0 <<<
Pulse Sensor sample aquisition and processing happens in the background via Timer 1 interrupt. 1mS sample rate.
The following variables are automatically updated:
Pulse :     boolean that is true when a heartbeat is sensed then false in time with pin13 LED going out.
Signal :    int that holds the analog signal data straight from the sensor. updated every 1mS.
HRV  :      int that holds the time between the last two beats. 1mS resolution.
B  :        boolean that is made true whenever HRV is updated. User must reset.
BPM  :      int that holds the heart rate value. derived from averaging HRV every 10 pulses.
QS  :       boolean that is made true whenever BPM is updated. User must reset.
Scale  :    int that works abit like gain. use to change the amplitude of the digital filter output. useful range 12<>20 : high<>low default = 12
FSignal  :  int that holds the output of the digital filter/amplifier. updated every 1mS.

See the README for detailed information and known issues.
Joel Murphy  December 2011  Happy New Year! 

long Hxv[4]; // these arrays are used in the digital filter
long Hyv[4]; // H for highpass, L for lowpass
long Lxv[4];
long Lyv[4];

unsigned long readings; // used to help normalize the signal
unsigned long peakTime; // used to time the start of the heart pulse
unsigned long lastPeakTime = 0;// used to find the time between beats
volatile int Peak;     // used to locate the highest point in positive phase of heart beat waveform
int rate;              // used to help determine pulse rate
volatile int BPM;      // used to hold the pulse rate
int offset = 0;        // used to normalize the raw data
int sampleCounter;     // used to determine pulse timing
int beatCounter = 1;   // used to keep track of pulses
volatile int Signal;   // holds the incoming raw data
int NSignal;           // holds the normalized signal 
volatile int FSignal;  // holds result of the bandpass filter
volatile int HRV;      // holds the time between beats
volatile int Scale = 15;  // used to scale the result of the digital filter. range 12<>20 : high<>low amplification
volatile int Fade = 0;

boolean first = true; // reminds us to seed the filter on the first go
volatile boolean Pulse = false;  // becomes true when there is a heart pulse
volatile boolean B = false;     // becomes true when there is a heart pulse
volatile boolean QS = false;      // becomes true when pulse rate is determined. every 20 pulses

int pulsePin = 0;  // pulse sensor purple wire connected to analog pin 0

void setup(){
pinMode(13,OUTPUT);    // pin 13 will blink to your heartbeat!
Serial.begin(115200); // we agree to talk fast!
// this next bit will wind up in the library. it initializes Timer1 to throw an interrupt every 1mS.


void loop(){
  Serial.print("S");          // S tells processing that the following string is sensor data
  Serial.println(Signal);    //  filterdSignal holds the latest filtered Pulse Sensor signal
  if (B == true){             //  B is true when arduino finds the heart beat
    Serial.print("B");        // 'B' tells Processing the following string is HRV data (time between beats in mS)
    Serial.println(HRV);      //  HRV holds the time between this pulse and the last pulse in mS
    B = false;                // reseting the QS for next time
  if (QS == true){            //  QS is true when arduino derives the heart rate by averaging HRV over 20 beats
    Serial.print("Q");        //  'QS' tells Processing that the following string is heart rate data
    Serial.println(BPM);      //  BPM holds the heart rate in beats per minute
    QS = false;               //  reset the B for next time
  Fade -= 15;
  Fade = constrain(Fade,0,255);
delay(20);                    //  take a break


ISR(TIMER1_OVF_vect){ // triggered every time Timer 1 overflows
// Timer 1 makes sure that we take a reading every milisecond
Signal = analogRead(pulsePin);

// First normailize the waveform around 0
readings += Signal; // take a running total
sampleCounter++;     // we do this every milisecond. this timer is used as a clock
if ((sampleCounter %300) == 0){   // adjust as needed
  offset = readings / 300;        // average the running total
  readings = 0;                   // reset running total
NSignal = Signal - offset;        // normalizing here

if(first = true){
  for (int i=0; i<4; i++){
    Lxv[i] = Lyv[i] = NSignal <<10;  // seed the lowpass filter
    Hxv[i] = Hyv[i] = NSignal <<10;  // seed the highpass filter
first = false;      // only seed once please
    Lxv[0] = Lxv[1]; Lxv[1] = Lxv[2]; Lxv[2] = Lxv[3];
    Lxv[3] = NSignal<<10;    // insert the normalized data into the lowpass filter
    Lyv[0] = Lyv[1]; Lyv[1] = Lyv[2]; Lyv[2] = Lyv[3];
    Lyv[3] = (Lxv[0] + Lxv[3]) + 3 * (Lxv[1] + Lxv[2])
          + (3846 * Lyv[0]) + (-11781 * Lyv[1]) + (12031 * Lyv[2]);
//  Butterworth; Highpass; Order = 3; Sample Rate = 1mS; Corner = .8Hz
    Hxv[0] = Hxv[1]; Hxv[1] = Hxv[2]; Hxv[2] = Hxv[3];
    Hxv[3] = Lyv[3] / 4116; // insert lowpass result into highpass filter
    Hyv[0] = Hyv[1]; Hyv[1] = Hyv[2]; Hyv[2] = Hyv[3];
    Hyv[3] = (Hxv[3]-Hxv[0]) + 3 * (Hxv[1] - Hxv[2])
          + (8110 * Hyv[0]) + (-12206 * Hyv[1]) + (12031 * Hyv[2]);
FSignal = Hyv[3] >> Scale;  // result of highpass shift-scaled
//PLAY AROUND WITH THE SHIFT VALUE TO SCALE THE OUTPUT ~12 <> ~20 = High <> Low Amplification.

if (FSignal >= Peak && Pulse == false){  // heart beat causes ADC readings to surge down in value.  
  Peak = FSignal;                        // finding the moment when the downward pulse starts
  peakTime = sampleCounter;              // recodrd the time to derive HRV. 
if ((sampleCounter %20) == 0){// only look for the beat every 20mS. This clears out alot of high frequency noise.
  if (FSignal < 0 && Pulse == false){  // signal surges down in value every time there is a pulse
     Pulse = true;                     // Pulse will stay true as long as pulse signal < 0
     digitalWrite(13,HIGH);            // pin 13 will stay high as long as pulse signal < 0  
     Fade = 255;                       // set the fade value to highest for fading LED on pin 11 (optional)   
     HRV = peakTime - lastPeakTime;    // measure time between beats
     lastPeakTime = peakTime;          // keep track of time for next pulse
     B = true;                         // set the Quantified Self flag when HRV gets updated. NOT cleared inside this ISR     
     rate += HRV;                      // add to the running total of HRV used to determine heart rate
     beatCounter++;                     // beatCounter times when to calculate bpm by averaging the beat time values
     if (beatCounter == 10){            // derive heart rate every 10 beats. adjust as needed
       rate /= beatCounter;             // averaging time between beats
       BPM = 60000/rate;                // how many beats can fit into a minute?
       beatCounter = 1;                 // reset counter
       rate = 0;                        // reset running total
       QS = true;                       // set Beat flag when BPM gets updated. NOT cleared inside this ISR
  if (FSignal > 0 && Pulse == true){    // when the values are going up, it's the time between beats
    digitalWrite(13,LOW);               // so turn off the pin 13 LED
    Pulse = false;                      // reset these variables so we can do it again!
    Peak = 0;                           // 

}// end isr

A Quick Test

There are few packages in R that implements the Butterworth filtering on timeseries data. I’ve used mFilter to test out the theory. First I generated a cosine wave with random noise:

> x = cos(pi*seq(100)/5)+rnorm(100, sd=0.5)
> plot(x, type='l')

And then I run it through the bwfilter function to see how the algorithm smoothes out the noisy data. It should do a reasonable job of getting back our original cosine wave with the noise removed.

> f3 = bwfilter(x, freq=3)
> f4 = bwfilter(x, freq=4)
> f5 = bwfilter(x, freq=5)
> f6 = bwfilter(x, freq=6)
> plot(f3$x, col=1, type='l')
> lines(f3$trend, col=2)
> lines(f4$trend, col=3)
> lines(f5$trend, col=4)
> lines(f6$trend, col=5)
> legend("topleft", legend=c("rawdata","freq=3","freq=4","freq=5","freq=6"), col=1:5, lty=rep(1,5))

The result shows the effect of “smoothing” that Butterworth algorithm carries out on the raw data as you increase the number of sample count per cycle. In our case, the number of samples per sinusoidal wave was 10 ( pi * 100 / 5 = 20 pi = 10 waves ). With 100 total samples, that gives you 10 samples per wave. As you throttle the freq argument from 3 to 6, you can see how the filtering is taking out the random noise I added in.

By default, the bwfilter function uses order 2. The order basically determines how “complex” your model can get. Higher the order, more accurate the filtering will be, but at a computational cost. Below is the printout of bwfilter R function.

function (x, freq = NULL, nfix = NULL, drift = FALSE) 
    if (is.null(drift)) 
        drift <- TRUE
    xname = deparse(substitute(x))
    if (is.ts(x)) 
        frx = frequency(x)
    else frx = 1
    if (is.null(freq)) {
        if (frx > 1) 
            freq = trunc(frx * 2.5)
        else freq = 2
    if (is.null(nfix)) 
        nfix = 2
    xo = x
    x = as.matrix(x)
    if (drift) 
        x = undrift(x)
    n = length(x) = 2 * pi/freq
    mu = (1/tan(^(2 * nfix)
    imat = diag(n)
    Ln = rbind(matrix(0, 1, n), diag(1, n - 1, n))
    Ln = imat - Ln
    if (nfix > 1) {
        for (i in 1:(nfix - 1)) Ln = (imat - Ln) %*% Ln
    Q = t(Ln[3:n, ])
    SIGMA.R = t(Q) %*% Q
    SIGMA.n = abs(SIGMA.R)
    g = t(Q) %*% as.matrix(x)
    b = solve(SIGMA.n + mu * SIGMA.R, g)
    x.cycle = c(mu * Q %*% b)
    x.trend = x - x.cycle
    if (is.ts(xo)) {
        tsp.x = tsp(xo)
        x.cycle = ts(x.cycle, star = tsp.x[1], frequency = tsp.x[3])
        x.trend = ts(x.trend, star = tsp.x[1], frequency = tsp.x[3])
        x = ts(x, star = tsp.x[1], frequency = tsp.x[3])
    A = mu * Q %*% solve(SIGMA.n + mu * SIGMA.R) %*% t(Q)
    if (is.ts(xo)) {
        tsp.x = tsp(xo)
        x.cycle = ts(x.cycle, star = tsp.x[1], frequency = tsp.x[3])
        x.trend = ts(x.trend, star = tsp.x[1], frequency = tsp.x[3])
        x = ts(x, star = tsp.x[1], frequency = tsp.x[3])
    res <- list(cycle = x.cycle, trend = x.trend, fmatrix = A, 
        title = "Butterworth Filter", xname = xname, call =, 
        type = "asymmetric", lambda = mu, nfix = nfix, freq = freq, 
        method = "bwfilter", x = x)
    return(structure(res, class = "mFilter"))

Hmm.. the guts of the function looks somewhat familiar to me. It contains matrix manipulation that seems to construct the coefficient matrix that models the relationship among variables on a "moving window". The matrix multiplication is carried out between this coefficient matrix and the actual data, which gives the values to the right-hand side of the equation : Ax = b. The problem is then treated as an inverse problem. The function "solve" is used when you have the model and the output, but you do not know which inputs you need to make the output hold true given the relationships defined in your linear model. The coefficients, or the loadings of the variables are calculated this way, and it is a common technique used in numerical computing when the model parameters are fit to the existing dataset.

Further investigation is necessary to understand the system of equations used and what objective function this filter is trying to optimize.

Read More

BLE technology in the news

The list of URL links about MonBaby, competing products and related technologies:


Monbaby in the news and media:

The links about similar and competing products and concepts:

The introduction to Bluetooth Low Energy:

Articles about Bluetooth Low Energy applications in medical devices:

Articles about digital filters:

Read More

Developing for CC2540: Part I

IAR Development Environment

TI’s CC2540 is both the host microcontroller and a bluetooth LE chip, commonly referred to as SoC (System on Chip). You would think that the host microcontroller might be just tacked-on, an after-thought, since the bluetooth LE chip is the star of the show. If that might have been your first impression, you’d be dead wrong. The microcontroller (SoC) component of CC2540 is a full-blown 8051 core with impressive array of  peripherals and functionalities. This 8051 chip boasts 256kB flash for programming space, 8kB ram, USB driver, 2 hardware controlled UART, and many more features.  In comparison, the ever-popular Arduino Uno only has 32Kb, merely 8 time smaller than this 8051 core in CC2540.

With such a beefy spec on their 8051 core, Chipcon (subsidiary of TI since 2006) developers went all-out designing a significant software stack for their line of newer chips. This software stack relies on abstracted layers of software, delineating the logical separation of hardware interface, operating system, and user application. With the exception of the BLE stack, the part of the library that implements Bluetooth LE communication, rest of the source code is provided with the download. The code is well-thought out and nicely laid out, with ample comments that serve as documentation in itself.

This software stack takes up over 100kB of 256kB total flash space. On my machine, the compiled code took up about 110kB. It could be the differences between the IAR version and the library version (mine’s on 1.1a).

HAL Layer

The HAL (Hardware Abstraction Layer) sits on top of IAR’s device-specific defines for CC2540 (ioCC2540.h). It gives convenient mappings for IO peripherals, and macros for accessing hardware functions within CC2540 such as UART, SPI, USB, Timers, etc.

This layer also defines which ports are tied to which peripherals are mapped to which IO modules on the Evaluation board. The Chipcon’s SmartRF05EB Evalulation Board is the one that comes with CC2540 development kit. This board as many IO goodies such as LCD, led’s, eeprom, push buttons, directional joy stick. The file hal_board_cfg.h defines these mappings, and the documentation suggests modifying this file when using CC2540 on a different board (obviously!).


OSAL Layer

The development of CC2540 requires knowledge of layers of software stack that are rather involved. For example, series of tasks are handled by event-based operating system layer called OSAL (Operating System Abstract Layer). This layer is not a full operating system, however.

The OSAL layer gives wrappers and interfaces to execute linear set of operations in an organized manner. It does this by largely defining actions into 2 categories: tasks and events. Each task can handle multiple events, and each event corresponds to a specific task. You can think of this as array of tasks, each task item containing 16 bits. Each bit per task would correspond to an event that is associated with such task. Thus, you can define at most 15 (-1 for reserved) events per task.

The implementation of this task / event handling is found under OSAL.c, within the function osal_run_system.

  uint8 idx = 0;


  do {
    if (tasksEvents[idx])  // Task is highest priority that is ready.
  } while (++idx < tasksCnt);

  if (idx < tasksCnt)
    uint16 events;
    halIntState_t intState;

    events = tasksEvents[idx];
    tasksEvents[idx] = 0;  // Clear the Events for this task.

    activeTaskID = idx;
    events = (tasksArr[idx])( idx, events );
    activeTaskID = TASK_NO_TASK;

    tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.

Notice it scans from the lowest idx (highest priority task), finds the task with any event set on it. It then drops into the if block that checks to make sure the idx of the task is not the max of tasks registered. Within this block, it simply calls the callback function registered within tasksArr which is a global variable containing all registered callback functions. Prior to the execution of this function, the data arrays tasksEvents and tasksArr needs to be created during compile time.

Read More

BLE Protocol Stack

The Bluetooth LE’s protocol is comprised of several layers of both hardware and software implemented inter-communication paradigm. The picture below describes how the protocol stack is organized:


The developers typically deal with both GAP and GATT layers when implementing their applications. The GAP layer defines several roles the bluetooth LE end-device will be classified as. The GATT layer defines profiles, which is organized set of data and services the end-device will support. Through these layers, each BLE device can not only be identified, but its characteristics and attributes can be determined by other nodes wanting to pair against it. The lower layers of the protocol stack is both a combination of hardware implementation and software enforced interface.

New GATT profile specifications are being proposed and adopted by the members of Bluetooth SIG. These specifications provide guidelines across wide range of end-user applications and scenarios. A complete list of these profiles can be found here.

In order to draw a parallel against the internet world, the GAP can be thought of as a type of application protocol such as FTP, HTTP, SSH. Furthermore, once an application has been classified as HTTP, it would support protocol specific commands such as GET or POST requests, among others. These protocol-specific set of functions and data can be thought of as GATT in the BLE world.

For more detailed description of the BLE protocol stack, the following documents by TI can be very useful in understanding the basic concepts.



Read More

A Foray Into Bluetooth LE

Bluetooth Low Energy, or otherwise known as Bluetooth v4.0, is the new wireless standard targeted for new generation of low-power applications. With the advent of smartphone technologies and mobile computing, the need for portable sensors and near-communication networks have become a new found interest among vendors as well as consumers.

We are at the cusp of technological convergence and advancement that will make significant impact in the way we live. Low-power wireless sensors can be literally embedded everywhere, from wearable devices to buildings, and common objects that we associate with day-to-day. These monitors can be designed to transmit useful data from their physical surroundings and environments, and the collected data can be harvested for practical applications.

One of the primary areas where we envision the use of this wireless technology is within the medical industry. Bluetooth LE can enable telemonitoring, or remote monitoring, of patients. The vital signals such as heartrate, blood pressure, body temperature and be monitored and the data can be transmitted wirelessly. These sensors can not only provide detailed data for personnel caring for the patients, but also trigger alerts upon patient-specific body conditions. This will allow continuous active monitoring of patients who need intensive care and will help improve the quality of diagnose and treatment.

There are many useful resources online in order to learn more about Bluetooth LE. To list a few:

We will focus on developing useful and exciting devices with Bluetooth LE. While our products will not be limited to using Bluetooth LE, it will be interesting to see cool applications come out of this new wireless standard in the coming few years. Stay tuned!

Read More