Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. #include "sns_inputAnalog.h"
  3. //TODO: Config over CAN, save to eeprom, pullups, references
  4.  
  5. struct {
  6.     uint8_t             Status;         //Used for digital input, high or low
  7.     uint16_t            PeriodCnt;      //Counter for periodicity
  8.     uint16_t            LastSentAdVal;  //Remember the last sent AD value
  9. } sns_inputAnalog_Sensor[sns_inputAnalog_NUM_SUPPORTED];
  10.  
  11.  
  12. #define HIGH        1
  13. #define LOW         2
  14. #define NOCHANGE    0
  15.  
  16. #ifdef sns_inputAnalog_USEEEPROM
  17. #include "sns_inputAnalog_eeprom.h"
  18.  
  19. struct eeprom_sns_inputAnalog EEMEM eeprom_sns_inputAnalog =
  20. {
  21.     {
  22.         {
  23.         /* Define initialization values on the EEPROM variables here, this will generate a *.eep file
  24.         that can be used to store this values to the node, can in future be done with a EEPROM module
  25.         and the make-scrips. Write the values in the exact same order as the struct is defined in the *.h file.  */
  26.         1*sns_inputAnalog0Factor/(2^sns_inputAnalog0Scale), //Config, low level threshold voltage, (1 volt)
  27.         2*sns_inputAnalog0Factor/(2^sns_inputAnalog0Scale), //Config, high level threshold voltage, (2 volts)
  28.         4800,   //Config, periodicity
  29.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE,   //Config, if sensor is of type periodic or digital input
  30.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_PULLUP_DISABLE,            //Config, if the pullup should be enabled
  31.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_REFERENCE_DISABLE,         //Config, if the reference to GND should be enabled
  32.         },
  33. #if sns_inputAnalog_NUM_SUPPORTED>=2
  34.         {
  35.         1*sns_inputAnalog1Factor/(2^sns_inputAnalog1Scale), //Config, low level threshold voltage, (1 volt)
  36.         2*sns_inputAnalog1Factor/(2^sns_inputAnalog1Scale), //Config, high level threshold voltage, (2 volts)
  37.         4900,  
  38.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE,   //Config, if sensor is of type periodic or digital input
  39.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_PULLUP_DISABLE,            //Config, if the pullup should be enabled
  40.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_REFERENCE_DISABLE,         //Config, if the reference to GND should be enabled
  41.         },
  42. #endif
  43. #if sns_inputAnalog_NUM_SUPPORTED>=3
  44.         {
  45.         1*sns_inputAnalog2Factor/(2^sns_inputAnalog2Scale), //Config, low level threshold voltage
  46.         2*sns_inputAnalog2Factor/(2^sns_inputAnalog2Scale), //Config, high level threshold voltage, (2 volts)
  47.         5100,
  48.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE,   //Config, if sensor is of type periodic or digital input
  49.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_PULLUP_DISABLE,            //Config, if the pullup should be enabled
  50.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_REFERENCE_DISABLE,         //Config, if the reference to GND should be enabled
  51.         },
  52. #endif
  53. #if sns_inputAnalog_NUM_SUPPORTED>=4
  54.         {
  55.         1*sns_inputAnalog3Factor/(2^sns_inputAnalog3Scale), //Config, low level threshold voltage
  56.         2*sns_inputAnalog3Factor/(2^sns_inputAnalog3Scale), //Config, high level threshold voltage, (2 volts)
  57.         5200,
  58.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE,   //Config, if sensor is of type periodic or digital input
  59.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_PULLUP_DISABLE,            //Config, if the pullup should be enabled
  60.         CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_REFERENCE_DISABLE,         //Config, if the reference to GND should be enabled
  61.         }
  62. #endif
  63.     },
  64.     0   // crc, must be a correct value, but this will also be handled by the EEPROM module or make scripts
  65. };
  66. #endif
  67.  
  68. void sns_inputAnalog_Init(void)
  69. {
  70. #ifdef sns_inputAnalog_USEEEPROM
  71.     if (EEDATA_OK)
  72.     {
  73.         /* Use stored data to set initial values for the module */
  74.         for (uint8_t i=0; i<sns_inputAnalog_NUM_SUPPORTED; i++)
  75.         {
  76.             //eeprom_write_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog, sizeof(sns_inputAnalog_Config)*i );
  77.             eeprom_read_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*i, sizeof(sns_inputAnalog_Config) );
  78.         }
  79.     }
  80.     else
  81.     {
  82.         /* The CRC of the EEPROM is not correct, store default values and update CRC */
  83.         for (uint8_t i=0; i<sns_inputAnalog_NUM_SUPPORTED; i++)
  84.         {
  85.             sns_inputAnalog_Config[i].LowTh=50;         //Config, low level threshold voltage
  86.             sns_inputAnalog_Config[i].HighTh=100;       //Config, high level threshold voltage
  87.             sns_inputAnalog_Config[i].Periodicity=5000; //Config, periodicity
  88.             sns_inputAnalog_Config[i].Type=CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE;    //Config, if sensor is of type periodic or digital input
  89.             sns_inputAnalog_Config[i].PullupEnable=CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_PULLUP_DISABLE;     //Config, if the pullup should be enabled
  90.             sns_inputAnalog_Config[i].RefEnable=CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_REFERENCE_DISABLE;     //Config, if the reference to GND should be enabled
  91.            
  92.             eeprom_update_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*i, sizeof(sns_inputAnalog_Config) );
  93.         }
  94.         EEDATA_UPDATE_CRC;
  95.     }
  96. #endif  
  97.  
  98.     ADC_Init();
  99.     Timer_SetTimeout(sns_inputAnalog_TIMER, sns_inputAnalog_POLL_PERIOD_MS , TimerTypeFreeRunning, 0);
  100. }
  101.  
  102. void sns_inputAnalog_Process(void)
  103. {
  104.     /* When the timer has overflowed the AD channels shall be read */
  105.     if (Timer_Expired(sns_inputAnalog_TIMER))
  106.     {
  107.         StdCan_Msg_t txMsg;
  108.         StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  109.         StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  110.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_INPUTANALOG;
  111.         txMsg.Header.ModuleId = sns_inputAnalog_ID;
  112.  
  113.         uint16_t AdValue=0;
  114.         /* For each channel */
  115.         for (uint8_t i=0; i<sns_inputAnalog_NUM_SUPPORTED; i++)
  116.         {
  117.             /* Do reading of AD channel */
  118.             switch (i)
  119.             {
  120.                 case 0:
  121.                     AdValue = ADC_Get(sns_inputAnalog0AD);
  122.                     break;
  123.                 case 1:
  124.                     AdValue = ADC_Get(sns_inputAnalog1AD);
  125.                     break;
  126.                 case 2:
  127.                     AdValue = ADC_Get(sns_inputAnalog2AD);
  128.                     break;
  129.                 case 3:
  130.                     AdValue = ADC_Get(sns_inputAnalog3AD);
  131.                     break;
  132.             }
  133.            
  134.             /* If this channel is configured as periodic transmission of voltage */
  135.             if (sns_inputAnalog_Config[i].Type == CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE)
  136.             {
  137.                 /* Count periodicity */
  138.                 sns_inputAnalog_Sensor[i].PeriodCnt += sns_inputAnalog_POLL_PERIOD_MS;
  139.                 /* If periodicity overflowed or AD value changed more than threshold since last sent value */
  140.                 if (sns_inputAnalog_Sensor[i].PeriodCnt >= sns_inputAnalog_Config[i].Periodicity ||
  141.                     MAX(AdValue,sns_inputAnalog_Sensor[i].LastSentAdVal)-MIN(AdValue,sns_inputAnalog_Sensor[i].LastSentAdVal) > sns_inputAnalog_Config[i].LowTh)
  142.                 //if (sns_inputAnalog_Sensor[i].PeriodCnt >= sns_inputAnalog_Config[i].Periodicity ||
  143.                 //  abs(AdValue-sns_inputAnalog_Sensor[i].LastSentAdVal) > sns_inputAnalog_Config[i].LowTh)
  144.                 {
  145.                     /* Reset periodicity counter */
  146.                     sns_inputAnalog_Sensor[i].PeriodCnt = 0;
  147.                     /* Store value as last sent */
  148.                     sns_inputAnalog_Sensor[i].LastSentAdVal = AdValue;
  149.                    
  150.                     /* send sensor value on CAN with command CAN_MODULE_CMD_PHYSICAL_VOLTAGE */
  151.                     txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_VOLTAGE;
  152.                     txMsg.Length = 3;
  153.                     /* The channel should be transmitted in byte 0 */
  154.                     txMsg.Data[0] = i;
  155.                    
  156.                     uint8_t analogScale = 10;
  157.                     /* Select parameters for AD conversion */
  158.                     switch (i)
  159.                     {
  160.                         case 0:
  161.                             analogScale = sns_inputAnalog0Scale;
  162.                             AdValue = AdValue * sns_inputAnalog0Factor;
  163.                             break;
  164.                         case 1:
  165.                             analogScale = sns_inputAnalog1Scale;
  166.                             AdValue = AdValue * sns_inputAnalog1Factor;
  167.                             break;
  168.                         case 2:
  169.                             analogScale = sns_inputAnalog2Scale;
  170.                             AdValue = AdValue * sns_inputAnalog2Factor;
  171.                             break;
  172.                         case 3:
  173.                             analogScale = sns_inputAnalog3Scale;
  174.                             AdValue = AdValue * sns_inputAnalog3Factor;
  175.                             break;
  176.                     }
  177.                     txMsg.Data[1] = (AdValue>>(analogScale-6+8))&0xff;
  178.                     txMsg.Data[2] = (AdValue>>(analogScale-6))&0xff;
  179.                    
  180.                     /* Send value on CAN */
  181.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
  182.                 }
  183.             }
  184.             /* If this channel is configured as digital input */
  185.             else if (sns_inputAnalog_Config[i].Type == CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_DIGITALINPUT)
  186.             {
  187.                 txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS;
  188.                 txMsg.Length = 2;
  189.                 /* The channel should be transmitted in byte 0 */
  190.                 txMsg.Data[0] = i;
  191.                 /* If status was low but voltage is above high theshold */
  192.                 if (sns_inputAnalog_Sensor[i].Status == LOW && AdValue > sns_inputAnalog_Config[i].HighTh)
  193.                 {
  194.                     /* Consider status to be high */
  195.                     sns_inputAnalog_Sensor[i].Status = HIGH;
  196.                     txMsg.Data[1] = CAN_MODULE_ENUM_PHYSICAL_PINSTATUS_STATUS_HIGH;
  197.                    
  198.                     /* send status on CAN with command CAN_MODULE_CMD_PHYSICAL_PINSTATUS */
  199.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  200.                 }
  201.                 /* If status was high but voltage is below low theshold */
  202.                 else if (sns_inputAnalog_Sensor[i].Status == HIGH && AdValue < sns_inputAnalog_Config[i].LowTh)
  203.                 {
  204.                     /* Consider status to be low */
  205.                     sns_inputAnalog_Sensor[i].Status = LOW;
  206.                     txMsg.Data[1] = CAN_MODULE_ENUM_PHYSICAL_PINSTATUS_STATUS_LOW;
  207.                    
  208.                     /* send status on CAN with command CAN_MODULE_CMD_PHYSICAL_PINSTATUS */
  209.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  210.                 }
  211.             }
  212.         }
  213.  
  214.     }
  215. }
  216.  
  217. void sns_inputAnalog_HandleMessage(StdCan_Msg_t *rxMsg)
  218. {
  219. /*  if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
  220.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
  221.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_INPUTANALOG &&
  222.         rxMsg->Header.ModuleId == sns_inputAnalog_ID)
  223.     {
  224.         switch (rxMsg->Header.Command)
  225.         {
  226.         case CAN_CMD_MODULE_DUMMY:
  227.         ///TODO: Do something dummy
  228.         break;
  229.         }
  230.     }*/
  231. }
  232.  
  233. void sns_inputAnalog_List(uint8_t ModuleSequenceNumber)
  234. {
  235.     StdCan_Msg_t txMsg;
  236.    
  237.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  238.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  239.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_INPUTANALOG;
  240.     txMsg.Header.ModuleId = sns_inputAnalog_ID;
  241.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  242.     txMsg.Length = 6;
  243.  
  244.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  245.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  246.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  247.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  248.    
  249.     txMsg.Data[4] = NUMBER_OF_MODULES;
  250.     txMsg.Data[5] = ModuleSequenceNumber;
  251.    
  252.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  253. }
  254.