Subversion Repositories HomeAutomation

Rev

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