Wireless Home Automation - Southern Polytechnic State ...

fiercebunΗλεκτρονική - Συσκευές

2 Νοε 2013 (πριν από 3 χρόνια και 8 μήνες)

108 εμφανίσεις

Web Home Automation through Bluetooth


Overview


This project aims to allow the home owner to get information about home temperatures and control lighting
entirely
through a web
-
based interface. On one end, a

home PC is set to r
un an ASP.NET web server that
sends
commands to the 8051 microcontroller via a Bluetooth Serial Port Profile (SPP). On the other end, the
microcontroller interfaces with a P
hil
ips BGB203 Bluetooth module
using UART. The microcontroller calculates
room temp
erature through the built
-
in 12
-
bit ADC using a thermistor, and also controls the status of various
household lights. Commands from the PC can tell the microcontroller to turn on or off lights and report the state of
any light or the room temperature.

Equi
pment



(1) Silicon Labs C8051F005SDK Evaluation Board with USB Debug Adapter



(1) SparkFun WRL
-
08474 Bluetooth SMD Module based on Philips BGB203



(1) SparkFun WRL
-
00150 Bluetooth USB Module



(1) B57891M0152J000 Leaded NTC thermistor



(3) 4.7kOhm resistors

Sche
matic



Building the Circuit


There are a couple of different Bluetooth modules available for purchase. The WRL
-
08474 used here is a
surface mount device, so you will need a breakout board or some other way to connect the module to your
microcontroller.

1.

Connect pin TX on the module to RX on the microcontroller and RX to TX. This is the basic
setup for
simple serial communication. In this microcontroller configuration, the UART TX is assigned to pin
P0.0 and RX is assigned to pin P0.1.

2.

On the module, conne
ct RTS to CTS pin. This bypasses any flow control setting on the Bluetooth
module.

3.

Build a Wheatstone bridge circuit with the 4.7kOhm resistors and the thermistor. The voltage to be
measured should be connected to AIO0 and AIO1 on the green analog I/O bloc
k.

4.

Set jumpers on the J6 connecter such that AIO0
-
1 is connected to the microcontroller AIN0
-
1.

Software


This device requires use of the microcontroller’s UART and ADC subsystems. The software needs to
initialize these systems and also setup the Bluetooth

module through the UART interface using the BGB203’s AT
command set.


First we will take a look at the ADC initialization. Set the BIASE bit to enable the ADC. The C8051F005
already contains an internal 1.2V voltage reference

which we can use by setting t
he REFBE bit. The internal
reference

goes through a gain 2 buffer amplifier for an input range from
-
2.43V to 2.43V.

Set ADC conversion to
start upon write of 1 to the ADBUSY bit in the ADC0CN control register.
Remember to enable the ADC end
-
of
-
conversion
interrupt, bit 1 on the EIE2 register.


Periodic readings of the thermistor are triggered by Timer 3 interrupt, which sets ADBUSY. We initialize
the reload value such that an interrupt is triggered approximately every second. The Timer 3 ISR simply clears
the
interrupt flag and sets ADBUSY.


To enable the UART,
the CrossBar needs to be configured so that TX and RX are assigned to port I/O pins.
The exact pins depend on what other functionality is enabled, but in this setup TX is assigned to P0.0 and RX to
P
0.1.

This is done by setting the UARTEN bit in the XBR0 register. Additionally, the TX pin needs to be set to
push
-
pull in the PRT0CF register. The RX pin is automatically set to open drain when the UART is enabled
regardless of what is in PRT0CF.


Next we

need to set the baud rate. The baud clock in this cas
e is derived from Timer 2 running in Baud
Clock Generator mode. The Bluetooth module can communicate at most standard baud rates. However, the internal
oscillator on the
C8051F005 runs at a speed of 16
M
Hz, which is not cleanly divisible into these standard speeds.
You can purchase external oscillators such as those that run at 11.059MHz in order to access a wider range of
communication speeds.


We can calculate the baud rate with the following equation:

Baud rate
= (1/32
)*(clock speed)*(1/
(2^16
-
reload value))


In order to ensure successful com
munication, try to stay within 3
% error in baud rate. Table _ gives a list of
usable baud rates and reload values for the internal oscillator versus that for an 11.0
59
2
MHz external oscillator.

Standard Rate

16
MHz reload

16
MHz error

11.059
2
MHz
reload

11.059MHz error

115200

0xFFF
C

8.51
%

0xFFF
D

0%

57600

0xFFF
7

-
3.55
%

0xFFF
A

0%

38400

0xFFF
3

0.16
%

0xFFF
7

0%

19200

0xFF
E6

0.16
%

0xFF
E
E

0%

9600

0xFF
CC

0.16
%

0xFFD
C

0%



A
s you can see, the 11.0592MHz clock allows for faster UART communication even though it is slower
than the internal oscillator. Also, the internal oscillator does not run at exactly 16MHz, so you may need to try a
couple of reload values b
efore hitting on
one that works for your microcontroller.


Lastly, we need to implement the UART ISR called when either RI or TI flags are set. The RI is the receive
interrupt set when the microcontroller
has finished receiving a byte of data in the SBUF register. The TI i
s the
transmit interrupt which is set when a byte of data has finished transmitting. Since RI and TI both trigger the same
interrupt, the ISR must handle both cases.


On a receive interrupt, the software clears the RI flag and attempts to place the receive
d byte into a buffer
array. If the buffer is full, the data is simply lost.


In case of a transmit interrupt, the software clears the TI flag

and checks is there is more data in the
transmit buffer. If it is empty, the software clears TXBUSY, a variable th
at keeps track of whether the
microcontroller is in a transmit sequence, and exits the ISR. If there is more data, the next byte in the buffer is
written to SBUF which automatically initiates a transmission.

Interfacing the BGB203


The Bluetooth module is
controlled by sending commands through the UART interface.

By default from
the Philips manufacturer, the UART is configured for a baud rate of 115200, 8 data bits, no parity, 1 stop bit and no
flow control. However, the module as received from SparkFun wil
l have default baud rate of 9600 instead.

If you
remember, the internal oscillator on the development board could not hit a 115200 baud rate, so this is ideal.

All commands
must begin with the

“AT”

prefix
, except for the escape sequence. Also, commands mus
t end

with a carriage return character, hexadecimal 0x0D. The standard command sequence is shown below.

<Prefix><Command><CR>


The escape sequence is used to tell the module to enter command mode from data mode.
When in

data
mode, the module sends any inpu
t from the microcontroller to the PC over Bluetooth.

The default sequence is
“+++”.

The module may also fall back into command mode if it loses its Bluetooth SPP connection with the PC.


Before the module is ready to communicate with the PC, we need to iss
ue a couple of configuration
commands.

+++

AT&F


Reset configuration to default settings stored in on
-
chip
F
lash.

AT+BTLNM=”SPSU
-
BT”


Change Bluetooth module local name to “SPSU
-
BT”

AT+BTAUT=1, 0


Sets automatic connection mode. The module will not leave d
ata mode upon lost connection

AT+BTURT=9600, 8, 0, 1, 0


Sets UART baud rate to 9600

AT+BTSEC=0


Disable security mode such that pairing is unnecessary

AT+BTFLS


Stores current configuration into Flash

AT+BTSRV=2


Starts the Bluetooth SPP server


At this p
oint, you are ready to communicate with the PC from the microcontroller. Once the PC establishes
an SPP connection, any data sent from the 8051 will show up on a virtual serial port on the PC, and vice versa.

Measuring Ambient Room Temperature


The B57891M
0152J000 thermistor is a negative temperature coefficient device, meaning its resistance gets
smaller

as the temperature increases. Thermistors are accurate and stable over time, but they are highly nonlinear.
Instead of mathematically calculating the temp
erature, the software will use an 8
-
point lookup table based off the
thermistor datasheet and estimate intermediate values using linear interpolation.


The thermistor is placed in a Wheatstone bridge with three 4.7kOhm resistors. By measuring the voltage
d
ifference between both arms, we can accurately determine small changes in the thermistor’s resistance. Another
advantage of the Wheatstone bridge is that the voltage difference is a relative measurement, meaning fluctuations in
supply voltage will not

affe
ct the voltage measurement as much.


The 12
-
bit ADC in the C8051F005 converts the potential AIN0


AIN1 into a digital value based off the
internal
2.4V
voltage reference.
Thus in

the differential input mode, the range of the ADC is from
-
2.4V
to
2.4V
.
We
can use Kirchoff’s circuit laws to determine the resistance of the thermistor.

V=Vcc/2
-
Vcc*R/(4.7k+R) V
-
Vcc/2=Vcc*R/(4.7k+R) (V
-
Vcc/2)*4.7k+(V
-
Vcc/2)*R=Vcc*R

V
-
Vcc/2)*4.7k=R(3*Vcc/2
-
V)

R=
4.7k*(V
-
Vcc/2)/(Vcc*3/2
-
V)


By using the above equation, we

can bui
ld a lookup table from
the data sheet to relate voltage to
temperature.

Temperature

Resistance

Voltage

0.0

4300

0.0569

5.0

3436

0.240

10.0

2766

0.411

15.0

2238

0.569

20.0

1823

0.711

25.0

1500

0.836

30.0

1245

0.944

35.0

1030

1.04

40.0

856.5

1.13



The ADC samples an unknown input by using a small capacitor. It continuously tracks the voltage level of
the input. When it is ready to perform a conversion, the ADC cuts off connection to the input and holds the charge
that represents the analog level. T
his is commonly referred to as a sample and hold circuit.

The ADC uses a technique called successive approximation. It utilizes a 12
-
bit DAC and a comparator. The
ADC gets clocked 12 times by the system clock. Each cycle determines the value of one bit, st
arting with the most
significant. For example, on the first clock cycle, the most significant bit of the DAC is set and its voltage compared
to the input. If the voltage of the input is higher than the DAC output, then we know the most significant bit shou
ld
be one. Otherwise, that bit should be 0.


An ADC interrupt is triggered at the end of each conversion. The ISR takes the new reading and adds it to
an accumulator variable.
Every 8 readings, the accumulator is averaged and the averaged value stored in t
he global
variable ‘result’. Such an averaging filter helps reduce the effect of noise and produce a more stable temperature
reading.

Connecting to the PC


Install the BlueSoleil software that comes with the Bluetooth USB module.
Plug in the Bluetooth modu
le
and open the BlueSoleil main window by double clicking on the tray icon.



Next, click on the orange orb to search for Bluetooth devices. Don’t forget to have your microcontroller
Bluetooth module powered on at this point! Note that the SparkFun module

might show up as only a device address
at first. Wait until the BlueSoleil program finishes its search and right click on the module, then select Refresh
Services.

After that, right click again and select Connect
-
>Bluetooth Serial Port Service.



The fir
st time you connect to the SPP service, a Quick Connect dialogue will appear. Write down or
remember which COM port it is connected to. If at any time you forget, you can find out which port the device is
assigned by going to Tools
-
>Configuration
-
>Quick Co
nnect…


Now you can open up any terminal program and send data to the microcontroller by connecting to that
COM port with the same baud rate and data settings as the Bluetooth module on the device.

Web Interface using ASP.NET


The final step
is to build a
web interface to allow remote control by the home owner from anywhere in the
world. This is done using ASP.NET to build a dynamic web page that can interact with the virtual serial port on the
web server.



The website organizes and shows the user the sta
tus of every component connected to the microcontroller.
The two update buttons update the status variables

by querying the 8051 over the Bluetooth. The microcontroller
processes query strings and returns the relevant data.


Similarly, the website uses a f
orm interface to allow the user to send command strings over Bluetooth,
which the microcontroller processes and effects any necessary changes.

Code

main.c:

#include <c8051f000.h>

#include <stdio.h>

#include "uart_fifo.h"


sbit LED = P1^6;


// ADC0 definiti
ons

#define TABLESIZE 8

#define INTDEC 8


unsigned char avgBuffer[8];

unsigned short avgTemperature;

unsigned char avgVoltage;

unsigned short sumVoltage;

unsigned short accumulator;

unsigned short result;


char voltageTable[ TABLESIZE] = {63, 70, 76, 83, 88
, 93, 98, 103};

unsigned short temperatureTabl e[TABLESIZE] = {175, 200, 225, 250, 275, 300, 325, 350};


union strange

{


unsigned short buf16;


char buf8[2];

} adcBuffer;


// main definitions

#define BAUDRATE 115200


void SYSCLK_Init(void);

void PORT_Init(
void);

void TIMER3_Init(void);

void ADC0_Init(void);


void TIMER1_ISR(voi d);

void TIMER3_ISR(voi d);

void ADC0_ISR(void);


void reportTemperat ure();


char adcrate;

char buffer;

int i, j;


void main (void)

{


WDTCN = 0xDE;


// disable watchdog timer


WDTCN =

0xAD;



SYSCLK_Init();


// initialize oscillator


PORT_Init();


// initialize crossbar and GPIO


TIMER3_Init();


// initialize heartbeat interrupt


ADC0_Init();


// initialize ADC0


UART_Init(9600);

// initialize UART



IE |= 0x80;



// global interrupt e
nable



RXBufInit();


TXBufInit();



UART_OutString("+++AT+BTAUT=1
\
r");


UART_OutString("AT+BTSRV=2
\
r");;



while(1)


{



if(UART_InChar(&buffer))



{




if(buffer == 'Q')




{





while(!UART_InChar(&buffer)) { }





if(buffer == 'T')





{






reportTem
perature();





}





else if(buffer == 'L')





{






while(!UART_InChar(&buffer)) { }






switch(buffer)






{







case '1': while(!UART_InChar(&buffer)) { }








if(LED)










{










UART_OutString("L1:On
\
r
\
n");










}










else










{










UART_OutString("L1:Off
\
r
\
n");










}










break;







default: break;






}





}




}




else if(buffer == 'C')




{





while(!UART_InChar(&buffer)) { }





if(buffer == 'L')





{






while(!UART_InC
har(&buffer)) { }






switch(buffer)






{







case '1': while(!UART_InChar(&buffer)) { }










if(buffer == '1')










{










LED = 1;










}










else if(buffer == '0')










{










LED = 0;










}










break;














default: break;






}





}




}



}


}

}


//
-----------------------------------------------------------------------------

// Initialization Subroutines

//
-----------------------------------------------------------------------------


//
-----------------------------------------------------------------------------

// SYSCLK_Init

//
-----------------------------------------------------------------------------

//

// This routine initializes the system clock to use internal 16MHz crystal

/
/

void SYSCLK_Init(void)

{


OSCXCN = 0x00;

// external oscillator off


OSCICN = 0x07;

// internal oscillator set to 16MHz

}


//
-----------------------------------------------------------------------------

// PORT_Init

//
------------------------------------
-----------------------------------------

//

// Configure the Crossbar and GPIO ports

//

void PORT_Init(void)

{


// XBR0 Port I/O Crossbar Register 0


// bit 7 CP0EN = 0


// bit 6 ECIE = 0


// bit 5
-
3 PCA0ME = 000


// bit 2 UARTEN = 1


// bit 1 SPI0OEN = 0


// bit 0 SMB0OEN = 0


XBR0 = 0x04;



XBR1 = 0x00;


XBR2 = 0x40;


// Enable crossbar and weak pull
-
ups



PRT0CF |= 0x03;


// set TX pin as push
-
pull


PRT1CF |= 0x40;


// set heartbeat led as push
-
pull



PRT0CF = 0xFD;


PRT1CF = 0xFF;


PRT2CF = 0xFF;


P
RT3CF = 0xFF;



P1 = 0x00;

}


// Timer 3

// controls ADC0 conversion interrupt

void TIMER3_Init(void)

{


// TMR3CN Timer 3 Control Register


// bit 7 TF3


// bit 6
-
3 unused


// bit 2 TR3 = 0


disable timer 3


// bit 1 T3M = 0


use system clock/12


// bit 0

unused


TMR3CN = 0x00;



TMR3RLH = (((
-
41667) >> 8) & 0xFF);


TMR3RLL = ((
-
41667) & 0xFF);


TMR3H = TMR3RLH;


TMR3L = TMR3RLL;



EIE2 = 0x01;


TMR3CN = 0x04;

}


void ADC0_Init(void)

{


// select AIN0
-
1 differential input


AMX0CF = 0x01;


AMX0SL = 0x00;



// select AIN0 single ended input


//AMX0CF = 0x00;


//AMX0SL = 0x00;



// ADC0CF ADC Configuration Register


// bit 7 ADCSC2 = 0


// bit 6 ADCSC1 = 1


// bit 5 ADCSC0 = 1


// bit 4
-
3 unused


// bit 2 AMPGN2 = 0


// bit 1 AMPGN1 = 0


// bit 0 AMPGN0 = 0


A
DC0CF = 0x60;



// ADC0CN ADC Control Register


// bit 7 ADCEN = 1


// enable ADC0


// bit 6 ADCTM = 1


// bit 5 ADCINT = 0


// bit 4 ADBUSY = 0


// bit 3 ADSTM1 = 0


// conversion on write to ADBUSY


// bit 2 ADSTM0 = 0


// bit 1 ADWINT = 0


// bit 0 ADLJ
ST = 0


// right
-
justified


ADC0CN = 0xC0;



// ADC0H[7:4] = 000b


// data in ADC0H[3:0]
-
ADC0L[7:0]



// REF0CN Reference Control Register


// bit 7
-
3 unused


// bit 2 TEMPE = 0


// internal temperature sensor off


// bit 1 BIASE = 1


// internal bias on


// bit 0 REFBE = 1


// use internal voltage reference


REF0CN = 0x03;



EIE2 |= 0x02;


// enable ADC0 end
-
of
-
conversi on interrupt

}


void ADC0_ISR(void) interrupt 15

{


ADCINT = 0;


// clear interrupt flag



adcBuffer.buf8[0] = ADC0H;


adcBuffer.buf8[1] =
ADC0L;



accumulator += adcBuffer.buf16;

// add new value to accumulator



if(!j)


{



result = accumulator/INTDEC;

// decimate and store



j = INTDEC;






// reset accumulator



accumulator = 0;


}


j
--
;

}


void TIMER3_ISR(voi d) interrupt 14

{


TMR3CN &=

~(0x80);




// approximately 1 conversion/second


if((adcrate++) == 0x10)


{



ADBUSY = 1;



adcrate = 0;


}

}


void reportTemperat ure()

{


// converts raw ADC value to voltage in units 0.1V


avgVoltage = ((((result >> 2)*61)/128) & 0xFF);



i = 0;


while
(i < TABLESIZE && avgVoltage > voltageTable[i])


{



i++;


}




if(i == 0)


{



// value is below minimum on lookup table



avgTemperature = temperatureTable[i];


}


else if(i == TABLESIZE)


{



// value is above maximum on lookup table



avgTemperature =
temperatureTable[ TABLESIZE
-
1];


}


else


{



// linear approximation for an in
-
between value



avgTemperature = (temperatureTabl e[i]
-

(voltageTabl e[i]
-

avgVoltage) *








(temperatureTable[i]
-

temperatureTable[i
-
1] ) /








(voltageTabl e[i]
-

voltage
Table[i
-
1]));


}



// reports temperature in 'T:xx.x
\
r
\
n' format


UART_OutString("T:");


UART_OutUDec(avgTemperature);


UART_OutString("
\
r
\
n");

}



uart_fifo.h:


// FIFO Definitions

void RXBufInit(void);

int RXBufPush(char newdata);

int RXBufPop(char *data
Pt);

int RXBufFull(voi d);

int RXBufEmpty(void);


void TXBufInit(void);

int TXBufPush(char newdata);

int TXBufPop(char *dataPt);

int TXBufFull(void);

int TXBufEmpty(voi d);



// UART Definitions

void UART_Init(int baudrate);

void UART_ISR(void);


void UART_O
utChar(char outdata);

void UART_OutString(char *outdata);

void UART_OutUDec(unsigned short number);

int UART_InChar(char *indata);



uart_fifo.c:


#include <c8051f000.h>

#include "uart_fifo.h"


// FIFO Definitions

#define RXBUFSIZE 20

#define TXBUFSIZE 20


// FIFO Variables

char RXBuf[RXBUFSIZE];

char *RXGetPt;

char *RXPutPt;

char TXBuf[TXBUFSIZE];

char *TXGetPt;

char *TXPutPt;


// UART Definitions

//#define SYSCLK 19200000

#define SYSCLK 18000000


char TXBusy;


void RXBufInit(void)

{


RXPutPt = &RXBuf[0];


RXGetPt = &RXBuf[0];

}


int RXBufPush(char newdata)

{


char *tmpPt = RXPutPt;


*(tmpPt) = newdata;


// try to push data onto buffer


tmpPt++;



if(tmpPt == &RXBuf[RXBUFSIZE])


{



tmpPt = &RXBuf[0];

// go to front of buffer


}



if(tmpPt == RXGetPt)


{



return 0;



// buffer is full, push failed


}


else


{



RXPutPt = tmpPt;

// set PutPt, push successful



return 1;


}

}


int RXBufPop(char *dataPt)

{


if(RXGetPt == RXPutPt)


{



return 0;



// buffer empty, nothing to pop


}


else


{



*(dataPt) = *(RXGe
tPt);



RXGetPt++;



if(RXGetPt == &RXBuf[RXBUFSIZE])



{




RXGetPt = &RXBuf[0];

// go to front of buffer



}



return 1;


}

}


int RXBufFull(voi d)

{


char *tmpPt = RXPutPt;


tmpPt++;


if(tmpPt == &RXBuf[RXBUFSIZE])


{



tmpPt = &RXBuf[0];

// go to front
of buffer


}


if(tmpPt == RXGetPt)


{



return 1;


}


else


{



return 0;


}

}


int RXBufEmpty(void)

{



return (RXGetPt == RXPutPt);

}


void TXBufInit(void)

{


TXPutPt = &TXBuf[0];


TXGetPt = &TXBuf[0];

}


int TXBufPush(char newdata)

{


char *tmpPt = TXPu
tPt;


*(tmpPt) = newdata;


// try to push data onto buffer


tmpPt++;



if(tmpPt == &TXBuf[TXBUFSIZE])


{



tmpPt = &TXBuf[0];

// go to front of buffer


}



if(tmpPt == TXGetPt)


{



return 0;



// buffer is full, push failed


}


else


{



TXPutPt = tmpPt;

// set PutPt, push successful



return 1;


}

}


int TXBufPop(char *dataPt)

{


if(TXGetPt == TXPutPt)


{



return 0;



// buffer empty, nothing to pop


}


else


{



*(dataPt) = *(TXGetPt);



TXGetPt++;



if(TXGetPt == &TXBuf[TXBUFSIZE])



{




TXGetPt = &TX
Buf[0];

// go to front of buffer



}



return 1;


}

}


int TXBufFull(void)

{


char *tmpPt = TXPutPt;


tmpPt++;


if(tmpPt == &TXBuf[TXBUFSIZE])


{



tmpPt = &TXBuf[0];

// go to front of buffer


}


if(tmpPt == TXGetPt)


{



return 1;


}


else


{



return 0;


}

}


int TXBufEmpty(voi d)

{



return (TXGetPt == TXPutPt);

}


//
-----------------------------------------------------------------------------

// UART_Init

//
-----------------------------------------------------------------------------

//

// Configure the
UART

//

void UART_Init(int baudrate)

{


// SCON Serial Port Control Register


// bit 7 SM0 = 0


Mode 1: 8
-
bit, variable baud rate


// bit 6 SM1 = 1


// bit 5 SM2 = 0


// bit 4 REN = 1


UART reception enabled


// bit 3 TB8 = X


// bit 2 RB8 = X


// bit 1 TI




transmit interrupt


// bit 0 RI




receive interrupt


SCON = 0x50;



TI = 1;



ES = 1;



// enable UART interrupts



// Timer 2 setup as baud rate clock


// When in baud rate generator mode, Timer 2


// clock source is fixed at SYSCLK/2



TR2 = 0;


//
disable Timer 2



// T2CON Timer 2 Control Register


// bit 7 TF2


// bit 6 EXF2


// bit 5 RCLK = 1


use timer 2 for UART receive


// bit 4 TCLK = 1


use timer 2 for UART transmit


// bit 3 EXEN2 = 0


disable external interrupt


// bit 2 TR2 = 0


disable t
imer 2


// bit 1 C/T2 = 0


use internal clock


// bit 0 CP/RL2 = 0


set auto
-
reload mode


RCLK = 1;


TCLK = 1;


EXEN2 = 0;


CT2 = 0;


CPRL2 = 0;



// SYSCLK = 19200000 Baud rate = 9600


//RCAP2H = (((
-
(SYSCLK/32/baudrate))+4) >> 8) & 0xFF;


//RCAP2L = ((
-
(
SYSCLK/32/baudrate))+4) & 0xFF;


// SYSCLK = 18000000 Baud rate = 9600


RCAP2H = (((
-
(SYSCLK/32/baudrate))) >> 8) & 0xFF;


RCAP2L = ((
-
(SYSCLK/32/baudrate))) & 0xFF;


TL2 = RCAP2L;


TH2 = RCAP2H;



TR2 = 1;

}


void UART_ISR(void) interrupt 4

{


if(RI)


{



RI = 0;





// clear interrupt flag




if(!RXBufFull())



{




RXBufPush(SBUF);



}


}


else if(TI)


{



TI = 0;





// clear interrupt flag




if(!TXBufEmpty())



{




char TXdata;




TXBufPop(&TXdata);




SBUF = TXdata;




TXBusy = 1;



// still transmi
tting



}



else



{




TXBusy = 0;



// all transmit finished



}


}

}


void UART_OutChar(char outdata)

{


while(TXBufPush(outdata) == 0) { }


while(TXBusy == 1) { }


TI = 1;

}


void UART_OutString(char *outdata)

{


while(*outdata)


{



UART_OutChar(*outd
ata);



outdata++;


}

}


// UART_OutInteger

// converts an integer value into its ASCII character

void UART_OutInteger(unsigned char integer)

{


switch(integer)


{



case 0: UART_OutChar('0');




break;



case 1: UART_OutChar('1');




break;



case 2: UART_OutChar('2');




break;



case 3: UART_OutChar('3');




break;



case 4: UART_OutChar('4');




break;



case 5: UART_OutChar('5');




break;



case 6: UART_OutChar('6');




break;



case 7: UART_OutChar('7'
);




break;



case 8: UART_OutChar('8');




break;



case 9: UART_OutChar('9');




break;



default: break;


}

}


// UART_OutUDec

// outputs an unsigned decimal in xx.x format

void UART_OutUDec(unsigned short number)

{


if(number > 10
0)


{



UART_OutInteger(number/100);



number = number
-

(number/100)*100;


}


if(number > 10)


{



UART_OutInteger(number/10);



number = number
-

(number/10)*10;


}


else


{



UART_OutChar('0');


}


UART_OutChar('.');


UART_OutInteger(number);

}


int UAR
T_InChar(char *indata)

{


if(RXBufEmpty())


{



return 0;


}


else


{



RXBufPop(indata);



return 1;


}

}



Website


Default.aspx:


<%
@

Page

Language
="C#"

AutoEventWireup
="true"

CodeBehind
="Default.aspx.cs"

Inherits
="home_web_app._Default"

%>


<!
DOCTYPE

h
tml

PUBLIC

"
-
//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1
-
transitional.dtd">


<
html

xmlns
="http://www.w3.org/1999/xhtml"

>

<
head

runat
="server">


<
title
>
Bluetooth Home Automation
</
title
>

</
head
>

<
body
>


<
img

src
="sps
u
-
header.jpg"


alt
="Southern Polytechnic State University"

/>


<
p

/>


<
form

id
="Form1"

action
="Default.aspx"

method
="post"

runat
="server">


<
asp
:
ScriptManager

ID
="ScriptManager1"

runat
="server"

/>


<
asp
:
UpdatePanel

ID
="UpdatePane
l1"

runat
="server">


<
ContentTemplate
>


<
table

border
="1">


<
tr
>


<
td

align
="center">
Inside Temperature
</
td
>


<
td

align
="center"><
b
><
asp
:
Label

ID
="Temperature"

Text
=
""

runat
="server"

/>
&degC
</
b
></
td
>


</
tr
>


<
tr
>


<
td

align
="center">
Living Room Lights
</
td
>


<
td

align
="center"><
b
><
asp
:
Label

ID
="LivingRoom"

Text
="Off"

runat
="server"

/></
b
></
td
>


</
tr
>


</
table
>


</
ContentTemplate
>


</
asp
:
UpdatePanel
>


<
asp
:
Button

ID
="UpTemp"

Text
="Update Temperature"

OnClick
="UpdateTemperature"

runat
="server"

/>


<
asp
:
Button

ID
="UpLight1"

T
ext
="Update Light 1"

OnClick
="UpdateLight1"

runat
="server"

/>


<
p

/>


<
div
>


Living Room Lights:
<
asp
:
RadioButton

ID
="Light1"

Text
="On"

GroupName
="rLivingRoom"

runat
="server"

/>


<
asp
:
RadioButton

ID
="Light2"

Text
="Off"

r
unat
="server"

GroupName
="rLivingRoom"

/>


<
br

/>


<
asp
:
Button

ID
="Submit"

Text
="Submit Change"

OnClick
="ChangeStatus"

runat
="server"

/>


<
br

/>


</
div
>


<
div
>


<
asp
:
Label

ID
="ErrorMsg"

Font
-
Italic
="
true"

ForeColor
="Red"

Text
=""

runat
="server"

/>


</
div
>


</
form
>

</
body
>

</
html
>


Default.aspx.cs:


using

System;

using

System.Collections;

using

System.Configuration;

using

System.Data;

using

System.Linq;

using

System.Web;

using

System.Web.Secur
ity;

using

System.Web.UI;

using

System.Web.UI.HtmlControls;

using

System.Web.UI.WebControls;

using

System.Web.UI.WebControls.WebParts;

using

System.Xml.Linq;

using

System.IO.Ports;

using

System.Threading;


namespace

home_web_app

{


public

partial

class

_Default

: System.Web.UI.
Page


{


static

SerialPort

spComm =
new

SerialPort
();



protected

void

Page_Load(
object

sender,
EventArgs

e)


{


if

(!Page.IsPostBack)


{


spComm.Close();



spComm.BaudRate = 9600;


spComm.PortName =
"COM8"
;


spComm.DataBits = 8;


spComm.Parity =
Parity
.None;


spComm.Handshake =
Handshake
.None;


spComm.StopBits =
StopBits
.One;



spComm.ReadTimeout = 2000;


Temperature.Text =
"N/A"
;


LivingRoom.Text =
"N/A"
;


Light2.Checked =
true
;


ErrorMsg.Text =
""
;


}


}



protected

void

UpdateTemperatu
re(
object

sender,
EventArgs

e)


{


try


{


String

rxString;


bool

complete =
false
;



if

(!spComm.IsOpen)


{


spComm.Open();


}



while

(!complete)


{


spComm.Write(
"QT
\
r
\
n"
);


rxString = spComm.ReadLine();


if

(rxString.StartsWith(
"T:"
))


{


complete =
true
;



Temperature.Text = rxString.Substring(2);


}


}


ErrorMsg.Text =
""
;


}


catch

(
TimeoutException
)


{


ErrorMsg.Text =
"Communication tim
ed out"
;


Temperature.Text =
"N/A"
;


}


catch

(
UnauthorizedAccessException

uae)


{


ErrorMsg.Text =
"Cannot open connection to Bluetooth device"
;


Temperature.Text =
"N/A"
;



throw

uae;


}


catch

(System.IO.
IOException

siie)


{


ErrorMsg.Text =
"Error communicating with Bluetooth device"
;


Temperature.Text =
"N/A"
;


throw

siie;


}


finally


{


spComm.Close();


}


}



protected

void

UpdateLight1(
object

sender,
EventArgs

e)


{


try


{


String

rxString;


bool

compl
ete =
false
;



if

(!spComm.IsOpen)


{


spComm.Open();


}


while

(!complete)


{


spComm.Write(
"QL1
\
r
\
n"
);


rxString = spComm.
ReadLine();


if

(rxString.StartsWith(
"L1:"
))


{


complete =
true
;


LivingRoom.Text = rxString.Substring(3);


}


}


ErrorMsg
.Text =
""
;


}


catch

(
TimeoutException
)


{


ErrorMsg.Text =
"Communication timed out"
;


LivingRoom.Text =
"N/A"
;


}


catch

(
UnauthorizedAccessException

uae)


{


ErrorMsg.Text =
"Cannot open connection to Bluetooth device"
;


LivingRoom.Text =
"N/A"
;


throw

uae;


}


catch

(System.IO.
IOException

siie)


{


ErrorMsg.Text =
"E
rror communicating with Bluetooth device"
;


LivingRoom.Text =
"N/A"
;


throw

siie;


}


finally


{


spComm.Close();


}


}




protected

void

ChangeSt
atus(
object

sender,
EventArgs

e)


{


try


{


if

(!spComm.IsOpen)


{


spComm.Open();


}


if

(Light1.Checked)


{


sp
Comm.WriteLine(
"CL11
\
r
\
n"
);


}


else

if

(Light2.Checked)


{


spComm.WriteLine(
"CL10
\
r
\
n"
);


}


ErrorMsg.Text =
""
;


}


catch

(
UnauthorizedAc
cessException

uae)


{


ErrorMsg.Text =
"Cannot open connection to Bluetooth device"
;


throw

uae;


}


catch

(System.IO.
IOException

siie)


{


ErrorMsg.Text =
"Error comm
unicating with Bluetooth device"
;


throw

siie;


}


finally


{


spComm.Close();


}


}


}

}