Home automation using Xbee radios
Dependencies: EthernetNetIf HTTPServer RPCInterface mbed C12832_lcd
Diff: main.cpp
- Revision:
- 10:de0be690b3c0
- Parent:
- 9:4b1e3531dd00
- Child:
- 11:03ff417d0d5d
diff -r 4b1e3531dd00 -r de0be690b3c0 main.cpp --- a/main.cpp Wed Dec 04 02:35:47 2013 +0000 +++ b/main.cpp Fri Dec 06 07:05:49 2013 +0000 @@ -9,6 +9,7 @@ 0 = No connection 1 = Light Control (Digital Output) 2 = Motion Sense (Digital Input) +3 = Button (Digital Input) */ @@ -21,6 +22,8 @@ DigitalIn pb(p8); DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); DigitalOut led4(LED4); Serial xbeeSerial(p9, p10); @@ -29,25 +32,47 @@ int dataCounter = 0; bool clear = false; + +int motionDetector0 = 1; +int motionDetector1 = 1; + +int button0 = 1; +int button1 = 1; + //Create port variables float ReadTemperatureSensor0 = 0.0; float ReadTemperatureSensor1 = 0.0; -int ReadMotionDetector0 = 1; //Motion detector is low-active -int ReadMotionDetector1 = 1; //Motion detector is low-active +float ReadTemperatureSensor2 = 0.0; + +int ReadMotionEnable0 = 0; +int ReadMotionEnable1 = 0; +int WriteMotionEnable0 = 0; +int WriteMotionEnable1 = 0; + int ReadLightSwitch0 = 0; int ReadLightSwitch1 = 0; +int ReadLightSwitch2 = 0; + int WriteLightSwitch0 = 0; int WriteLightSwitch1 = 0; +int WriteLightSwitch2 = 0; //Make these variables accessible over RPC by attaching them to an RPCVariable -RPCVariable<float> RPCTemperatureSensor0(&ReadTemperatureSensor0, "TemperatureSensor0"); -RPCVariable<float> RPCTemperatureSensor1(&ReadTemperatureSensor1, "TemperatureSensor1"); -RPCVariable<int> RPCMotionDetector0(&ReadMotionDetector0, "MotionDetector0"); -RPCVariable<int> RPCMotionDetector1(&ReadMotionDetector1, "MotionDetector1"); -RPCVariable<int> RPCReadLightSwitch0(&ReadLightSwitch0, "ReadLightSwitch0"); -RPCVariable<int> RPCReadLightSwitch1(&ReadLightSwitch1, "ReadLightSwitch1"); -RPCVariable<int> RPCWriteLightSwitch0(&WriteLightSwitch0, "WriteLightSwitch0"); -RPCVariable<int> RPCWriteLightSwitch1(&WriteLightSwitch1, "WriteLightSwitch1"); +RPCVariable<float> RPCTemperatureSensor0(&ReadTemperatureSensor0, "Temp0"); +//RPCVariable<float> RPCTemperatureSensor1(&ReadTemperatureSensor1, "Temp1"); +RPCVariable<float> RPCTemperatureSensor2(&ReadTemperatureSensor2, "Temp2"); + +RPCVariable<int> RPCReadMotionEnable0(&ReadMotionEnable0, "RMotion0"); +RPCVariable<int> RPCReadMotionEnable1(&ReadMotionEnable1, "RMotion1"); + +RPCVariable<int> RPCWriteMotionEnable0(&WriteMotionEnable0, "WMotion0"); +RPCVariable<int> RPCWriteMotionEnable1(&WriteMotionEnable1, "WMotion1"); + +RPCVariable<int> RPCReadLightSwitch0(&ReadLightSwitch0, "RLight0"); +RPCVariable<int> RPCReadLightSwitch1(&ReadLightSwitch1, "RLight1"); + +RPCVariable<int> RPCWriteLightSwitch0(&WriteLightSwitch0, "WLight0"); +RPCVariable<int> RPCWriteLightSwitch1(&WriteLightSwitch1, "WLight1"); EthernetNetIf eth; HTTPServer svr; @@ -59,17 +84,19 @@ unsigned int addrLow; // lower address of sensor unsigned short digitalData; unsigned short digitalDataOutput; + bool digitalDataValid; + bool firstDigitalData; int digitalType[10]; float analogData[4]; int analogType[4]; float* analogRpcDataPointer[4]; - int* digitalOutRpcDataPointer[10]; - int* digitalInRpcDataPointer[10]; + int* rpcDataPointer[10]; + int* writeRpcDataPointer[10]; + int* prevData[10]; Timer* timerList[10]; struct xbee * next; // pointer to next struct }; -struct xbee *root; struct xbee xbeeList[3]; int xbeeCount = 3; @@ -77,7 +104,7 @@ -void xbeeSerialCallback() { +void xbeeSerialHandler() { //printf("Xbee\n"); if(clear){ dataCounter = 0; @@ -85,10 +112,10 @@ } if(dataCounter < 500){ while(xbeeSerial.readable() == true && dataCounter < 500){ - led4 = 1; +// led4 = 1; data[dataCounter] = xbeeSerial.getc(); dataCounter++; - led4 = 0; +// led4 = 0; } } else{ @@ -102,7 +129,7 @@ int main() { - //xbeeSerial.attach(&xbeeSerialCallback); + //xbeeSerial.attach(&xbeeSerialHandler); printf("\n\nBeginning Setup\n"); // Ethernet Setup @@ -119,56 +146,50 @@ // Show that the server is ready and listening svr.bind(80); printf("RPC Server Ready\n"); - - /* This won't change, or we would lose the list in memory */ - //struct xbee *root; - root = (struct xbee *) malloc( sizeof(struct xbee) ); - root->next = NULL; - /* The node root points to has its next pointer equal to a null pointer - set */ - //struct xbee* xbee1; -// struct xbee* xbee2; -// struct xbee* xbee3; - -// printf("Beginning Xbee Radio Struct Setup\n"); -// xbee1 = addnode(root, 0x0013a200, 0x4079d00b); //Router0 -// xbee1->analogType[1] = 1; //Analog Devices TMP36 Temp Sensor -// xbee1->digitalType[0] = 1; //Light control (output) -// xbee1->digitalType[3] = 1; //Motion sensor (input) -// xbee1->analogRpcDataPointer[1] = &ReadTemperatureSensor1; -// printf("xbee1 setup\n"); + + xbeeList[0].addrHigh = 0x0013a200; xbeeList[0].addrLow = 0x4079d00b; //Router0 xbeeList[0].analogType[1] = 1; //Analog Devices TMP36 Temp Sensor xbeeList[0].digitalType[0] = 1; //Light control (output) xbeeList[0].digitalType[2] = 2; //Motion sensor (input) + xbeeList[0].digitalType[3] = 3; //Button (input) xbeeList[0].analogRpcDataPointer[1] = &ReadTemperatureSensor0; -// printf("Xbee0: Storing RPC variable address %d\nStored address is %d\n", &ReadTemperatureSensor1, xbeeList[0].analogRpcDataPointer[1]); - xbeeList[0].digitalOutRpcDataPointer[0] = &ReadLightSwitch0; - xbeeList[0].digitalInRpcDataPointer[2] = &ReadMotionDetector0; + + xbeeList[0].rpcDataPointer[0] = &ReadLightSwitch0; + xbeeList[0].writeRpcDataPointer[0] = &WriteLightSwitch0; + + xbeeList[0].rpcDataPointer[2] = &ReadMotionEnable0; + xbeeList[0].writeRpcDataPointer[2] = &WriteMotionEnable0; + xbeeList[0].prevData[2] = &motionDetector0; Timer motionTimer0; xbeeList[0].timerList[2] = &motionTimer0; - + xbeeList[0].prevData[3] = &button0; -// xbee2 = addnode(root, 0x0013a200, 0x4079d023); //Router1 -// xbee2->analogType[1] = 1; //Analog Devices TMP36 Temp Sensor -// xbee2->digitalType[0] = 1; //Light control (output) -// printf("xbee2 setup\n"); + xbeeList[1].addrHigh = 0x0013a200; xbeeList[1].addrLow = 0x4079d023; //Router1 - xbeeList[1].analogType[1] = 1; //Analog Devices TMP36 Temp Sensor xbeeList[1].digitalType[0] = 1; //Light control (output) xbeeList[1].digitalType[2] = 2; //Motion sensor (input) - xbeeList[1].analogRpcDataPointer[1] = &ReadTemperatureSensor1; -// printf("Xbee1: Storing RPC variable address %d\nStored address is %d\n", &ReadTemperatureSensor2, xbeeList[1].analogRpcDataPointer[1]); - xbeeList[1].digitalOutRpcDataPointer[0] = &ReadLightSwitch1; - xbeeList[1].digitalInRpcDataPointer[2] = &ReadMotionDetector1; + xbeeList[1].digitalType[3] = 3; //Button (input) + + xbeeList[1].rpcDataPointer[0] = &ReadLightSwitch1; + xbeeList[1].writeRpcDataPointer[0] = &WriteLightSwitch1; + + xbeeList[1].rpcDataPointer[2] = &ReadMotionEnable1; + xbeeList[1].writeRpcDataPointer[2] = &WriteMotionEnable1; + xbeeList[1].prevData[2] = &motionDetector1; Timer motionTimer1; xbeeList[1].timerList[2] = &motionTimer1; + xbeeList[1].prevData[3] = &button1; - //xbee3 = addnode(root, 0, 3); -// xbee3->digitalType[3] = 1; //Motion sensor (input) + + xbeeList[2].addrHigh = 0x0013a200; + xbeeList[2].addrLow = 0x406874c6; //Router2 + xbeeList[2].analogType[1] = 1; //Analog Devices TMP36 Temp Sensor + xbeeList[2].analogRpcDataPointer[1] = &ReadTemperatureSensor2; + printf("Initialization finished\n\n"); @@ -179,10 +200,10 @@ //Main program loop while(true){ Net::poll(); - xbeeSerialCallback(); + xbeeSerialHandler(); monitorXbee(); compareDigitalReadWrite(); - + monitorTimers(); // TODO: Poll sensors and reset RPC variables. @@ -190,26 +211,11 @@ led1 = !led1; tm.start(); - monitorTimers(); + } } } -struct xbee* addnode(struct xbee* root, unsigned int addrHigh, unsigned int addrLow){ - struct xbee* node; - node = root; - - if ( node != 0 ) { - while ( node->next != 0){ - node = node->next; - } - } - node = (struct xbee *) malloc( sizeof(struct xbee) ); - node->next = NULL; - node->addrHigh = addrHigh; - node->addrLow = addrLow; - return node; -} int getDigitalValue(int i, short pins){ @@ -231,16 +237,14 @@ default: return data; } -// return(data); } -void digitalInputHandle(struct xbee* root, unsigned int addrHigh, unsigned int addrLow, unsigned short data){ - //struct xbee* node; -// node = root; - - //printf("Digital input handler: Address: %x %x\nDigital Data = %d\n", addrHigh, addrLow, data); +void digitalInputHandle(unsigned int addrHigh, unsigned int addrLow, unsigned short data){ + if(DEBUG) + printf("Digital input handler: Address: %x %x\nDigital Data = %d\n", addrHigh, addrLow, data); + unsigned short tmp = data; for(int i = 0; i < xbeeCount; i++){ if(xbeeList[i].addrHigh == addrHigh && xbeeList[i].addrLow == addrLow){ @@ -249,49 +253,36 @@ //Place the digital data in the appropriate position in the struct xbeeList[i].digitalData = data; - //Need to update appropriate RPC variables + for(int j = 0; j < 10; j++){ + if(xbeeList[i].digitalType[j] != 2){ //Make sure we don't overwrite the motion enable RPC variable + //Update RPC variable, if present + if(xbeeList[i].rpcDataPointer[j] != NULL){ + *xbeeList[i].rpcDataPointer[j] = tmp & 1; + tmp = tmp >> 1; + } + } + } + + //if(xbeeList[i].firstDigitalData == false && xbeeList[i].digitalDataValid == false){ +// xbeeList[i].firstDigitalData = true; +// }else if(xbeeList[i].firstDigitalData == true && xbeeList[i].digitalDataValid == false){ + xbeeList[i].digitalDataValid = true; + // xbeeList[i].firstDigitalData = false; +// } break; } if(i == (xbeeCount - 1)){ printf("No matching addresses found\n"); } } - - - /* - Add code here to check for digital input changes. - This is important to be able to detect motion - */ - - - /*if ( node != 0 ) { - while ( node->addrHigh != addrHigh){ - node = node->next; - } - while(node->addrLow !=addrLow){ - node = node->next; - } - } - else { - printf("There is no node in the list"); - } - - if(node != 0){ - node->digitalData = data; - } - else{ - printf("Node is not in the list"); - }*/ - } -void analogInputHandle(struct xbee* root,unsigned int addrHigh, unsigned int addrLow, int index, float data){ - //struct xbee* node; -// node = root; +void analogInputHandle(unsigned int addrHigh, unsigned int addrLow, int index, float data){ float analogData; - //printf("Analog input handler: Address: %x %x\nAnalog Index = %d Analog Value = %f\n", addrHigh, addrLow, index, data); + if(DEBUG) + printf("Analog input handler: Address: %x %x\nAnalog Index = %d Analog Value = %f\n", addrHigh, addrLow, index, data); if(index < 0){ printf("ERROR: Analog input index is negative\n"); @@ -305,133 +296,130 @@ if(DEBUG) printf("Xbee %d radio address match\n", i); - //Place the analog data in the appropriate position in the struct - analogData = analogInputFormat(data, xbeeList[i].analogType[index]); - xbeeList[i].analogData[index] = analogData; + if(xbeeList[i].analogType[index]){ //Verify that analog input is actually enabled. If not, ignore the data + + //Place the analog data in the appropriate position in the struct + analogData = analogInputFormat(data, xbeeList[i].analogType[index]); + xbeeList[i].analogData[index] = analogData; - if(xbeeList[i].analogRpcDataPointer[index] != NULL){ - //Also push the analog data to the RPC variable - *xbeeList[i].analogRpcDataPointer[index] = analogData; - //printf("Storing value %f into RPC pointer. Value stored is %f\n", analogData, *xbeeList[i].analogRpcDataPointer[index]); - }else - printf("No valid RPC variable found\n"); + if(xbeeList[i].analogRpcDataPointer[index] != NULL){ + //Also push the analog data to the RPC variable + *xbeeList[i].analogRpcDataPointer[index] = analogData; + //printf("Storing value %f into RPC pointer. Value stored is %f\n", analogData, *xbeeList[i].analogRpcDataPointer[index]); + }else + printf("No valid RPC variable found\n"); + } break; } if(i == (xbeeCount - 1)){ printf("No matching addresses found\n"); } } - - - - - - - - /*if ( node != 0 ) { - printf("Comparing addrHigh %x to %x\n", node->addrHigh, addrHigh); - while ( node->addrHigh != addrHigh){ - if(node->next != NULL){ - node = node->next; - }else{ - printf("Reached end of search with no addrHigh match\n"); - break; - } - printf("Comparing addrHigh %x to %x\n", node->addrHigh, addrHigh); - } - - printf("Comparing addrLow %x to %x\n", node->addrLow, addrLow); - while(node->addrLow != addrLow){ - if(node->next != NULL){ - node = node->next; - }else{ - printf("Reached end of search with no addrLow match\n"); - break; - } - printf("Comparing addrLow %x to %x\n", node->addrLow, addrLow); - } - }else { - printf("There is no node in the list"); - } - - if(node != 0 && index >= 0){ - //Place the analog data in the appropriate position in the struct - analogData = analogInputFormat(data, node->analogType[index]); - node->analogData[index] = analogData; - - if(node->analogRpcDataPointer[index] != NULL){ - //Also push the analog data to the RPC variable - *node->analogRpcDataPointer[index] = analogData; - printf("Storing value %f into RPC pointer. Value stored is %f\n", analogData, *node->analogRpcDataPointer[index]); - } - } - else{ - printf("Node is not in the list"); - }*/ } - +/* + This is bad code + I need to replace this + + Possibly change name to monitorRpcValues +*/ void compareDigitalReadWrite(){ int mask = 1; int i, digiIndex; - int rpcValue = 0; - int digiValue = 0; + bool rpcValue = false; + bool pinValue = false; for(i = 0; i < xbeeCount; i++){ //Loop through all xbees mask = 1; - for(digiIndex = 0; digiIndex < 10; digiIndex++){ //Loop through all digital inputs to see if they do not match the corresponding RPC variable - - if(xbeeList[i].digitalType[digiIndex] == 1){ //Is this digital I/O a light control (digital output)? + if(xbeeList[i].digitalDataValid){ + + for(digiIndex = 0; digiIndex < 10; digiIndex++){ //Loop through all digital inputs to see if they do not match the corresponding RPC variable - if(*xbeeList[i].digitalOutRpcDataPointer[digiIndex]) - rpcValue = 1; + if(xbeeList[i].digitalData & mask) + pinValue = true; else - rpcValue = 0; + pinValue = false; + - if((xbeeList[i].digitalData & mask) != rpcValue){ - printf("Xbee%d: Digital output %d = %d doesn't match RPC variable = %d Updating Xbee...\n", i, digiIndex, xbeeList[i].digitalData & mask, rpcValue); - //This means that the digital output is in the incorrect state - //Therefore write out the RPC state to the radio - digitalWriteXbee(xbeeList[i].addrHigh, xbeeList[i].addrLow, digiIndex, rpcValue); - //printf("Old digitalData = %d\t", xbeeList[i].digitalData); - xbeeList[i].digitalData = (xbeeList[i].digitalData & ~mask) | (rpcValue << digiIndex); //Update the digitalData value with the new output value - //printf("Updated digitalData = %d, mask = %d, rpcValue = %d, digiIndex = %d\n", xbeeList[i].digitalData, mask, rpcValue, digiIndex); - } - //Otherwise, it matches - } - - if(xbeeList[i].digitalType[digiIndex] == 2){ //Is this digital I/O a motion detector (digital input)? - digiValue = (xbeeList[i].digitalData & mask); - - //Get the RPC value - if(*xbeeList[i].digitalInRpcDataPointer[digiIndex]) - rpcValue = 1; - else - rpcValue = 0; + //Check for both the motion enable value changes as well as actual motion sensor activations + if(xbeeList[i].digitalType[digiIndex] == 2){ //Is this digital I/O a motion detector (digital input)? - if(digiValue != rpcValue){ //This means there has been a state change, either motion detected, or sensor returning to normal - - if(digiValue == 0 || rpcValue == 0){ //Motion detected - -// printf("Motion detected on Xbee%d\n", i); - //if(digiValue) -// rpcValue = 1; -// else -// rpcValue = 0; - - rpcValue = 1; - *xbeeList[i].digitalInRpcDataPointer[digiIndex] = rpcValue; - - *xbeeList[i].digitalOutRpcDataPointer[0] = 1; //Turn on the light - xbeeList[i].timerList[digiIndex]->start(); //Restart timer + if(xbeeList[i].writeRpcDataPointer[digiIndex] != NULL && xbeeList[i].rpcDataPointer[digiIndex] != NULL){ + + //Determine if user changed value of motion enable. If so, update read RPC variable + if(*xbeeList[i].writeRpcDataPointer[digiIndex] != *xbeeList[i].rpcDataPointer[digiIndex]){ + *xbeeList[i].rpcDataPointer[digiIndex] = *xbeeList[i].writeRpcDataPointer[digiIndex]; + } + + if(*xbeeList[i].rpcDataPointer[digiIndex]){ //Is motion enabled? + if(pinValue != *xbeeList[i].prevData[digiIndex]){ //See if the motion detection pin has changed value + if(pinValue == 0){ //Motion has been detected + //turn on the light & restart timer + printf("Xbee%d: Motion detected\n", i); + *xbeeList[i].writeRpcDataPointer[0] = 1; + xbeeList[i].timerList[digiIndex]->start(); + } + //update motion detector value with new state + *xbeeList[i].prevData[digiIndex] = pinValue; + } + } } } + + //Check for button state if present + if(xbeeList[i].digitalType[digiIndex] == 3){ //Is this digital I/O a button (digital input)? + if(xbeeList[i].prevData[digiIndex] != NULL){ + if(pinValue != *xbeeList[i].prevData[digiIndex]){ //See if the button pin has changed value + if(pinValue == 0){ //Button press detected + + if(xbeeList[i].rpcDataPointer[0] != NULL){ + if(*xbeeList[i].rpcDataPointer[0]) + rpcValue = true; + else + rpcValue = false; + } + + //turn the light on or off + printf("Xbee%d: Button pressed\n", i); + if(rpcValue) + *xbeeList[i].writeRpcDataPointer[0] = 0; + else + *xbeeList[i].writeRpcDataPointer[0] = 1; + } + //update value with new state + *xbeeList[i].prevData[digiIndex] = pinValue; + } + } + } + + + if(xbeeList[i].digitalType[digiIndex] == 1){ //Is this digital I/O a light control (digital output)? + + if(xbeeList[i].writeRpcDataPointer[digiIndex] != NULL){ + if(*xbeeList[i].writeRpcDataPointer[digiIndex]) + rpcValue = true; + else + rpcValue = false; + + if(pinValue != rpcValue){ + if(DEBUG) + printf("Xbee%d: Writing %d to digital output %d\n", i, rpcValue, digiIndex); + //This means that the digital output is in the incorrect state, Therefore write out the RPC state to the radio + digitalWriteXbee(xbeeList[i].addrHigh, xbeeList[i].addrLow, digiIndex, rpcValue); + xbeeList[i].digitalData = (xbeeList[i].digitalData & ~mask) | (rpcValue << digiIndex); //Update the digitalData value with the new output value + } + //Otherwise, it matches + if(xbeeList[i].rpcDataPointer[digiIndex] != NULL) + *xbeeList[i].rpcDataPointer[digiIndex] = rpcValue; //Update the read RPC variable to reflect the actual value + } + } + + mask = mask << 1; } - mask = mask << 1; } } } @@ -440,11 +428,17 @@ void monitorTimers(){ - for(int i = 0; i < xbeeCount; i++){ //Loop through all xbees - for(int digiIndex = 0; digiIndex < 10; digiIndex++){ //Loop through all digital I/O - if(xbeeList[i].digitalType[digiIndex] == 2){ //See if I/O is a motion detector input - if(xbeeList[i].timerList[digiIndex]->read() > 15){ //Check if timer has expired - *xbeeList[i].digitalOutRpcDataPointer[0] = 0; //If timer has expired, turn light off + for(int i = 0; i < xbeeCount; i++){ //Loop through all xbees + for(int digiIndex = 0; digiIndex < 10; digiIndex++){ //Loop through all digital I/O + if(xbeeList[i].digitalType[digiIndex] == 2){ //See if I/O is a motion detector input + if(xbeeList[i].rpcDataPointer[digiIndex] != NULL){ //Make sure RPC value is valid + if(*xbeeList[i].rpcDataPointer[digiIndex]){ //Check if motion detection is enabled + if(xbeeList[i].timerList[digiIndex]->read() > 15){ //Check if timer has expired + if(xbeeList[i].rpcDataPointer[0] != NULL) + *xbeeList[i].writeRpcDataPointer[0] = 0; //If timer has expired, turn light off + } + + } } } }