Subversion Repositories HomeAutomation

Rev

Rev 1540 | Rev 1542 | 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. #if ((__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ == 6 && __AVR_LIBC_REVISION__ >= 7)||(__AVR_LIBC_MAJOR__ == 1  && __AVR_LIBC_MINOR__ > 6)||__AVR_LIBC_MAJOR__ > 1)
  93.             eeprom_update_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*i, sizeof(sns_inputAnalog_Config) );
  94. #else
  95.             eeprom_write_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*i, sizeof(sns_inputAnalog_Config) );
  96.             #warning Using old version of AVRlibc
  97. #endif
  98.         }
  99.         EEDATA_UPDATE_CRC;
  100.     }
  101. #endif  
  102.  
  103.     ADC_Init();
  104.     Timer_SetTimeout(sns_inputAnalog_TIMER, sns_inputAnalog_POLL_PERIOD_MS , TimerTypeFreeRunning, 0);
  105. }
  106.  
  107. void sns_inputAnalog_Process(void)
  108. {
  109.     /* When the timer has overflowed the AD channels shall be read */
  110.     if (Timer_Expired(sns_inputAnalog_TIMER))
  111.     {
  112.         StdCan_Msg_t txMsg;
  113.         StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  114.         StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  115.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_INPUTANALOG;
  116.         txMsg.Header.ModuleId = sns_inputAnalog_ID;
  117.  
  118.         uint16_t AdValue=0;
  119.         /* For each channel */
  120.         for (uint8_t i=0; i<sns_inputAnalog_NUM_SUPPORTED; i++)
  121.         {
  122.             /* Do reading of AD channel */
  123.             switch (i)
  124.             {
  125.                 case 0:
  126.                     AdValue = ADC_Get(sns_inputAnalog0AD);
  127.                     break;
  128.                 case 1:
  129.                     AdValue = ADC_Get(sns_inputAnalog1AD);
  130.                     break;
  131.                 case 2:
  132.                     AdValue = ADC_Get(sns_inputAnalog2AD);
  133.                     break;
  134.                 case 3:
  135.                     AdValue = ADC_Get(sns_inputAnalog3AD);
  136.                     break;
  137.             }
  138.            
  139.             /* If this channel is configured as periodic transmission of voltage */
  140.             if (sns_inputAnalog_Config[i].Type == CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE)
  141.             {
  142.                 /* Count periodicity */
  143.                 sns_inputAnalog_Sensor[i].PeriodCnt += sns_inputAnalog_POLL_PERIOD_MS;
  144.                 /* If periodicity overflowed or AD value changed more than threshold since last sent value */
  145.                 if (sns_inputAnalog_Sensor[i].PeriodCnt >= sns_inputAnalog_Config[i].Periodicity ||
  146.                     MAX(AdValue,sns_inputAnalog_Sensor[i].LastSentAdVal)-MIN(AdValue,sns_inputAnalog_Sensor[i].LastSentAdVal) > sns_inputAnalog_Config[i].LowTh)
  147.                 //if (sns_inputAnalog_Sensor[i].PeriodCnt >= sns_inputAnalog_Config[i].Periodicity ||
  148.                 //  abs(AdValue-sns_inputAnalog_Sensor[i].LastSentAdVal) > sns_inputAnalog_Config[i].LowTh)
  149.                 {
  150.                     /* Reset periodicity counter */
  151.                     sns_inputAnalog_Sensor[i].PeriodCnt = 0;
  152.                     /* Store value as last sent */
  153.                     sns_inputAnalog_Sensor[i].LastSentAdVal = AdValue;
  154.                    
  155.                     /* send sensor value on CAN with command CAN_MODULE_CMD_PHYSICAL_VOLTAGE */
  156.                     txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_VOLTAGE;
  157.                     txMsg.Length = 3;
  158.                     /* The channel should be transmitted in byte 0 */
  159.                     txMsg.Data[0] = i;
  160.                    
  161.                     uint8_t analogScale = 10;
  162.                     /* Select parameters for AD conversion */
  163.                     switch (i)
  164.                     {
  165.                         case 0:
  166.                             analogScale = sns_inputAnalog0Scale;
  167.                             AdValue = AdValue * sns_inputAnalog0Factor;
  168.                             break;
  169.                         case 1:
  170.                             analogScale = sns_inputAnalog1Scale;
  171.                             AdValue = AdValue * sns_inputAnalog1Factor;
  172.                             break;
  173.                         case 2:
  174.                             analogScale = sns_inputAnalog2Scale;
  175.                             AdValue = AdValue * sns_inputAnalog2Factor;
  176.                             break;
  177.                         case 3:
  178.                             analogScale = sns_inputAnalog3Scale;
  179.                             AdValue = AdValue * sns_inputAnalog3Factor;
  180.                             break;
  181.                     }
  182.                     txMsg.Data[1] = (AdValue>>(analogScale-6+8))&0xff;
  183.                     txMsg.Data[2] = (AdValue>>(analogScale-6))&0xff;
  184.                    
  185.                     /* Send value on CAN */
  186.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
  187.                 }
  188.             }
  189.             /* If this channel is configured as digital input */
  190.             else if (sns_inputAnalog_Config[i].Type == CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_DIGITALINPUT)
  191.             {
  192.                 txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS;
  193.                 txMsg.Length = 2;
  194.                 /* The channel should be transmitted in byte 0 */
  195.                 txMsg.Data[0] = i;
  196.                 /* If status was low but voltage is above high theshold */
  197.                 if (sns_inputAnalog_Sensor[i].Status == LOW && AdValue > sns_inputAnalog_Config[i].HighTh)
  198.                 {
  199.                     /* Consider status to be high */
  200.                     sns_inputAnalog_Sensor[i].Status = HIGH;
  201.                     txMsg.Data[1] = CAN_MODULE_ENUM_PHYSICAL_PINSTATUS_STATUS_HIGH;
  202.                    
  203.                     /* send status on CAN with command CAN_MODULE_CMD_PHYSICAL_PINSTATUS */
  204.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  205.                 }
  206.                 /* If status was high but voltage is below low theshold */
  207.                 else if (sns_inputAnalog_Sensor[i].Status == HIGH && AdValue < sns_inputAnalog_Config[i].LowTh)
  208.                 {
  209.                     /* Consider status to be low */
  210.                     sns_inputAnalog_Sensor[i].Status = LOW;
  211.                     txMsg.Data[1] = CAN_MODULE_ENUM_PHYSICAL_PINSTATUS_STATUS_LOW;
  212.                    
  213.                     /* send status on CAN with command CAN_MODULE_CMD_PHYSICAL_PINSTATUS */
  214.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  215.                 }
  216.             }
  217.         }
  218.  
  219.     }
  220. }
  221.  
  222. void sns_inputAnalog_HandleMessage(StdCan_Msg_t *rxMsg)
  223. {
  224. /*  if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
  225.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
  226.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_INPUTANALOG &&
  227.         rxMsg->Header.ModuleId == sns_inputAnalog_ID)
  228.     {
  229.         switch (rxMsg->Header.Command)
  230.         {
  231.         case CAN_CMD_MODULE_DUMMY:
  232.         ///TODO: Do something dummy
  233.         break;
  234.         }
  235.     }*/
  236. }
  237.  
  238. void sns_inputAnalog_List(uint8_t ModuleSequenceNumber)
  239. {
  240.     StdCan_Msg_t txMsg;
  241.    
  242.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  243.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  244.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_INPUTANALOG;
  245.     txMsg.Header.ModuleId = sns_inputAnalog_ID;
  246.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  247.     txMsg.Length = 6;
  248.  
  249.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  250.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  251.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  252.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  253.    
  254.     txMsg.Data[4] = NUMBER_OF_MODULES;
  255.     txMsg.Data[5] = ModuleSequenceNumber;
  256.    
  257.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  258. }
  259.