Subversion Repositories HomeAutomation

Rev

Rev 1477 | Rev 1745 | 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.         // TODO: keep motiondetect==1 true for at least one CAN send period, so detections are never lost
  54.         motionDetect = (avgValue >= 80);
  55.        
  56.         /**
  57.          * Read brightness sensor (via internal ADC).
  58.          */
  59.         brightness = ADC_Get(sns_PIR_BRIGHTNESS_AD);
  60.     }
  61.     else if (Timer_Expired(sns_PIR_SEND_TIMER)) {
  62.         /**
  63.          * Time to send CAN message.
  64.          */
  65.         StdCan_Msg_t txMsg;
  66.         StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  67.         StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  68.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PIR;
  69.         txMsg.Header.ModuleId = sns_PIR_ID;
  70.         txMsg.Header.Command = CAN_MODULE_CMD_PIR_MOTION;
  71.         txMsg.Length = 4;
  72.         txMsg.Data[0] = 0;
  73.         txMsg.Data[1] = (uint8_t)((brightness&0xFF00) >> 8);
  74.         txMsg.Data[2] = (uint8_t)((brightness&0x00FF) >> 0);
  75.         txMsg.Data[3] = motionDetect;
  76.         StdCan_Put(&txMsg);
  77.         // also print data to debug
  78.         printf("M:%u,B:%d\n", motionDetect, brightness);
  79.     }
  80. }
  81.  
  82. void sns_PIR_HandleMessage(StdCan_Msg_t *rxMsg)
  83. {
  84.     /*if (  StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_xyz && ///TODO: Change this to the actual class type
  85.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
  86.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_xyz && ///TODO: Change this to the actual module type
  87.         rxMsg->Header.ModuleId == sns_PIR_ID)
  88.     {
  89.         switch (rxMsg->Header.Command)
  90.         {
  91.         case CAN_CMD_MODULE_DUMMY:
  92.         ///TODO: Do something dummy
  93.         break;
  94.         }
  95.     }*/
  96. }
  97.  
  98. void sns_PIR_List(uint8_t ModuleSequenceNumber)
  99. {
  100.     StdCan_Msg_t txMsg;
  101.    
  102.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  103.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  104.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PIR;
  105.     txMsg.Header.ModuleId = sns_PIR_ID;
  106.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  107.     txMsg.Length = 6;
  108.  
  109.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  110.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  111.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  112.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  113.    
  114.     txMsg.Data[4] = NUMBER_OF_MODULES;
  115.     txMsg.Data[5] = ModuleSequenceNumber;
  116.    
  117.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  118. }
  119.  
  120.