You are on page 1of 37

APPENDIX A – BLOCK DIAGRAMS

Alarm Clock Module

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

Update Average Get A/D Samples

Determine
frequency and set
old_State =
current_State

Is frequency
No between 9
and 13 Hz? Yes

Is frequency Set current_State


between 13 = Alpha and
No Yes
and 50 Hz? output A = 1

Set current_State Set current_State


Yes
= Default = Beta

Is old_State
No
= Beta? Yes

Output B = 1

Figure C.1: Flow Chart1 - Flow chart of signal processing pic.

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?

Figure C.3: Flow Chart3 - Flow chart for buzzer.

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

Is signal B Is signal A Is signal A


No No
= 1? = 1? = 1?
Yes

Yes

Is signal B Is signal B
No
= 1? = 1?

No

No
No

Yes

Yes

Turn off relay Turn on relay

The flowchart implements the following pseudocode conditions:

if (Awake = 0 and Sleeping = 0) turn off relay;


if (Awake = 0 and Sleeping = 1 and signal B = 0) turn off relay;
if (Awake = 0 and Sleeping = 1 and signal B = 1) turn on relay;
if (Awake = 1 and Sleeping = 0 and signal A = 0 and Alarm_EN = 1) turn on relay;
if (Awake = 1 and Sleeping = 0 and signal A = 1 and Alarm_EN = 1) turn off relay;
if (Awake = 1 and Sleeping = 1 and signal A = 0 and signal B = 0 and Alarm_EN = 1) turn off relay;
if (Awake = 1 and Sleeping = 1 and signal A = 0 and signal B = 1 and Alarm_EN = 1) turn on relay;
if (Awake = 1 and Sleeping = 1 and signal A = 1 and signal B = 0 and Alarm_EN = 1) turn off relay;
if (Awake = 1 and Sleeping = 1 and signal A = 1 and signal B = 1 and Alarm_EN = 1) turn on relay;

Figure C.4: Flow Chart4 - Flow chart for relays.

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

Figure C.5: Flow Chart5 - Flow chart for interrupt 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

Figure D.11: Signal Processing PIC results - Actual 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.

HR & MIN Increment


4-position switch Push Buttons

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.

Part # Description Qty. Price Total


N/A Unomedical Ag/AgCl Electrodes 3 $0.19 $0.57
N/A PCB 1 3.29 3.29
AD622AN Instrumentation Amplifier 2 $5.15 $10.30
MC3403 Quad-Op Amp 1 $0.33 $0.33
Miscellaneous Parts 1 5.00 5.00
* 33 kΩ Resistor 4 - -
* 3.3 MΩ Resistor 4 - -
* 12 Ω Resistor 1 - -
* 39 Ω Resistor 1 - -
* 30 kΩ Resistor 1 - -
* 0.1 µF Capacitor 4 - -
* 3 Conductor Shielded Cable 2 - -
* Alligator clips 3 - -
* Banana Jack Plugs 4 - -
--------------
TOTAL $19.16
* Covered in Miscellaneous Costs

Table F.1: EEG - Parts and Cost for EEG Module

Part # Description Qty. Price Total


PIC16F877A PIC Microcontroller 1 $4.76 $4.76
FOX F1100E 4 MHz Crystal Oscillator 1 $1.58 $1.58
1N5822 Schottky Diode 1 $0.32 $0.32
1N4734 Zener Diode 1 $0.11 $0.11
N/A PCB 1 $3.29 $3.29
N/A Miscellaneous Parts 1
* 47kΩ Resistor 1
* 1-amp Fuse 1
--------------
TOTAL $10.06
* Covered in Miscellaneous Costs

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

Part # Description Qty. Price Total


N/A Aluminum Box 1 $6.99 $6.99
N/A Plexiglass cover 1 $3.99 $3.99
N/A Banana Jack Sockets 8 $1.20 $9.60
 N/A Wall Outlet   1  $2.99 $2.99
------------
  TOTAL     $23.57

Table F.4: Miscellaneous - Miscellaneous Parts and Cost

35
APPENDIX G – MISCELLANEOUS

Frequency (Hz) Brain Wave Sleep Stage


0.5 – 3 Delta Deep Sleep
4–7 Theta Drowsy Sleep
8 – 13 Alpha Light Sleep
14 + Beta Awake, REM

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>

#device *=16 ADC=10 // Use 16-bit pointers, use 10-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)

// These require use of Set_Tris_x()


#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
// End Preprocessor Directives

#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;

disable_interrupts(GLOBAL); // disable global interrupts


delay_ms(500); // wait for voltages to stablize
Set_Tris_A(MY_TRISA); // Pin A's I/O
Set_Tris_C(MY_TRISC); // Pin C's I/O
initADC();

output_low(SIGA);
output_low(SIGB);

while(FOREVER)
{
// initialize running average
runningAVG = initRunningAVG();

oldADC = read_adc();
delay_ms(5);

// while(time_interval < 1000)


while(time_interval < 200*TIMEINTERVAL)
{
newADC = read_adc();

if(((oldADC < runningAVG) && (newADC > runningAVG)) ||


((oldADC > runningAVG) && (newADC < runningAVG)))
zero_crossings ++;

delay_ms(5);
time_interval ++;
oldADC = newADC;
}

frequency = (zero_crossings) >> 1;


time_interval = 0;
zero_crossings = 0;
// oldState = currentState;

// find the current state (alert or sleeping?) of the user


if((frequency > (ALPHAWAVES_L)*TIMEINTERVAL-1) && (frequency <
ALPHAWAVES_H*TIMEINTERVAL-1)) // in alpha stage
currentState = ALPHASTATE;
else if(frequency > (BETAWAVES_L)*TIMEINTERVAL-1) // in beta stage
{
currentState = BETASTATE;
oldState = BETASTATE;
}
else if((frequency < (ALPHAWAVES_L)*TIMEINTERVAL-1))
currentState = DEEPSTATE;
else
currentState = DEFAULTSTATE;

40
// now send the output signals
if(currentState == ALPHASTATE)
output_high(SIGA);
else
output_low(SIGA);

if(((currentState == DEEPSTATE)) && (oldState == BETASTATE) && (signalB ==


0))
{
output_high(SIGB);
signalB = 1;
}
else if(signalB == 1)
output_high(SIGB);
else
output_low(SIGB);

}
}

// Purpose: Initializes ADC


// Precondition: None
// Postcondition: ADC is configured
void initADC(void)
{
setup_adc_ports(AN0); // A0, Vrefh = Vdd, Vrefl = gnd
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel( 0 );
delay_us(10);
}

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;
}

avg = sum >> 8;

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 SIGA PIN_C0


#define SIGB PIN_C1 // PinC0 signals that the person should wake up

#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

// These require use of Set_Tris_x()


#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)

#define DELAY_CHANGE_TIME 20000

// 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);

// Purpose: Initializes timer interrupts


// Precondition: None
// Postcondition: Timers and interrupts are enabled
void initTimers(void)
{
setup_timer_1( T1_INTERNAL | T1_DIV_BY_8 ); // timer1 will increment every
(32/4000000) = 8 microseconds
set_timer1(3036); // It will
overflow every 0.5 seconds
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
timerCount1 = 0;
}

// Purpose: Timer1 ISR


// Precondition: initTimers called
// Postcondition: Timer1 counter updated
// This routine is called every 0.5 seconds
#INT_TIMER1
void Timer1ISR(void)
{
disable_interrupts(GLOBAL);
disable_interrupts(INT_TIMER1);
set_timer1(3036);

timerCount1 ++;

// if(timerCount1 == 114) // 59.7679 seconds have passed


// set_timer1(36520); // compensate for overcounting

if(timerCount1 > 119)


{
timerCount1 = 0;
increment = 1;

/*
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;
}

if(timeMin > 59){


timeMin = 0;
timeHour ++;
}

if(timeHour > 23)


timeHour = 0;

pina4 = input(PIN_A4);
pind5 = input(PIN_D5);
pind4 = input(PIN_D4);
// counter = 0;
// while(counter < DELAY_CHANGE_TIME)
// counter ++;

// increment minute if button is pressed


if(pind5 == 1){
timeMin ++;
timerCount1 = 0;
set_timer1(3036);
counter = 0;
while(counter < DELAY_CHANGE_TIME)
counter ++;
// disable_interrupts(GLOBAL);
// delay_ms(250); // delay for 0.25 seconds
// enable_interrupts(GLOBAL);
}

// increment hour if button is pressed


if(pind4 == 1){
timeHour ++;
timerCount1 = 0;
set_timer1(3036);
45
counter = 0;
while(counter < DELAY_CHANGE_TIME)
counter ++;
// disable_interrupts(GLOBAL);
// delay_ms(250); // delay for 0.25 seconds
// enable_interrupts(GLOBAL);
}

// check for time wraparound


if(timeMin > 59)
timeMin = 0;

if(timeHour > 23)


timeHour = 0;

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;
}

if(timeMin > 59){


timeMin = 0;
timeHour ++;
}

if(timeHour > 23)


timeHour = 0;

pina5 = input(PIN_A5);
pind4 = input(PIN_D4);
pind5 = input(PIN_D5);
// counter = 0;
// while(counter < DELAY_CHANGE_TIME)
// counter ++;

// increment alarm if button is pressed


if(pind5 == 1){
alarmMin ++;
counter = 0;
while(counter < DELAY_CHANGE_TIME)
counter ++;
// disable_interrupts(GLOBAL);
// delay_ms(250); // delay for 0.25 seconds
// enable_interrupts(GLOBAL);
}

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);
}

// check for time wraparound


if(alarmMin > 59)
alarmMin = 0;

if(alarmHour > 23)


alarmHour = 0;

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;}

// set alarm minute display


if(alarmMin < 10){ amin1 = 0; amin0 = alarmMin; }
else if(alarmMin < 20){ amin1 = 1; amin0 = alarmMin - 10;}
else if(alarmMin < 30){ amin1 = 2; amin0 = alarmMin - 20;}
else if(alarmMin < 40){ amin1 = 3; amin0 = alarmMin - 30;}
else if(alarmMin < 50){ amin1 = 4; amin0 = alarmMin - 40;}
else { amin1 = 5; amin0 = alarmMin - 50;}

if(timeHour < 10){ thour1 = 0; thour0 = timeHour; }


else if(timeHour < 20){ thour1 = 1; thour0 = timeHour - 10;}
else { thour1 = 2; thour0 = timeHour - 20;}

if(alarmHour < 10){ ahour1 = 0; ahour0 = alarmHour; }


else if(alarmHour < 20){ ahour1 = 1; ahour0 = alarmHour - 10;}
else { ahour1 = 2; ahour0 = alarmHour - 20;}
}

// ============================================================
// 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

output_low(PIN_E2); // buzzer off by default


output_high(PIN_E0); // relays on by default
output_high(PIN_E1);

// start main loop


while(TRUE)
{
pina5 = input(PIN_A5);
pina4 = input(PIN_A4);
pina3 = input(PIN_A3);
pina0 = input(PIN_A0);
pina1 = input(PIN_A1);
pina2 = input(PIN_A2);
pind1 = input(PIN_D1);
pind0 = input(PIN_D0);
pind2 = input(PIN_D2);
pind3 = input(PIN_D3);

// first check if real time has to be incremented


if(increment == 1){
timeMin ++;
increment = 0;
}

if(timeMin > 59){


timeMin = 0;
timeHour ++;
}

if(timeHour > 23)


timeHour = 0;

// while(!pina2 && !pina3 && !pina4 && !pina5);


counter = 0;
while(counter < 5000)
counter ++;

// counter = 0;
// while(counter < DELAY_CHANGE_TIME)
// counter ++;

// display the real time or alarm time


// if(input(PIN_A5) == 1) // call set_alarm routine
if(pina5 == 1)
set_alarm();
// else if(input(PIN_A4) == 1) // call set_alarm routine
48
// else if(pina4 == 1)
if(pina4 == 1)
set_time();
// else{
// display the real time and update it too
update_time();
display(tmin0, tmin1, thour0, thour1);
// }

//////////////////////////////////////
OUTPUTS /////////////////////////////////////////
// set buzzer and relay outputs depending on input signals and time

if( pina3 && (timeHour*60+timeMin == alarmHour*60+alarmMin) ) // hard


time buzzer
{
output_high(PIN_E2);
if(pind1)
output_high(PIN_E0);
else
output_low(PIN_E0);
if(pind3)
output_high(PIN_E1);
else
output_low(PIN_E1);
}
else if( pina3 && pina0 &&
(timeHour*60+timeMin > alarmHour*60+alarmMin-90) &&
(timeHour*60+timeMin < alarmHour*60+alarmMin) ) //
give 90 minutes for light sleep stage
{
output_high(PIN_E2);
if(pind1)
output_high(PIN_E0);
else
output_low(PIN_E0);
if(pind3)
output_high(PIN_E1);
else
output_low(PIN_E1);
}
else if( pina3 && pina1 ) // if alarm is set and user has fallen
asleep
{
if(pind0)
output_low(PIN_E0);
else
output_high(PIN_E0);
if(pind2)
output_low(PIN_E1);
else
output_high(PIN_E1);
}

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

int8 CONST LED_MAP0[10] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}; //0..


int8 CONST LED_MAP1[10] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19}; //1..
int8 CONST LED_MAP2[10] = {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29}; //2..
int8 CONST LED_MAP3[10] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //3..
int8 CONST LED_MAP4[10] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49}; //4..
int8 CONST LED_MAP5[10] = {0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59}; //5..

//=================================================================================
/*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
*/

void display(int8 minLSB, int8 minMSB, int8 hrLSB, int8 hrMSB)


{

//tie cathodes of LED to gnd


//deal with minutes first
if(minMSB==0){ //look at MSB of minutes
display_mins0(minLSB);
}
if(minMSB==1){
display_mins1(minLSB);
}
if(minMSB==2){
display_mins2(minLSB);
}
if(minMSB==3){
display_mins3(minLSB);
}
if(minMSB==4){
display_mins4(minLSB);
}
if(minMSB==5){
display_mins5(minLSB);
}

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

You might also like