Professional Documents
Culture Documents
User
Interface
Signal Processing Module
EEG Module
Alarm
EEG Signal Clock
Circuit Processing Circuit
Circuit
Display Relay
Circuit Circuit
Figure A.1: Block Diagram of Project - block diagram demonstrating the modularity of our project.
16
APPENDIX B – SCHEMATICS
C R2
Left Electrode
.1u 33k
R1 C
3.3mega U17
.1u + U18
0 OUT +
0
- OUT Output
C R2 AD622
Right Electrode - OPAMP
.1u 33k C
R1
3.3mega
.1u
0
Neck Electrode
0
0
Figure B.1: Original Schematic - Schematic of original design for EEG Circuit
C R2
.1u R1 33k C
3.3mega
.1u
0
0
Figure B.2: Old Filters - Original bandpass filter used in EEG Circuit
0.1u R2
R1 R1 U7 3.3mega
+ C C
33k 33k U6
OUT
C +
0.1u 0.1u R2
0.1u - OUT
OPAMP
3.3mega
- OPAMP
Figure B.3: New Filters - Final design for bandpass filter used in EEG Circuit
17
+5 V
4 3 47 Kohm
+5 V PIC16F877A
F1100E
1
2 V(t) 2
+5 V 1N5822
1 amp fuse 9
10
11
12
1N4734 13
14
15
sigA sigB
Figure B.4: PIC Schematic - Schematic of final signal processing module
18
19
Figure B.5: Alarm Clock Schematic – Schematic of the Alarm clock module
APPENDIX C – FLOW CHARTS
Start
Initialize
Average
Determine
frequency and set
old_State =
current_State
Is frequency
No between 9
and 13 Hz? Yes
Is old_State
No
= Beta? Yes
Output B = 1
20
Clock and Alarm Time Flowchart
Start
Initialize interrupt
vectors and
I/O ports
Enable all
interrupts
No Display Time
Start Alarm_Signal
and Start Relay
sub-charts
Is Set_Time
Yes
= 1?
Yes
Is Set_Alarm
Yes
= 1?
Disable all
interrupts
Disable all
interrupts
Is Increment
= 1?
No
Yes
Is Increment
= 1? No
No
Yes Increment
Clock_Time
No
Increment
Alarm_Time
Is Set_Time
= 0?
Is Set_Alarm
Yes
= 0?
Figure C.2: Flow Chart2 - Flow chart for Alarm Clock pic.
21
Check ClockTime
Start Alarm_Signal
and AlarmTime
(AlarmTime - 90 minutes)
< ClockTime <
AlarmTime? Yes
Is AlarmClock
No
No Enabled?
Yes
Is signalA
No
high?
Yes
Don’t Sound
Sound Alarm
Alarm
Yes
Is AlarmClock
No
Enabled?
22
Relay conditions for turning on and off
Start Relay
Is Awake
No Yes
= 1?
Is Alarm_EN
No Yes
= 1?
Is Sleeping Is Sleeping
No
= 1? = 1? Yes
Yes
Yes
Is signal B Is signal B
No
= 1? = 1?
No
No
No
Yes
Yes
23
Interrupt Handler Flowchart
From
main to Start Interrupt
interrupt Handler
handler
Disable all
interrupts
Increment
timer1Count
and set Timer1 to
3036
Is timer1Count
Yes
= 120?
Increment timeMin
and set
No timer1Count = 0
Return
from Enable all
interrupt interrupts
handler
24
APPENDIX D – SIMULATIONS & TEST DATA
Figure D.1: Frequency response - The red line is the frequency response for the passive filter design.
The green line is the frequency response of the active filter design.
25
Figure D.2: Gain Verification I - The bottom signal represents the input signal of 1mVpp. The top signal
represents the output of approximately 3.31Vpp.
Figure D.3: LPF Verification I – The bottom signal represents the input signal of 1mVpp at 75 Hz. The
top signal shows the effects of the low pass filter at 75 Hz with an output of only 2.56Vpp, rather than
3.31Vpp.
26
Figure D.4: HPF Verification I – The bottom signal represents the input signal of 1mVpp at 0.1 Hz. The
top signal shows the effects of the high pass filter at 0.1 Hz with an output of only 1.76Vpp, rather than
3.31Vpp.
Figure D.5: EEG Comparison – The left plot is a recording of the EEG output from the final circuit on
the PCB. The right plot is a recording of the EEG output from the demo circuit on the breadboard.
27
Figure D.6: Gain Verification II – This signal represents the output of approximately 1.2Vpp.
Figure D.7: LPF Verification I – This signal shows the effects of the low pass filter at 75 Hz with an
output of only .47Vpp, rather than the expected 1.2Vpp.
28
Figure D.8: HPF Verification II - This signal shows the effects of the high pass filter at 0.1 Hz with an
output of only .231Vpp, rather than the expected 1.2 Vpp.
Frequency Response
1.4
1.2
1
Voltage (V)
0.8
0.6
0.4
0.2
0
0 10 20 30 40 50 60 70 80 90 100
Frequency (Hz)
Figure D.9: Actual Frequency Response – Plot of data recorded from EEG circuit showing the actual
frequency response from 0.1-100 Hz.
29
Figure D.10: Signal Processing PIC Design - Desired response of sigA
30
PIC time www.time.gov PIC interval www.time.gov Difference
interval
10:10 1:18:00 N/A N/A N/A
10:20 1:28:00 10 min 10 min 0
10:30 1:38:00 20 min 20 min 0
10:40 1:48:00 30 min 30 min 0
10:50 1:58:00 40 min 40 min 0
11:00 2:08:00 50 min 50 min 0
11:10 2:18:00 1h 1h 0
02:36 17:43:48 16 h, 26 min 16 h, 25 m, 48s +12 s
10:10 1:17:44 24 h 23 h, 49m, 44s + 16 s
Table D.1: Alarm Clock PIC Analysis - Comparison of PIC time with www.time.gov time, showing
how accurate our alarm clock is.
31
APPENDIX E – PICTURES
Figure E.1: Electrode Placement – This picture shows the placement of the electrodes on the user. Two
electrodes are place on the right and left side of the forehead, and a third electrode is placed on the neck
which serves as a ground.
Relay
Circuit
Banana Jack
Inputs from
Electrodes
Appliance
Control
Switches
Plexiglass Cover
Display Circuit
EEG Circuit (Signal Processing Circuit and Alarm Clock Circuit below)
Figure E.2: Alarm Clock Box – This picture shows the front view of the alarm clock box and the
placement of most of the associated hardware.
32
Figure E.3: Bad PCBs - This figure shows the Display PCB. An area of the PCB has been enlarged in
order to show where the copper contacts were peeling off.
33
APPENDIX F – PARTS AND COST
Please note that Tables F.1-F.4 are tables listing all the parts and costs associated with the different
modules of the project. Each table includes a part #, description, quantity, price, and total price.
Table F.2: Signal Processing Module - Parts and Cost for Signal Processing Module
34
Part # Description Qty. Price Total
PIC16F877A PIC Microcontroller 1 $4.76 $4.76
FOX F1100E 4 MHz Crystal Oscillator** 1 - -
N/A 47kΩ Resistor** 1 - -
N/A 1-amp Fuse** 1 - -
1N58222 Schottky Diode** 1 - -
1N4734 Zener Diode** 1 - -
LSD3211-11 (MAN74) 7 Segment HEX Display 4 $1.62 $6.48
CD4511BE BCD-to-7 Segment Converter 4 $0.63 $2.52
T77S1D10-05 Relay 2 $2.11 $4.22
74AC11000 4 NAND Gate IC 1 $1.30 $1.30
MCP320B2 Piezo-Buzzer 1 $2.70 $2.70
N/A Miscellaneous Parts $10 $10
* 2-State Switch 4 ~*
* Push Button 2 ~*
* 4 Position Switch 1 ~*
* 900 nF Capacitor 9 ~*
* 10 kΩ Resistor 9 ~*
* 220 Ω Resistor 40 ~*
* 15 pF Capacitor 2 ~*
N/A PCB 2 $3.29 $6.58
------------
TOTAL $38.56
* Covered in Miscellaneous Costs
** Parts shared with Signal Processing Module
Table F.3: Alarm Clock Module - Parts and Cost for Alarm Clock Module
35
APPENDIX G – MISCELLANEOUS
Table G.1: Brain Waves - shows the frequency ranges associated with each stage of sleep.
Pin
# Label I/O Description To/From Part
2 A0 I Analog Signal from EEG
4 Vref- GND
5 Vref+ Vdd
6 E0 O A (Light sleep) Alarm Clock PIC
7 E1 O B (Fall Asleep) Alarm Clock PIC
Table G.2: Signal Processing I/O – mapping of I/O ports for the signal processing PIC
36
Pin I/ To/Fro
# Label O Description m Part Label
2 A0 I A
3 A1 I B
4 A2 I ALARM_OFF four pos. switch
5 A3 ALARM_ON four pos. switch
6 A4 I SET_TIME four pos. switch
7 A5 I SET_ALARM four pos. switch
33 B0 O MIN – ones digit 7-Seg Decoder 1 A
34 B1 O MIN – ones digit 7-Seg Decoder 1 B
35 B2 O MIN – ones digit 7-Seg Decoder 1 C
36 B3 O MIN – ones digit 7-Seg Decoder 1 D
37 B4 O MIN – tens digit 7-Seg Decoder 2 A
38 B5 O MIN – tens digit 7-Seg Decoder 2 B
39 B6 O MIN – tens digit 7-Seg Decoder 2 C
40 B7 O MIN – tens digit 7-Seg Decoder 2 D
15 C0 O HR – ones digit 7-Seg Decoder 3 A
16 C1 O HR – ones digit 7-Seg Decoder 3 B
17 C2 O HR – ones digit 7-Seg Decoder 3 C
18 C3 O HR – ones digit 7-Seg Decoder 3 D
23 C4 O HR – tens digit 7-Seg Decoder 4 A
24 C5 O HR – tens digit 7-Seg Decoder 4 B
25 C6 O HR – tens digit 7-Seg Decoder 4 C
26 C7 O HR – tens digit 7-Seg Decoder 4 D
19 D0 I Appl. 1 - Turn off at night switch
20 D1 I Appl. 1 - Turn on in morn. switch
21 D2 I Appl. 2 - Turn off at night switch
22 D3 I Appl. 2 - Turn on in morn. switch
27 D4 I Change HR push button
28 D5 I Change MIN push button
13 OSC1 crystal oscillator
14 OSC2 crystal osc. (not used)
8 E0 O Appliance 1 Relay Relay 1
9 E1 O Appliance 2 Relay Relay 2
10 E2 O BUZZER piezo buzzer
Table G.3: Alarm Clock I/O – mapping of I/O ports for the Alarm clock PIC
37
BCD inputs segment outputs display
D C B A a b c d e f g
0 0 0 0 1 1 1 1 1 1 0
0 0 0 1 0 1 1 0 0 0 0
0 0 1 0 1 1 0 1 1 0 1
0 0 1 1 1 1 1 1 0 0 1
0 1 0 0 0 1 1 0 0 1 1
0 1 0 1 1 0 1 1 0 1 1
0 1 1 0 0 0 1 1 1 1 1
0 1 1 1 1 1 1 0 0 0 0
1 0 0 0 1 1 1 1 1 1 1
1 0 0 1 1 1 1 0 0 1 1
Table G.4: Hex Displays - Decoding table for 7-segment HEX displays
38
APPENDIX H – PIC MICROCONTROLLER CODE
//////////////////////////////////////////////////////////////////////
//// ADSignalAnalysis.C ////
//// ////
//// This program calculates the frequency of an analog signal ////
//// using zero-crossing analysis of A/D samples. ////
//// This version uses 8 bit ADC. ////
//// ////
//// I/O: ////
//// A0 input analog signal ////
//// C0 output bit A ////
//// C1 output bit B ////
//// ////
//// ////
//// Written February 2006 ////
//// by Jonathan Santos ////
//// partners: Kevin Lee, Daniel Kim ////
//// ////
//////////////////////////////////////////////////////////////////////
#include <16F877A.h>
#use delay(clock=4000000)
#include "Include\ADSignalAnalysis.h"
// function declarations
void initTimers(void);
void initADC(void);
int16 initRunningAvg(void);
#pragma zero_ram
void main( void)
{
// declare variables
int16 zero_crossings;
int16 newADC, oldADC;
int16 runningAVG;
int16 frequency;
int16 time_interval;
int8 signalB;
int8 currentState;
int8 oldState;
39
// initialize variables
zero_crossings = 0;
newADC = 0;
oldADC = 0;
runningAVG = 0;
frequency = 0;
time_interval = 0;
signalB = 0;
currentState = DEFAULTSTATE;
oldState = DEFAULTSTATE;
output_low(SIGA);
output_low(SIGB);
while(FOREVER)
{
// initialize running average
runningAVG = initRunningAVG();
oldADC = read_adc();
delay_ms(5);
delay_ms(5);
time_interval ++;
oldADC = newADC;
}
40
// now send the output signals
if(currentState == ALPHASTATE)
output_high(SIGA);
else
output_low(SIGA);
}
}
int16 initRunningAvg(void)
{
int16 j, samples;
int16 avg;
int32 sum;
sum = 0;
for(j = 0; j < 256; j++)
{
samples = Read_ADC();
delay_ms(5);
sum = sum + samples;
}
return (avg);
}
41
//////////////////////////////////////////////////////////////////////
//// ADSignalAnalysis.h ////
//// ////
//// Function declarations used in ADSignalAnalysis.c ////
//// Constants and definitions used in ADSignalAnalysis.c ////
//// ////
//// Written February 2006 ////
//// by Jonathan Santos ////
//// partners: Kevin Lee, Daniel Kim ////
//// ////
//////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//// constants and definitions
// A/D + Buttons
#define MY_TRISA 0b11111111 // PinA[7:0] I/O all inputs
#define MY_TRISC 0b00000000 // PinC[7:0] I/O all outputs
#define ALPHAWAVES_L 9
#define ALPHAWAVES_H 13
#define BETAWAVES_L 14
#define BETAWAVES_H 30
#define DELTAWAVES_L 1
#define DELTAWAVES_H 3
#define THETAWAVES_L 4
#define THETAWAVES_H 8
#define FOREVER 1
#define TIMEINTERVAL 1 // time interval for data collection
#define DEFAULTSTATE 0
#define ALPHASTATE 1
#define BETASTATE 2
#define DEEPSTATE 3
42
/////////////////////////////////////////////////////////////
//
// AlarmClock.c
//
// Implements an alarm clock. Alarm will only sound
// based on certain conditions of inputs A and B.
//
// Written March 2006 by Jonathan Santos
// modified from Group18 Fall 2004, "Smart Alarm Clock"
//
// Partners: Kevin Lee, Daniel Kim
//
// first version: March 25, 2006 - program structure done
// second version: March 28, 2006 - setting time/alarm and keeping time working
// third version: April 1, 2006 - changed method of timekeeping, all
outputs // signals done and working
// final version: ...
//
/////////////////////////////////////////////////////////////
#include <16F877A.h>
#device *=16 ADC=10 // Use 16-bit pointers, use 8-bit ADC
#fuses HS // You may or may not want some of these ....
#fuses NOWDT
#fuses NOPROTECT
#fuses NOLVP
#fuses NODEBUG
#fuses NOPUT
#fuses NOBROWNOUT
#use delay(clock=4000000) //4MHz
// Global variables
int16 timeMin = 10;
int16 timeHour = 10;
int16 alarmMin = 0;
int16 alarmHour = 7;
//int8 timeMin;
//int8 timeHour;
//int8 alarmMin;
//int8 alarmHour;
//int8 testint = 0;
//int8 testint2 = 0;
int8 pina4;
int8 pina5;
int8 pina0;
int8 pina3;
int8 pina1;
int8 pina2;
43
int8 pind1;
int8 pind0;
int8 pind2;
int8 pind3;
int8 pind4;
int8 pind5;
int8 timerCount1 = 0;
int8 increment = 0;
int16 counter = 0;
int8 tmin0, tmin1, thour0, thour1; // time variables
int8 amin0, amin1, ahour0, ahour1; // alarm variables
#include "Include\display.c"
// function declarations
void initTimers( void);
void timer1ISR( void);
void set_time( void);
void set_alarm(void);
void update_time( void);
timerCount1 ++;
/*
if(testint2 == 0){
output_high(PIN_E0);
testint2 = 1;
}
else{
44
output_low(PIN_E0);
testint2 = 0;
}
*/
}
/*
if(testint == 0){
output_high(PIN_E1);
testint = 1;
}
else{
output_low(PIN_E1);
testint = 0;
}
*/
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
}
void set_time(void)
{
while(pina4) // do not leave while we are setting the real time
{
// allow time to increment also
if(increment == 1){
timeMin ++;
increment = 0;
}
pina4 = input(PIN_A4);
pind5 = input(PIN_D5);
pind4 = input(PIN_D4);
// counter = 0;
// while(counter < DELAY_CHANGE_TIME)
// counter ++;
update_time();
display(tmin0, tmin1, thour0, thour1);
}
}
void set_alarm(void)
{
while(pina5) // do not leave while we are setting the alarm time
{
// allow time to be incremented
if(increment == 1){
timeMin ++;
increment = 0;
}
pina5 = input(PIN_A5);
pind4 = input(PIN_D4);
pind5 = input(PIN_D5);
// counter = 0;
// while(counter < DELAY_CHANGE_TIME)
// counter ++;
if(pind4 == 1){
alarmHour ++;
counter = 0;
while(counter < DELAY_CHANGE_TIME)
counter ++;
// disable_interrupts(GLOBAL);
46
// delay_ms(250); // delay for 0.25 seconds
// enable_interrupts(GLOBAL);
}
update_time();
display(amin0, amin1, ahour0, ahour1);
}
}
void update_time(void)
{
// set time minute display
if(timeMin < 10){ tmin1 = 0; tmin0 = timeMin; }
else if(timeMin < 20){ tmin1 = 1; tmin0 = timeMin - 10;}
else if(timeMin < 30){ tmin1 = 2; tmin0 = timeMin - 20;}
else if(timeMin < 40){ tmin1 = 3; tmin0 = timeMin - 30;}
else if(timeMin < 50){ tmin1 = 4; tmin0 = timeMin - 40;}
else { tmin1 = 5; tmin0 = timeMin - 50;}
// ============================================================
// MAIN SUBROUTINE
//
// Main subroutine controls the entire program. Set clock time
// and alarm time. Set off buzzer.
#pragma zero_ram
void main()
{
disable_interrupts(GLOBAL); // We don't want to be interrupted yet
disable_interrupts(INT_TIMER1);
delay_ms(500); // wait for voltages to stablize
// configure I/O
setup_adc(ADC_OFF);
setup_adc_ports(NO_ANALOGS); // set portA as all digital
set_tris_a(0b11111111); // all inputs
set_tris_b(0b00000000); // all outputs
set_tris_c(0b00000000); // all outputs
set_tris_d(0b11111111); // all inputs
47
set_tris_e(0b00000000); // all outputs
// port_b = 0;
// port_c = 0;
// port_e = 0;
// timeMin = 10;
// timeHour = 10;
// alarmMin = 0;
// alarmHour = 7;
output_low(PIN_E2); // buzzer off by default
output_high(PIN_E0); // relays on by default
output_high(PIN_E1);
delay_ms(50);
initTimers(); // This is where the interrupts are enabled again
// counter = 0;
// while(counter < DELAY_CHANGE_TIME)
// counter ++;
//////////////////////////////////////
OUTPUTS /////////////////////////////////////////
// set buzzer and relay outputs depending on input signals and time
else
{
output_low(PIN_E2);
output_high(PIN_E0);
output_high(PIN_E1);
}
49
} // end while loop
} // end main
/////////////////////////////////////////////////////////////
//
// display.c
//
// Displays functions for the alarm clock.
//
// Written March 2006 by Jonathan Santos
// modified from Group18 Fall 2004, "Smart Alarm Clock"
//
// Partners: Kevin Lee, Daniel Kim
//
/////////////////////////////////////////////////////////////
int8 port_b;
int8 port_c;
int8 port_e;
//=================================================================================
// MAPPING FOR DECODER ON ROUTE TO 7 SEG LED DISPLAY
//=================================================================================
/*display_mins0, display_mins1, display_mins2, display_mins3, display_mins4.
display_mins5,
display_hrs0, display_hrs1, display_hrs2 retrieves character mapping for
corresponding digit.
It then sends that mapping to corresponding LED decoder through port b. If digit
is not between 0 and 9,
nothing will be outputted (serves as precautionary step).
Calls: none
Input: int8 c - digit to be mapped
Output: none
*/
// function declarations
void display_mins0(int8 c);
void display_mins1(int8 c);
void display_mins2(int8 c);
void display_mins3(int8 c);
void display_mins4(int8 c);
void display_mins5(int8 c);
void display_hrs0(int8 c);
void display_hrs1(int8 c);
void display_hrs2(int8 c);
50
void display(int8 minLSB, int8 minMSB, int8 hrLSB, int8 hrMSB);
// function definitions
void display_mins0(int8 c) {
if((c>9)||(c<0))
port_b=0x00;
else
port_b=LED_MAP0[c];
}
void display_mins1(int8 c) {
if((c>9)||(c<0))
port_b=0x00;
else
port_b=LED_MAP1[c];
}
void display_mins2(int8 c) {
if((c>9)||(c<0))
port_b=0x00;
else
port_b=LED_MAP2[c];
}
void display_mins3(int8 c) {
if((c>9)||(c<0))
port_b=0x00;
else
port_b=LED_MAP3[c];
}
void display_mins4(int8 c) {
if((c>9)||(c<0))
port_b=0x00;
else
port_b=LED_MAP4[c];
}
void display_mins5(int8 c) {
if((c>9)||(c<0))
port_b=0x00;
else
port_b=LED_MAP5[c];
}
void display_hrs0(int8 c) {
if((c>9)||(c<0))
port_c=0x00;
else
port_c=LED_MAP0[c];
}
void display_hrs1(int8 c) {
if((c>9)||(c<0))
port_c=0x00;
else
port_c=LED_MAP1[c];
}
void display_hrs2(int8 c) {
if((c>9)||(c<0))
port_c=0x00;
51
else
port_c=LED_MAP2[c];
}
//=================================================================================
/*
Display subroutine gets character mapping for each digit
Calls: display_mins0, display_mins1, display_mins3, display_mins4, display_mins5
display_hrs0, display_hrs1, display_hrs2
Inputs: minsLSB - least sig bit for minutes display
minsMSB - most sig bit for minutes display
hrLSB - least sig bit for hour display
hrMSB - most sig bit for hour display
OutputsL none
*/
if(hrMSB==0){
display_hrs0(hrLSB);
}
if(hrMSB==1){
display_hrs1(hrLSB);
}
if (hrMSB==2){
display_hrs2(hrLSB);
}
output_b(port_b);
output_c(port_c);
52