This project gives a basic idea of how to develop patient monitoring systems based on a Windows Mobile device.

Introduction
Some time back, I developed a prototype real-time monitoring console for medical monitoring. This tip explains my work.
Definitions
- ECG means electrocardiograph, a graph that indicates electrical activity of heart tissues.
- SPO2 means Oxyhemoglobin saturation, or simply the percentage of Oxygen in blood. For a normal adult at rest, this could be around 95 to 99.
- Respiration means one inspiration and one expiration. For a normal adult at rest, this could be around 16 to 20 per minute.
Application and Scope
Biomedical monitors are used in critical care applications where patients are continuously monitored for any changes in the function of their vital organs. If such a monitor streams data to handheld devices like Windows Mobile phone, we can implement an anywhere, anytime monitoring device. This can help medical specialists to monitor any patient instantly, without leaving their seat.
The current demo takes values from static integer arrays. But, I will soon move it to Bluetooth to plot true real-time data. I have tested the code myself on an i-mate K-JAM device that runs Windows Mobile 5.0. However, this code should run on any PPC 2003 compatible device.
The application's working is quite simple, as described below:
public partial class Form1 : Form
{
int x, p, q, r, y, px, pp, pq, pr, py = 0;
Pen yelgpen = new Pen(Color.YellowGreen);
Pen redpen = new Pen(Color.Red);
Pen graypen = new Pen(Color.Gray);
Pen blackpen = new Pen(Color.Black);
int[] ECGArray = new int[]
{ -5, -14, -10, -8, -9, -7, 0, 121, 108, -24, -34, -18, -19, -16, -19, -17,
-11, -11, -10, -1, 13, 33, 45, 47, 46, 37, 12, -12, -24, -23, -25, -21, -20,
-17, -19, -14, -12, -13, -12, -13, -8, -9, -5, -8, 10, 21, 19, 4, -10,
-11, -11, -12, -8, -12, 0, 121, 108, -24, -23, -18, -21, -16, -15, -14,
-10, -12, -7, 5, 26, 43, 46, 46, 41, 21, -1, -18, -24, -19, -22, -21,
-18, -18, -16, -13, -10, -12, -11, -8, -10, -8, -7, 0, 18, 24, 9, -7,
-13, -11, -9, -8, -10, 0, 121, 108, -24, -33, -17, -20, -19, -17, -14,
-13, -11, -8, 2, 19, 35, 47, 50, 43, 29, 7, -15, -29, -22, -25, -20,
-16, -19, -17, -16, -12, -11, -11, -10, -11, -9, -6, 0, 13, 23, 15, -2,
-11, -10, -10, -8, -7, -15, 0, 121, 108, -24, -20, -19, -20, -16, -12,
-14, -15, -11, -2, 12, 30, 41, 48, 44, 34, 16, -5, -21, -22, -21, -20,
-20, -13, -15, -15, -17, -14, -13, -9, -10, -10, -11, -8, 5, 23, 22, 4,
-9, -10, -12, -10, -10, -11, 0, 121, 108, -24, -28, -18, -19, -16, -16,
-16, -15, -13, -8, 4, 21, 39, 44, 46, 38, 45, 24, -1, -23, -28, -27, -25,
-20, -21, -18, -18, -14, -14};
int[] SPO2Array = new int[]
{ 10, 9, 9, 9, 9, 9, 9, 10, 12, 16, 20, 25, 31, 37, 41, 45, 47, 47,
46, 42, 38, 33, 27, 23, 20, 17, 15, 15, 16, 16, 18, 18, 19, 19, 18, 18, 17,
16, 15, 13, 13, 11, 11, 11, 10, 10, 9, 9, 9, 9, 9, 9, 10, 12, 16, 20, 25,
31, 37, 41, 45, 47, 47, 46, 42, 38, 33, 27, 23, 20, 17, 15, 15, 16, 16, 18,
18, 19, 19, 18, 18, 17, 16, 15, 13, 13, 11, 11, 11, 10, 10, 9, 9, 9, 9, 9,
9, 10, 12, 16, 20, 25, 31, 37, 41, 45, 47, 47, 46, 42, 38, 33, 27, 23, 20,
17, 15, 15, 16, 16, 18, 18, 19, 19, 18, 18, 17, 16, 15, 13, 13, 11, 11, 11,
10, 10, 9, 9, 9, 9, 9, 9, 10, 12, 16, 20, 25, 31, 37, 41, 45, 47, 47, 46,
42, 38, 33, 27, 23, 20, 17, 15, 15, 16, 16, 18, 18, 19, 19, 18, 18, 17, 16,
15, 13, 13, 11, 11, 11, 10, 10, 9, 9, 9, 9, 9, 9, 10, 12, 16, 20, 25, 31,
37, 41, 45, 47, 47, 46, 42, 38, 33, 27, 23, 20, 17, 15, 15, 16, 16, 18, 18,
19, 19, 18, 18, 17, 16, 15, 13, 13, 11, 11, 11, 10, 10, 10, 10 };
int[] respArray = new int[] { 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52,
53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 57,
57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55,
54, 54, 54, 54, 54, 53, 53, 53, 52, 52, 51, 51, 51, 50, 50, 50, 49,
49, 49, 48, 48, 47, 47, 47, 46, 46, 46, 45, 45, 45, 45, 44, 44, 44,
43, 43, 42, 42, 41, 41, 41, 40, 40, 39, 39, 38, 38, 38, 37, 37, 37,
36, 36, 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 34, 33, 33, 33, 33,
33, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31,
31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34,
34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 39, 39, 40, 40,
40, 41, 41, 42, 42, 42, 43, 43, 44, 44, 45, 45, 45, 45, 46, 46, 46,
46, 47, 47, 47, 47, 48, 48, 49, 49, 49, 49, 49, 49 };
Now, use a timer to get the graph moving:
private void timer1_Tick(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
for (int i = 0; i < ECGArray.Length; i++)
{
if (x > this.Width - 10)
{
x = 0;
pp = 0;
pq = 0;
pr = 0;
px = 0;
}
x += 1;
p = 70 - (ECGArray[i] / 6 + 50);
g.DrawLine(yelgpen, px, pp, x, p);
g.DrawLine(yelgpen, px, pp + 60, x, p + 60);
g.DrawLine(yelgpen, px, pp + 120, x, p + 120);
q = ((SPO2Array[i] * -1) / 2 + 200);
g.DrawLine(graypen, px, pq, x, q);
r = (respArray[i] / 2 + 220);
g.DrawLine(redpen, px, pr, x, r);
g.DrawRectangle(blackpen, 0, 0, x + 1, this.Height);
pp = p;
pq = q;
pr = r;
px = x;
}
}
Do not forget to keep the timer enabled. I have set the timer interval to 1ms to get a good sweep speed.
History
- 14th February, 2022: Initial version