Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. #include "sns_water.h"
  3.  
  4. static uint8_t volatile sns_water_status = LOW;
  5. static uint8_t sns_water_ReportInterval = (uint8_t)sns_water_SEND_PERIOD_S;
  6. static uint32_t volatile sns_water_TickCnt=0;
  7. static uint32_t volatile sns_water_TimePrevTick;
  8. static uint32_t volatile sns_water_Buffer[4]= {0x0000ffff,0x0000ffff,0x0000ffff,0x0000ffff};
  9. static uint8_t volatile sns_water_BufPointer=0;
  10. static uint32_t volatile sns_water_StoreCnt=0;
  11.  
  12. StdCan_Msg_t txMsg;
  13.  
  14. #if sns_water_USEEEPROM==1
  15. #include "sns_water_eeprom.h"
  16. struct eeprom_sns_water EEMEM eeprom_sns_water =
  17. {
  18.     {
  19.           (uint8_t)sns_water_SEND_PERIOD_S, // reportInterval
  20.           0,    // VolumeCounterUpper
  21.           0     // VolumeCounterLower
  22.     },
  23.     0   // crc, must be a correct value, but this will also be handled by the EEPROM module or make scripts
  24. };
  25. #endif
  26.  
  27. void sns_water_Init(void)
  28. {
  29. #if sns_water_USEEEPROM==1
  30.     if (EEDATA_OK)
  31.     {  // Use stored data to set initial values for the module
  32. printf("ok\n");
  33.       sns_water_ReportInterval = eeprom_read_byte(EEDATA.reportInterval);
  34.       sns_water_TickCnt = eeprom_read_word(EEDATA16.VolumeCounterLower);
  35.       sns_water_TickCnt += (((uint32_t)(eeprom_read_word(EEDATA16.VolumeCounterUpper)))<<16);
  36.     } else
  37.     {   //The CRC of the EEPROM is not correct, store default values and update CRC
  38. printf("nok;");
  39.       eeprom_write_byte_crc(EEDATA.reportInterval, sns_water_SEND_PERIOD_S, WITHOUT_CRC);
  40.       eeprom_write_word_crc(EEDATA16.VolumeCounterUpper, 0, WITHOUT_CRC);
  41.       eeprom_write_word_crc(EEDATA16.VolumeCounterLower, 0, WITHOUT_CRC);
  42.       EEDATA_UPDATE_CRC;
  43.     }
  44. #endif
  45.  
  46.     ADC_Init();
  47.     sns_water_TimePrevTick = Timer_GetTicks();
  48.     Timer_SetTimeout(sns_water_ADPOLL_TIMER, sns_water_ADPOLL_PERIOD_MS, TimerTypeFreeRunning, 0);
  49.     Timer_SetTimeout(sns_water_SEND_TIMER, sns_water_SEND_PERIOD_S*1000, TimerTypeFreeRunning, 0);
  50.  
  51.     uint16_t ADvalue = ADC_Get(sns_water_AD_CHANNEL);
  52.     if (ADvalue > (sns_water_HIGH_THRESHOLD_MV*1024UL/5000UL))
  53.     {
  54.         sns_water_status = HIGH;
  55.     }
  56.  
  57.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  58.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  59.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_WATER;
  60.     txMsg.Header.ModuleId = sns_water_ID;
  61.     txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_FLOW;
  62.     txMsg.Length = 6;
  63. }
  64.  
  65. void sns_water_Process(void)
  66. {
  67.     /*
  68.     Notes
  69.     maybe its better to skip the poll timer and always poll when in process
  70.     */
  71.     uint8_t oldstatus = sns_water_status;
  72.     if (Timer_Expired(sns_water_ADPOLL_TIMER))
  73.     {
  74.         uint16_t ADvalue = ADC_Get(sns_water_AD_CHANNEL);
  75.         if (sns_water_status == LOW && ADvalue > (sns_water_HIGH_THRESHOLD_MV*1024UL/5000UL))
  76.         {
  77.             sns_water_status = HIGH;
  78.         }
  79.         else if (sns_water_status == HIGH && ADvalue < (sns_water_LOW_THRESHOLD_MV*1024UL/5000UL))
  80.         {
  81.             sns_water_status = LOW;
  82.         }
  83.     }
  84.  
  85.     /* If status changed == one tick */
  86.     if (oldstatus != sns_water_status)
  87.     {
  88.         sns_water_TickCnt += 1;
  89.  
  90.         sns_water_Buffer[sns_water_BufPointer] = Timer_GetTicks() - sns_water_TimePrevTick;
  91.         if (sns_water_BufPointer++ == 4)
  92.         {
  93.             sns_water_BufPointer = 0;
  94.         }
  95.  
  96.         sns_water_TimePrevTick = Timer_GetTicks();
  97.  
  98. #if sns_water_USEEEPROM==1
  99.         if ((sns_water_TickCnt % 2048) == 0)
  100.         {
  101.             eeprom_write_word_crc(EEDATA16.VolumeCounterUpper, (uint16_t)((sns_water_TickCnt>>16) & 0xffff), WITHOUT_CRC);
  102.             eeprom_write_word_crc(EEDATA16.VolumeCounterLower, (uint16_t)(sns_water_TickCnt & 0xffff), WITH_CRC);
  103.         }
  104. #endif
  105.     }
  106.  
  107.     if (Timer_Expired(sns_water_SEND_TIMER))
  108.     {
  109.         uint32_t flow4 = 0;
  110.         for (uint8_t i = 0; i<4;i++) {
  111.              flow4 += sns_water_Buffer[i];
  112.         }
  113.         flow4 = flow4/4;
  114.         /* The flow is ml per tick / time between ticks */
  115.         flow4 = sns_water_UL_PER_TICK/flow4;
  116.  
  117.         txMsg.Data[0] = (uint8_t)((flow4>>8) & 0xff);
  118.         txMsg.Data[1] = (uint8_t)(flow4 & 0xff);
  119.         txMsg.Data[5] = (uint8_t)(sns_water_TickCnt*sns_water_UL_PER_TICK/1000) & 0xff;
  120.         txMsg.Data[4] = (uint8_t)((sns_water_TickCnt*sns_water_UL_PER_TICK/1000) >> 8) & 0xff;
  121.         txMsg.Data[3] = (uint8_t)((sns_water_TickCnt*sns_water_UL_PER_TICK/1000) >> 16) & 0xff;
  122.         txMsg.Data[2] = (uint8_t)((sns_water_TickCnt*sns_water_UL_PER_TICK/1000) >> 24) & 0xff;
  123. #if CAN_PRINTF==1
  124. //      txMsg.Data[5] = (uint8_t)sns_water_TickCnt & 0xff;
  125. //      txMsg.Data[4] = (uint8_t)(sns_water_TickCnt >> 8) & 0xff;
  126. //      txMsg.Data[3] = (uint8_t)(sns_water_TickCnt >> 16) & 0xff;
  127. //      txMsg.Data[2] = (uint8_t)(sns_water_TickCnt >> 24) & 0xff;
  128. #endif
  129.         while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  130.  
  131.         /* TODO How to handle no flow? (means no ticks, no new time-diffs) */
  132.         /* This solution starts to fill buffer with older values if ticks come in slower than we send out data */
  133.         if (Timer_GetTicks() - sns_water_TimePrevTick > sns_water_SEND_PERIOD_S*1000)
  134.         {
  135.             sns_water_Buffer[sns_water_BufPointer] = Timer_GetTicks() - sns_water_TimePrevTick;
  136.             if (sns_water_BufPointer++ == 4)
  137.             {
  138.                 sns_water_BufPointer = 0;
  139.             }
  140.         }
  141.     }
  142. }
  143.  
  144. void sns_water_HandleMessage(StdCan_Msg_t *rxMsg)
  145. {
  146.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
  147.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
  148.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_WATER &&
  149.         rxMsg->Header.ModuleId == sns_water_ID)
  150.     {
  151.         StdCan_Msg_t txMsg2;
  152.         switch (rxMsg->Header.Command)
  153.         {
  154.         case CAN_MODULE_CMD_GLOBAL_REPORT_INTERVAL:
  155.             if (rxMsg->Length > 0)
  156.             {
  157.                 sns_water_ReportInterval = rxMsg->Data[0];
  158.                 Timer_SetTimeout(sns_water_SEND_TIMER, sns_water_ReportInterval*1000 , TimerTypeFreeRunning, 0);
  159.             }
  160.             StdCan_Set_class(txMsg2.Header, CAN_MODULE_CLASS_SNS);
  161.             StdCan_Set_direction(txMsg2.Header, DIRECTIONFLAG_FROM_OWNER);
  162.             txMsg2.Header.ModuleType = CAN_MODULE_TYPE_SNS_WATER;
  163.             txMsg2.Header.ModuleId = sns_water_ID;
  164.             txMsg2.Header.Command = CAN_MODULE_CMD_GLOBAL_REPORT_INTERVAL;
  165.             txMsg2.Length = 1;
  166.             txMsg2.Data[0] = sns_water_ReportInterval;
  167.             StdCan_Put(&txMsg2);
  168.             break;
  169.         case CAN_MODULE_CMD_WATER_SETVOLUME:
  170.             if (rxMsg->Length == 4)
  171.             {
  172.                 sns_water_TickCnt = (rxMsg->Data[3]*1000/sns_water_UL_PER_TICK);
  173.                 sns_water_TickCnt += ((uint32_t)(rxMsg->Data[2]*1000/sns_water_UL_PER_TICK))<<8;
  174.                 sns_water_TickCnt += ((uint32_t)(rxMsg->Data[1]*1000/sns_water_UL_PER_TICK))<<16;
  175.                 sns_water_TickCnt += ((uint32_t)(rxMsg->Data[0]*1000/sns_water_UL_PER_TICK))<<24;
  176.             }
  177.             StdCan_Set_class(txMsg2.Header, CAN_MODULE_CLASS_SNS);
  178.             StdCan_Set_direction(txMsg2.Header, DIRECTIONFLAG_FROM_OWNER);
  179.             txMsg2.Header.ModuleType = CAN_MODULE_TYPE_SNS_WATER;
  180.             txMsg2.Header.ModuleId = sns_water_ID;
  181.             txMsg2.Header.Command = CAN_MODULE_CMD_WATER_SETVOLUME;
  182.             txMsg2.Length = 1;
  183.             txMsg2.Data[3] = (uint8_t)(sns_water_TickCnt*sns_water_UL_PER_TICK/1000) & 0xff;
  184.             txMsg2.Data[2] = (uint8_t)((sns_water_TickCnt*sns_water_UL_PER_TICK/1000) >> 8) & 0xff;
  185.             txMsg2.Data[1] = (uint8_t)((sns_water_TickCnt*sns_water_UL_PER_TICK/1000) >> 16) & 0xff;
  186.             txMsg2.Data[0] = (uint8_t)((sns_water_TickCnt*sns_water_UL_PER_TICK/1000) >> 24) & 0xff;
  187.             StdCan_Put(&txMsg2);
  188.            
  189.             break;
  190.         }
  191.     }
  192. }
  193.  
  194. void sns_water_List(uint8_t ModuleSequenceNumber)
  195. {
  196.     StdCan_Msg_t txMsg;
  197.  
  198.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  199.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  200.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_WATER;
  201.     txMsg.Header.ModuleId = sns_water_ID;
  202.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  203.     txMsg.Length = 6;
  204.  
  205.     uint32_t HwId=BIOS_GetHwId();
  206.     txMsg.Data[0] = HwId&0xff;
  207.     txMsg.Data[1] = (HwId>>8)&0xff;
  208.     txMsg.Data[2] = (HwId>>16)&0xff;
  209.     txMsg.Data[3] = (HwId>>24)&0xff;
  210.  
  211.     txMsg.Data[4] = NUMBER_OF_MODULES;
  212.     txMsg.Data[5] = ModuleSequenceNumber;
  213.  
  214.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  215. }
  216.