ECG Project Report New
-
Upload
dileepkinjarapu -
Category
Documents
-
view
372 -
download
1
Transcript of ECG Project Report New
Low Cost Electrocardiography Monitoring System using Microcontroller
A project report submitted in partial fulfillment of the requirement for theaward of the degree of
BACHELOR OF ENGINEERINGIN
ELECTRONICS AND INSTRUMENTATION
Submitted by
Pradeep Kumar Terli V.S.Satya Praveen
T.Anil Kumar
Under the esteemed guidance of
Mrs.P.Indira,M.E.,Assistant Professor
Dept. of Electronics and Instrumentation Engineering
DEPARTMENT OF ELECTRONICS AND INSTRUMENTATION ENGINEERINGGITAM INSTITUTE OF TECHNOLOGY
(Autonomous) GITAM UNIVERSITY
Visakhapatnam-45
2010-2011DECLARATION
This is to certify that Report entitled “Low Cost Electrocardiography Monitoring System Using
Microcontroller” which is submitted by me in partial fulfillment of the requirement for the award
of Bachelors degree in Electronics and Instrumentation Engineering, GITAM Institute of
Technology , GITAM University comprises only my original work and due acknowledgement
has been made in the text to all other material used.
Date: Name of student
(signature)
APPROVED BY
Name & Designation of the Project Guide
(signature)
CERTIFICATE
This is to certify that report entitled “Measurment of Temperature using Thermocouple with the
help of Microcontroller” which is submitted by BATCH 6 in partial fulfillment of the
requirement for the award of degree B.Tech in Electronics & Instrumentation Engineering to
Department of Electronics & Instrumentation Engineering, GITAM Institute of
Technology is a record of the candidate own work carried out by him under my supervision. The
matter embodied in this thesis is original and has not been submitted for the award of any other
degree.
Date: Name & Desigantion of the Project Guide
(signature)
(signature) (signature)
Name and Designation Head of the Department
Project Coordinator
Electrocardiograph ( ECG )
Electrocardiography (ECG, or EKG [from the German Elektrokardiogramm]) is a transthoracic
interpretation of the electrical activity of the heart over timecaptured and externally recorded by
skin electrodes.[1] It is a noninvasiverecording produced by an electrocardiographic device.
The ECG works mostly by detecting and amplifying the tiny electrical changes on the skin that
are caused when the heart muscle "depolarises" during each heart beat. At rest, each heart muscle
cell has a charge across its outer wall, or cell membrane. Reducing this charge towards zero is
called de-polarisation, which activates the mechanisms in the cell that cause it to contract.
During each heartbeat a healthy heart will have an orderly progression of a wave of
depolarisation that is triggered by the cells in the sinoatrial node, spreads out through the atrium,
passes through "intrinsic conduction pathways" and then spreads all over the ventricles. This is
detected as tiny rises and falls in the voltage between two electrodes placed either side of the
heart which is displayed as a wavy line either on a screen or on paper. This display indicates the
overall rhythm of the heart and weaknesses in different parts of the heart muscle.
ECG Waveform
Lead Configurations
Limb leads
Leads I, II and III are called limb leads. The electrodes that form these signals are located on the
limbs—one on each arm and one on the left leg. The limb leads form the points of what is known
as Einthoven's triangle.
Lead I is the voltage between the (positive) left arm (LA) electrode and right arm (RA) electrode:
I = LA − RA.
Lead II is the voltage between the (positive) left leg (LL) electrode and the right arm (RA)
electrode:
II = LL − RA.
Lead III is the voltage between the (positive) left leg (LL) electrode and the left arm (LA)
electrode:
III = LL − LA.
Augmented limb leads
Lead augmented vector right (aVR) has the positive electrode (white) on the right arm. The
negative electrode is a combination of the left arm (black) electrode and the left leg (red)
electrode, which "augments" the signal strength of the positive electrode on the right arm:
Lead augmented vector left (aVL) has the positive (black) electrode on the left arm. The
negative electrode is a combination of the right arm (white) electrode and the left leg (red)
electrode, which "augments" the signal strength of the positive electrode on the left arm:
Lead augmented vector foot (aVF) has the positive (red) electrode on the left leg. The negative
electrode is a combination of the right arm (white) electrode and the left arm (black) electrode,
which "augments" the signal of the positive electrode on the left leg:
Unipolar vs. bipolar leads
Bipolar leads have one positive and one negative pole
Unipolar leads also have two poles, as a voltage is measured; however, the negative pole is a
composite pole (Wilson's central terminal) made up of signals from lots of other electrodes
PROJECT’s BLOCK DIAGRAM
Surface Electrodes to Pick up the ECG signal from human body
Amplification Instrumentation
AmplifierOpto Isolator
Band Pass Filter0.05 Hz – 120
Hz
Notch Filter50Hz
ATMega32Or
PIC MicrocontrollerFor programming Graphical LCD
GraphicalLCD Display
For ECG display
Adaptive Filtering (LMS Algorithm)
Disposable Electrodes
INSTRUMENTATION AMPLIFIER
SPECIFICATIONSEasy to use
Higher performance than discrete design
Single-supply and dual-supply operation
Input voltage range extends 150 mV below ground (single supply)
Low power, 550 μA maximum supply current
Gain set with one external resistor
Gain range: 1 (no resistor) to 1000
Noise: 35 nV/√Hz RTI noise @ 1 kHz (G = 1)
Excellent AC specifications
90 dB minimum CMRR (G = 10); 70 dB minimum CMRR (G = 1) at 60 Hz, 1 kΩ source
imbalance
800 kHz bandwidth (G = 1)
APPLICATIONS : Low power medical instrumentation, Transducer interfaces
Thermocouple amplifiers, Industrial process controls,Difference amplifiers.
ATMEGA32 Microcontroller
High-performance, Low-power AVR® 8-bit Microcontroller
Advanced RISC Architecture
131 Powerful Instructions – Most Single-clock Cycle Execution
Nonvolatile Program and Data Memories
32K Bytes of In-System Self-Programmable Flash
True Read-While-Write Operation
1024 Bytes EEPROM
– 2K Byte Internal SRAM
– Four PWM Channels
– 8-channel, 10-bit ADC
– On-chip Analog Comparator
– Internal Calibrated RC Oscillator
External and Internal Interrupt Sources
– Six Sleep Modes: Idle, ADC Noise Reduction, Power-save, Power-down, Standby and Extended Standby
• I/O and Packages– 32 Programmable I/O Lines
• Operating Voltages– 4.5 - 5.5V for ATmega32
• Speed Grades– 0 - 16 MHz for ATmega32
• Power Consumption at 1 MHz, 3V, 25°C for ATmega32L– Active: 1.1 mA– Idle Mode: 0.35 mA– Power-down Mode: < 1 μA
FeaturesHigh current transfer ratio : CTR >50%
High I/O isolation voltage :
VISO = 5000 Vrms (min.)
Fast response :
tr = 2 ms, tf = 3 ms(typ.)
Low dark current : ICEO < 100nA
Design Procedure:High pass filterPick C1 = C2: __________Calculate R1:2 * *C1*Frequency1: ___________
Low pass filter
Pick C1: __________Calculate C2 = C1 * 2: __________Calculate R1 and R2 =2 2 * *C1*Frequency1: __________
Notch Filter Design
ADAPTIVE 50HZ NOISE CANCELLATION
Least mean squares (LMS) algorithms are a class of adaptive filter used to mimic a desired
filter by finding the filter coefficients that relate to producing the least mean squares of the error
signal (difference between the desired and the actual signal). It is a stochastic gradient descent
method in that the filter is only adapted based on the error at the current time.
Hardware Implementation
60 Noise Cancellation System (Block Diagram)
This is the overall noise cancellation technique we use. Here we show the entire system in a
reduced "block diagram" format. Input/output pins are shown on the ATmega32.
Noise Adder (60 Hz Adaptive Noise Cancellation)
This circuit is used to create a 60 Hz contaminated signal for adaptive filter cancellation. Since
we need to be able to test our adaptive algorithm with a well-known and understood signal, we
used this non-inverting adding circuit so that we can sum a 60 Hz "noise" signal and a valid
reference signal. We use one function generator to make a "clean" signal and sum it with the
output of the transformer circuit
shown below.
Noise Remover (60 Hz Adaptive Noise Cancellation)
This circuit takes in the noise contaminated signal and an adaptive output signal from the
ATmega32 and sums them to remove the contamination. The overall output is then fed back to
the ATmega32 as an error reference signal through a RC lowpass to prevent aliasing.
AC Transformer Input Converter
We used an AC transformer to adaptively cancel "real" 60 Hz noise in from the 120 V
powerlines (the standard voltage and frequency of powerlines across the U.S.). In order to obtain
an reference voltage suitable for the ATmega32, we used the following circuit. The AC
transformer takes in a 56 V peak-to-peak signal (18 V RMS) and converts it to a 1.6 V peak-to-
peak, 1.8 V DC offset. We are using a 2.56 V reference voltage on the ATmega32 ADC.
RC Filter
The RC lowpass to filter the PWM out from the ATmega32 was made of a 20k Ohm resistor and
a 0.04 uF capacitor so that it has a cutoff frequency of about 230 Hz. Because are resistors and
capacitors are only valid to 5% and because the RC doesn't have the steepest cutoff, the cutoff
frequency is appropriate for the function.
ATMEGA32 PROGRAM FOR FILTERING
/* * Captures a reference signal (60Hz) from A.0, an error signal in * A.1, and adaptively generate an output to B.3 that minimizes the * correlation between input and error. * * By Robert Ochshorn and Kyle Wesson */
#include <inttypes.h>#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>
//output rate select/* #define OUT_CLK_OVR_8 /\* output with clock speed over 8 *\/ *//* #define OUT_CLK_OVR_64 /\* output with clock speed over 64 *\/ */#define OUT_FULL_CLK /* output with full clock speed */
//input rate select
/* #define IN_CLK_OVR_8 /\* output with clock speed over 8 *\/ */#define IN_CLK_OVR_64 /* output with clock speed over 64 *//* #define IN_FULL_CLK /\* output with full clock speed *\/ */
/* the increment shift determines what to divide the difference between previous output and next desired output in order to interpolate towards the desired output.*/
#ifdef OUT_FULL_CLK #ifdef IN_CLK_OVR_64 #define INC_SHIFT 7 #endif #ifdef IN_CLK_OVR_8 #define INC_SHIFT 4 #endif #ifdef IN_FULL_CLK #define INC_SHIFT 1 #endif#endif#ifdef OUT_CLK_OVR_8 #ifdef IN_CLK_OVR_64 #define INC_SHIFT 4 #endif #ifdef IN_CLK_OVR_8 #define INC_SHIFT 2 #endif #ifdef IN_FULL_CLK #define INC_SHIFT -2 #endif#endif#ifdef OUT_CLK_OVR_64 #ifdef IN_CLK_OVR_64 #define INC_SHIFT 2 #endif #ifdef IN_CLK_OVR_8 #define INC_SHIFT -2 #endif #ifdef IN_FULL_CLK #define INC_SHIFT -5 #endif#endif
#define FILTER_LENGTH 8 /* how many samples do we hold onto? */#define STEP_SIZE 1 /* filter one out of X inputs */
unsigned char INPUT_LENGTH = FILTER_LENGTH*STEP_SIZE; /* length of input buffer */
//outputsigned long accumulator; /* 16:16 fixed-point...the integer value is what we send to OCR0 */signed int increment; /* 0:16 fixed-pi */
signed long prev_out; /* previous output value */signed long out; /* next output value desired */
//inputunsigned char input[FILTER_LENGTH*STEP_SIZE]; /* reference input sampled as an 8:0 char. TODO: 10-bit a/d? */unsigned char* input_next; /* pointer to the next open spot in the input array */unsigned char* input_ptr; /* "disposable" pointer for use in loops */
//filtersigned long w[FILTER_LENGTH]; /* filter weights in 16:16 fixed point */
signed long safe_w[FILTER_LENGTH]; /* a safe way to restore our weights */
#define SAFE_W_RESET 10000unsigned int safe_w_time;
unsigned long err_mu; /* fixed-point error*mu */
#define MU 2 /* convergence rate */#define MU_SHIFT 0; /* Sets a threshold for error of magnitude of error that will cause weights to be updated (0-8) */
#define THRESHOLD 12 /* 16-X*/
char shift;
char error, error_cutoff; /* the captured error value and the cutoff between positive and negative, respectively. */
//fixed point math/* These defines allow 16:16 fixed point math */#define multFix80(a,b) (((a*((signed long)b)))) /* multiply fixed by 8:0 char */#define int2fix(a) (((signed long)(a))<<16) /* Convert char to fix. a is a char */#define fix2int(a) ((signed int)((a)>>16)) /* Convert fix to char. a is an int */#define float2fix(a) ((signed long)((a)*65536.0)) /* Convert float to fix. a is a float */#define fix2float(a) ((float)(a)/65536.0) /* Convert fix to float. a is an int */
#define LED_TIME_RESET 250 /* blink an LED every x times through the timer loop */
int led_time;int i;
int error_acc;
enum capture_states {REF_CAPT, ERR_CAPT};int capture_state;
enum flags {REF_READY, ERR_READY, WAITING};int process_state;
enum safety_states {SAFE_READY, NOTHING_IS_SAFE};int safety_state;
void init(void);void computeOutput(void);void updateWeightsLMS(void);void timing_fail(void);
// OUTPUTISR (TIMER0_OVF_vect) { accumulator += increment; OCR0 = 128 + fix2int(accumulator);}
// INPUTISR (TIMER2_OVF_vect) { switch(capture_state) { case REF_CAPT: if(++input_next == input+INPUT_LENGTH) { input_next = input; /* reset buffer ptr */
error_cutoff = error_acc / INPUT_LENGTH; /* normalize error cutoff */ error_acc = 0; /* reset error_acc */
}
capture_state = ERR_CAPT; *input_next = ADCH; /* get input sample */ process_state = REF_READY; break;
case ERR_CAPT:
capture_state = REF_CAPT; error = ADCH; error_acc += error; process_state = ERR_READY;
break; }
ADMUX ^= 1; /* toggle input source to A.1 */ ADCSRA |= 1<<ADSC; /* start next a/d conversion */
}
void computeOutput(void) { prev_out = out;
//compute output: y = \sum_{i=0}^{n} w_i * input_i i=0; out=0; //from least-recent input to end of buffer for(input_ptr=input_next; input_ptr<input+INPUT_LENGTH; input_ptr+=STEP_SIZE) { out += multFix80(w[i++], *input_ptr); } //from start of buffer to most-recent input for(input_ptr=input; input_ptr<input_next; input_ptr+=STEP_SIZE) { out += multFix80(w[i++], *input_ptr); } if(fix2int(out) > 128 || fix2int(out) < -128 || fix2int(out-prev_out) > 80 || fix2int(prev_out-out) > 80) { switch(safety_state) { case SAFE_READY: safe_w_time = SAFE_W_RESET; safety_state = NOTHING_IS_SAFE; //revert weights for(i=0; i<FILTER_LENGTH; i++) { w[i] = safe_w[i]; } PORTD ^= 0xff; //toggle LED computeOutput(); return; break; case NOTHING_IS_SAFE: for(i=0; i<FILTER_LENGTH; i++) { w[i] = 0; } PORTD ^= 0xff; //toggle LED computeOutput(); return; break; } } increment = (out-prev_out)>>INC_SHIFT;
}
/* efficient LMS implementation */void updateWeightsLMS(void) { i = 0;
if(error > error_cutoff) { shift = (error - error_cutoff)>>THRESHOLD; /* this serves as an amaglamation of mu and error magnitude */ for(input_ptr=input_next; input_ptr<input+INPUT_LENGTH; input_ptr+=STEP_SIZE) { w[i++] -= *input_ptr>>shift; } for(input_ptr=input; input_ptr<input_next; input_ptr+=STEP_SIZE) { w[i++] -= *input_ptr>>shift; } } else { shift = (error_cutoff - error)>>THRESHOLD; for(input_ptr=input_next; input_ptr<input+INPUT_LENGTH; input_ptr+=STEP_SIZE) { w[i++] += *input_ptr>>shift; } for(input_ptr=input; input_ptr<input_next; input_ptr+=STEP_SIZE) { w[i++] += *input_ptr>>shift; } }}
int main(void) { init(); while(1) { switch(process_state) { case WAITING: break; case REF_READY: computeOutput(); process_state = WAITING; break; case ERR_READY: if(--safe_w_time == 0) { /* backup a hopefully-working set of weights */ safe_w_time = SAFE_W_RESET; for(i=0; i<FILTER_LENGTH; i++) { safe_w[i] = w[i]; } safety_state = SAFE_READY; } updateWeightsLMS(); process_state = WAITING; break; } } return(0);}
void init(void) {
//led DDRD = 0xff; /* drive PORTD to output */ PORTD = 0x00; /* initialize LED on (active low)*/ led_time = LED_TIME_RESET; /* initialize LED reset scalar */
//ain DDRA = 0x00; /* drive PORTA to input */
//ocr0 DDRB = 0xff; /* drive PORTB to output */
//buffers input_next = input; /* initialize input_next pointer to the beginning of the input array */
for(i=0; i<(FILTER_LENGTH*STEP_SIZE); i++) { w[i] = int2fix(0); /* set filter weights to start at 0 */ input[i] = 0; /* initialize input buffer to 0 */ }
safe_w_time = SAFE_W_RESET;
process_state = WAITING;
safety_state = NOTHING_IS_SAFE;/* w[0] = float2fix(-0.3); */
//error capture_state = REF_CAPT; error_cutoff = 40; /* divide between positive and negative */
//init a/d and start capture ADMUX = 1<<ADLAR | /* left-adjust result */ 1<<REFS1 | 1<<REFS0; /* internal vref with external cap at aref pin */ ADCSRA = 1<<ADEN | /* ADC enable */ 1<<ADSC | /* start conversion */ 1<<MUX2 | 1<<MUX1 | 1<<MUX0; /* 128 prescalar */
TCCR0 = 1<<WGM01 | 1<<WGM00 | /* fast PWM mode */ 1<<COM01; /* clear OC0 on compare match */
#ifdef OUT_CLK_OVR_8 TCCR0 |= 0<<CS02 | 1<<CS01 | 0<<CS00; /* clk/8 prescaler */#else #ifdef OUT_CLK_OVR_64 TCCR0 |= 0<<CS02 | 1<<CS01 | 1<<CS00; /* clk/64 prescaler */ #else
TCCR0 |= 0<<CS02 | 0<<CS01 | 1<<CS00; /* full clock speed*/ #endif#endif
TCCR2 = 0<<WGM01 | 0<<WGM00 | /* normal timer/counter operation */ 1<<COM21 | 0<<COM20; /* clear oc2 on compare match */
#ifdef IN_CLK_OVR_64 TCCR2 |= 1<<CS22 | 0<<CS21 | 0<<CS20; /* clk/64 prescaler */#else #ifdef IN_CLK_OVR_8 TCCR2 |= 0<<CS22 | 1<<CS21 | 0<<CS20; /* clk/8 prescaler */ #else TCCR2 |= 0<<CS22 | 0<<CS21 | 1<<CS20; /* full speed ahead */ #endif#endif
TIMSK = 1<<TOIE0 | 1<<TOIE2; /* timer/counter0&2 overflow interrupt enable */
//crank up 'em interrupts! sei (); /* enable ISRs */}
void timing_fail(void) {
//disable interrupts TIMSK = 0<<TOIE0 | 0<<TOIE2;
int reset = 19000000;
//die badly while(1) { if(led_time != 0) { led_time--; } else { led_time = reset;
PORTD ^= 0xff; //blink LED } }
}
Graphic LCD - 128x64 G B/L
Dot matrix LCD segment driver with 64 channel output
·Input and Output signal
-Input: 8 bit parallel display data
Control signal from MPU
Splitted bias voltage (V1R, V1L, V2R, V2L,V3R. V3L, V4R, V4L)
- Output: 64 channel waveform for LCD driving.
· Display data is stored in display data RAM from MPU.
· Interface RAM
- Capacity: 512 bytes (4096 bits)
- RAM bit data: RAM bit data = 1:ON
RAM bit data- = 0:OFF
· Applicable LCD duty: 1/32~1/64
· LCD driving voltage: 8V~17V(VDD-VEE)
· Power supply voltage: + 5V±10%
· High voltage CMOS process.
· 100QFP and bare chip available.