Subversion Repositories HomeAutomation

Rev

Rev 1481 | Rev 1752 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. #include "sns_PIR.h"
  2.  
  3. #define ABS(a) ((a) < 0 ? (-1*a) : (a))
  4.  
  5.  
  6. // a weighted moving avarage value is used to remove "DC offset"
  7. static uint32_t zeroOffset = 0;
  8.  
  9. // a second avarage value is used to detect changes in avarage "energy"
  10. #define NR_AVG_VALUES   15
  11. static int8_t avgValues[NR_AVG_VALUES];
  12. static uint8_t avgIndex = 0;
  13.  
  14.  
  15. void sns_PIR_Init(void)
  16. {
  17.     ADC_Init();
  18.     ltc2450_init();
  19.     Timer_SetTimeout(sns_PIR_SAMPLE_TIMER,  sns_PIR_SAMPLE_PERIOD,  TimerTypeFreeRunning, 0);
  20.     Timer_SetTimeout(sns_PIR_SEND_TIMER,    sns_PIR_SEND_PERIOD,    TimerTypeFreeRunning, 0);
  21. }
  22.  
  23.  
  24. void sns_PIR_Process(void)
  25. {
  26.     uint8_t motionDetect;
  27.     uint16_t brightness;
  28.     if (Timer_Expired(sns_PIR_SAMPLE_TIMER)) {
  29.         /**
  30.          * Read PIR sensor (via external ADC)
  31.          */
  32.         uint16_t pirValue;
  33.         do {
  34.             // if ADC is busy, returned value is 0xFFFF
  35.             pirValue = ltc2450_read();
  36.         } while (pirValue >= 0xFFFF);
  37.         // first time?
  38.         if (zeroOffset == 0) {
  39.             zeroOffset = pirValue;
  40.         }
  41.         else {
  42.             zeroOffset = (zeroOffset*4 + (uint32_t)pirValue)/5;
  43.         }
  44.         int8_t test = (int8_t)((int32_t)pirValue - (int32_t)zeroOffset);
  45.         avgValues[avgIndex++] = test;
  46.         if (avgIndex >= NR_AVG_VALUES) {
  47.             avgIndex = 0;
  48.         }
  49.         uint16_t avgValue = 0;
  50.         for (uint8_t i=0; i<NR_AVG_VALUES; i++) {
  51.             avgValue += ABS(avgValues[i]);
  52.         }
  53.        
  54.         // TODO: keep motiondetect==1 true for at least one CAN send period, so detections are never lost
  55.         motionDetect = (avgValue >= 80);
  56.        
  57.     }
  58.     else if (Timer_Expired(sns_PIR_SEND_TIMER)) {
  59.         /**
  60.          * Read brightness sensor (via internal ADC).
  61.          */
  62.         brightness = ADC_Get(sns_PIR_BRIGHTNESS_AD);
  63.  
  64.         /**
  65.          * Time to send CAN message.
  66.          */
  67.         StdCan_Msg_t txMsg;
  68.         StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  69.         StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  70.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PIR;
  71.         txMsg.Header.ModuleId = sns_PIR_ID;
  72.         txMsg.Header.Command = CAN_MODULE_CMD_PIR_MOTION;
  73.         txMsg.Length = 4;
  74.         txMsg.Data[0] = 0;
  75.         txMsg.Data[1] = (uint8_t)((brightness&0xFF00) >> 8);
  76.         txMsg.Data[2] = (uint8_t)((brightness&0x00FF) >> 0);
  77.         txMsg.Data[3] = motionDetect;
  78.         StdCan_Put(&txMsg);
  79.         // also print data to debug
  80.         printf("M:%u,B:%d\n", motionDetect, brightness);
  81.     }
  82. }
  83.  
  84. void sns_PIR_HandleMessage(StdCan_Msg_t *rxMsg)
  85. {
  86.     /*if (  StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_xyz && ///TODO: Change this to the actual class type
  87.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
  88.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_xyz && ///TODO: Change this to the actual module type
  89.         rxMsg->Header.ModuleId == sns_PIR_ID)
  90.     {
  91.         switch (rxMsg->Header.Command)
  92.         {
  93.         case CAN_CMD_MODULE_DUMMY:
  94.         ///TODO: Do something dummy
  95.         break;
  96.         }
  97.     }*/
  98. }
  99.  
  100. void sns_PIR_List(uint8_t ModuleSequenceNumber)
  101. {
  102.     StdCan_Msg_t txMsg;
  103.    
  104.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  105.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  106.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PIR;
  107.     txMsg.Header.ModuleId = sns_PIR_ID;
  108.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  109.     txMsg.Length = 6;
  110.  
  111.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  112.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  113.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  114.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  115.    
  116.     txMsg.Data[4] = NUMBER_OF_MODULES;
  117.     txMsg.Data[5] = ModuleSequenceNumber;
  118.    
  119.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  120. }
  121.  
  122.