Home automation using Xbee radios
Dependencies: EthernetNetIf HTTPServer RPCInterface mbed C12832_lcd
main.cpp
- Committer:
- chrisisthefish
- Date:
- 2013-12-04
- Revision:
- 9:4b1e3531dd00
- Parent:
- 8:e32fcca16102
- Child:
- 10:de0be690b3c0
File content as of revision 9:4b1e3531dd00:
/* Analog Types: 0 = No connection 1 = Analog Devices TMP36 Temperature Sensor Digital Types: 0 = No connection 1 = Light Control (Digital Output) 2 = Motion Sense (Digital Input) */ #include "mbed.h" #include "EthernetNetIf.h" #include "HTTPServer.h" #include "SerialRPCInterface.h" #include "XbeeCommLib.h" DigitalIn pb(p8); DigitalOut led1(LED1); DigitalOut led4(LED4); Serial xbeeSerial(p9, p10); unsigned char data[500]; int dataCounter = 0; bool clear = false; //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 int ReadLightSwitch0 = 0; int ReadLightSwitch1 = 0; int WriteLightSwitch0 = 0; int WriteLightSwitch1 = 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"); EthernetNetIf eth; HTTPServer svr; struct xbee { // radio prototype with addresss, location, pointer to sensor list unsigned int addrHigh; // upper 16 bits address of sensor unsigned int addrLow; // lower address of sensor unsigned short digitalData; unsigned short digitalDataOutput; int digitalType[10]; float analogData[4]; int analogType[4]; float* analogRpcDataPointer[4]; int* digitalOutRpcDataPointer[10]; int* digitalInRpcDataPointer[10]; Timer* timerList[10]; struct xbee * next; // pointer to next struct }; struct xbee *root; struct xbee xbeeList[3]; int xbeeCount = 3; void xbeeSerialCallback() { //printf("Xbee\n"); if(clear){ dataCounter = 0; clear = false; } if(dataCounter < 500){ while(xbeeSerial.readable() == true && dataCounter < 500){ led4 = 1; data[dataCounter] = xbeeSerial.getc(); dataCounter++; led4 = 0; } } else{ printf("Serial data buffer overflow. Resetting buffer...\n"); dataCounter = 0; data[dataCounter] = xbeeSerial.getc(); } } int main() { //xbeeSerial.attach(&xbeeSerialCallback); printf("\n\nBeginning Setup\n"); // Ethernet Setup EthernetErr ethErr = eth.setup(); if(ethErr){ printf("Error %d in setup.\n", ethErr); return -1; } printf("Setup OK\n"); // Add RPCHandler svr.addHandler<RPCHandler>("/rpc"); // 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].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; Timer motionTimer0; xbeeList[0].timerList[2] = &motionTimer0; // 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; Timer motionTimer1; xbeeList[1].timerList[2] = &motionTimer1; //xbee3 = addnode(root, 0, 3); // xbee3->digitalType[3] = 1; //Motion sensor (input) printf("Initialization finished\n\n"); // TODO: Read sensors and set RPC variables to initial values Timer tm; tm.start(); //Main program loop while(true){ Net::poll(); xbeeSerialCallback(); monitorXbee(); compareDigitalReadWrite(); // TODO: Poll sensors and reset RPC variables. if(tm.read() > 1){ 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){ return ((pins>>i)&1); } float analogInputFormat(float data, int type){ // Incoming data is in volts: // Example: data = 0.7 -> 0.7 Volts switch (type){ case 1: //Analog Devices TMP36 Temp Sensor: 1 deg F per 10mV return data * 100; //Multiply voltage by 100 to get Temperature case 2: return data; case 3: return data; 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); for(int i = 0; i < xbeeCount; i++){ if(xbeeList[i].addrHigh == addrHigh && xbeeList[i].addrLow == addrLow){ //Addresses match match //Place the digital data in the appropriate position in the struct xbeeList[i].digitalData = data; //Need to update appropriate RPC variables 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; float analogData; //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"); return; } for(int i = 0; i < xbeeCount; i++){ if(xbeeList[i].addrHigh == addrHigh && xbeeList[i].addrLow == addrLow){ //Addresses match match 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].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"); }*/ } void compareDigitalReadWrite(){ int mask = 1; int i, digiIndex; int rpcValue = 0; int digiValue = 0; 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].digitalOutRpcDataPointer[digiIndex]) rpcValue = 1; else rpcValue = 0; 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; 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 } } } mask = mask << 1; } } } 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 } } } } }