Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. #include "sns_water.h"
  3.  
  4. uint8_t sns_water_status = LOW;
  5. uint32_t sns_water_liter_cnt=0;
  6. uint16_t sns_water_milliliter_cnt=0;
  7. static uint32_t volatile sns_water_TimePrevTick;
  8. static uint32_t volatile sns_water_Buffer[4]= {0xffff,0xffff,0xffff,0xffff};
  9. static uint8_t volatile sns_water_Buf_Pointer=0;
  10.  
  11. StdCan_Msg_t txMsg;
  12.  
  13. #if sns_water_USEEEPROM==1
  14. #include "sns_water_eeprom.h"
  15. struct eeprom_sns_water EEMEM eeprom_sns_water =
  16. {
  17.     {
  18.         ///TODO: Define initialization values on the EEPROM variables here, this will generate a *.eep file that can be used to store this values to the node, can in future be done with a EEPROM module and the make-scrips. Write the values in the exact same order as the struct is defined in the *.h file.
  19.         0xAB,       // x
  20.         0x1234      // y
  21.         0x12345678  // z
  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.     {
  32.       ///TODO: Use stored data to set initial values for the module
  33.       blablaX = eeprom_read_byte(EEDATA.x);
  34.       blablaY = eeprom_read_word(EEDATA16.y);
  35.       blablaZ = eeprom_read_dword(EEDATA32.y);
  36.     } else
  37.     {   //The CRC of the EEPROM is not correct, store default values and update CRC
  38.       eeprom_write_byte_crc(EEDATA.x, 0xAB, WITHOUT_CRC);
  39.       eeprom_write_word_crc(EEDATA16.y, 0x1234, WITHOUT_CRC);
  40.       eeprom_write_dword_crc(EEDATA32.y, 0x12345678, WITHOUT_CRC);
  41.       EEDATA_UPDATE_CRC;
  42.     }
  43. #endif
  44.  
  45.     ADC_Init();
  46.     sns_water_TimePrevTick = Timer_GetTicks();
  47.     Timer_SetTimeout(sns_water_ADPOLL_TIMER, sns_water_ADPOLL_PERIOD_MS, TimerTypeFreeRunning, 0);
  48.     Timer_SetTimeout(sns_water_SEND_TIMER, sns_water_SEND_PERIOD_S*1000, TimerTypeFreeRunning, 0);
  49.  
  50.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  51.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  52.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_WATER;
  53.     txMsg.Header.ModuleId = sns_water_ID;
  54.     txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_FLOW;
  55.     txMsg.Length = 6;
  56. }
  57.  
  58. void sns_water_Process(void)
  59. {
  60.     /*
  61.     Notes
  62.     maybe its better to skip the poll timer and always poll when in process
  63.     maybe one need a filter of x samples
  64.     */
  65.     uint8_t oldstatus = sns_water_status;
  66.     if (Timer_Expired(sns_water_ADPOLL_TIMER))
  67.     {
  68.         uint16_t ADvalue = ADC_Get(sns_water_AD_CHANNEL);
  69.         if (sns_water_status == LOW && ADvalue > (sns_water_HIGH_THRESHOLD_MV*1024UL/5000UL))
  70.         {
  71.             sns_water_status = HIGH;
  72. //printf("H\n");
  73.         }
  74.         else if (sns_water_status == HIGH && ADvalue < (sns_water_LOW_THRESHOLD_MV*1024UL/5000UL))
  75.         {
  76.             sns_water_status = LOW;
  77. //printf("L\n");
  78.         }
  79.     }
  80.    
  81.     if (oldstatus != sns_water_status)
  82.     {
  83.         sns_water_milliliter_cnt += sns_water_ML_PER_TICK;
  84.         /* If milliliter counter has more than one liter */
  85.         if (sns_water_milliliter_cnt >= 1000)
  86.         {
  87.             /* Add one liter to liter counter */
  88.             sns_water_liter_cnt += 1;
  89.             /* Decrease milliliter counter with the volume added to liter counter */
  90.             sns_water_milliliter_cnt -= 1000;
  91.         }
  92.        
  93.         sns_water_Buffer[sns_water_Buf_Pointer] = Timer_GetTicks() - sns_water_TimePrevTick;
  94.         if (sns_water_Buf_Pointer++ == 4)
  95.         {
  96.             sns_water_Buf_Pointer = 0;
  97.         }
  98.        
  99.         sns_water_TimePrevTick = Timer_GetTicks();
  100.     }
  101.    
  102.     if (Timer_Expired(sns_water_SEND_TIMER))
  103.     {
  104.         uint32_t flow4 = 0;
  105.         for (uint8_t i = 0; i<4;i++) {
  106.              flow4 += sns_water_Buffer[i];
  107.         }
  108.         flow4 = flow4/4;
  109.         /* The flow is ml per tick / time between ticks */
  110.         flow4 = sns_water_ML_PER_TICK*1000UL/flow4;
  111.         //uint16_t flow = sns_water_ML_PER_TICK*1000UL/sns_water_TimeDiff;
  112.         txMsg.Data[0] = (uint8_t)((flow4>>8) & 0xff);
  113.         txMsg.Data[1] = (uint8_t)(flow4 & 0xff);
  114.         txMsg.Data[5] = (uint8_t)sns_water_liter_cnt & 0xff;
  115.         txMsg.Data[4] = (uint8_t)(sns_water_liter_cnt >> 8) & 0xff;
  116.         txMsg.Data[3] = (uint8_t)(sns_water_liter_cnt >> 16) & 0xff;
  117.         txMsg.Data[2] = (uint8_t)(sns_water_liter_cnt >> 24) & 0xff;
  118.         while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  119.  
  120.         /* TODO How to handle no flow? (means no ticks, no new time-diffs) */
  121.         /* This solution starts to fill buffer with older values if ticks come in slower than we send out data */
  122.         if (Timer_GetTicks() - sns_water_TimePrevTick > sns_water_SEND_PERIOD_S*2000)
  123.         {
  124.             sns_water_Buffer[sns_water_Buf_Pointer] = Timer_GetTicks() - sns_water_TimePrevTick;
  125.             if (sns_water_Buf_Pointer++ == 4)
  126.             {
  127.                 sns_water_Buf_Pointer = 0;
  128.             }
  129.         }
  130.     }
  131. }
  132.  
  133. void sns_water_HandleMessage(StdCan_Msg_t *rxMsg)
  134. {
  135. #if 0
  136.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
  137.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
  138.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_WATER &&
  139.         rxMsg->Header.ModuleId == sns_water_ID)
  140.     {
  141.         switch (rxMsg->Header.Command)
  142.         {
  143.         case CAN_CMD_MODULE_DUMMY:
  144.        
  145.         break;
  146.         }
  147.     }
  148. #endif
  149. }
  150.  
  151. void sns_water_List(uint8_t ModuleSequenceNumber)
  152. {
  153.     StdCan_Msg_t txMsg;
  154.  
  155.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  156.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  157.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_WATER;
  158.     txMsg.Header.ModuleId = sns_water_ID;
  159.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  160.     txMsg.Length = 6;
  161.  
  162.     uint32_t HwId=BIOS_GetHwId();
  163.     txMsg.Data[0] = HwId&0xff;
  164.     txMsg.Data[1] = (HwId>>8)&0xff;
  165.     txMsg.Data[2] = (HwId>>16)&0xff;
  166.     txMsg.Data[3] = (HwId>>24)&0xff;
  167.  
  168.     txMsg.Data[4] = NUMBER_OF_MODULES;
  169.     txMsg.Data[5] = ModuleSequenceNumber;
  170.  
  171.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  172. }
  173.