Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. #include "sns_inputAnalog.h"
  3. //TODO: 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 setPullups(void)
  69. {
  70.    
  71. }
  72.  
  73. void setReferences(void)
  74. {
  75.    
  76. }
  77.  
  78. void sns_inputAnalog_Init(void)
  79. {
  80. #ifdef sns_inputAnalog_USEEEPROM
  81.     if (EEDATA_OK)
  82.     {
  83.         /* Use stored data to set initial values for the module */
  84.         for (uint8_t i=0; i<sns_inputAnalog_NUM_SUPPORTED; i++)
  85.         {
  86.             //eeprom_write_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog, sizeof(sns_inputAnalog_Config)*i );
  87.             eeprom_read_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*i, sizeof(sns_inputAnalog_Config) );
  88.         }
  89.     }
  90.     else
  91.     {
  92.         /* The CRC of the EEPROM is not correct, store default values and update CRC */
  93.         for (uint8_t i=0; i<sns_inputAnalog_NUM_SUPPORTED; i++)
  94.         {
  95.             sns_inputAnalog_Config[i].LowTh=50;         //Config, low level threshold voltage
  96.             sns_inputAnalog_Config[i].HighTh=100;       //Config, high level threshold voltage
  97.             sns_inputAnalog_Config[i].Periodicity=5000; //Config, periodicity
  98.             sns_inputAnalog_Config[i].Type=CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE;    //Config, if sensor is of type periodic or digital input
  99.             sns_inputAnalog_Config[i].PullupEnable=CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_PULLUP_DISABLE;     //Config, if the pullup should be enabled
  100.             sns_inputAnalog_Config[i].RefEnable=CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_REFERENCE_DISABLE;     //Config, if the reference to GND should be enabled
  101.            
  102. #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)
  103.             eeprom_update_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*i, sizeof(sns_inputAnalog_Config) );
  104. #else
  105.             eeprom_write_block( &sns_inputAnalog_Config[i], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*i, sizeof(sns_inputAnalog_Config) );
  106.             #warning Using old version of AVRlibc, does not support eeprom_update-functions
  107. #endif
  108.         }
  109.         EEDATA_UPDATE_CRC;
  110.     }
  111. #endif  
  112.  
  113.     /* Initiate ADC */
  114.     ADC_Init();
  115.     /* Start timer for reading inputs */
  116.     Timer_SetTimeout(sns_inputAnalog_TIMER, sns_inputAnalog_POLL_PERIOD_MS , TimerTypeFreeRunning, 0);
  117.     /* Set pullups according config */
  118.     setPullups();
  119.     /* Set gnd references according config */
  120.     setReferences();
  121. }
  122.  
  123. void sns_inputAnalog_Process(void)
  124. {
  125.     /* When the timer has overflowed the AD channels shall be read */
  126.     if (Timer_Expired(sns_inputAnalog_TIMER))
  127.     {
  128.         StdCan_Msg_t txMsg;
  129.         StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  130.         StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  131.         txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_INPUTANALOG;
  132.         txMsg.Header.ModuleId = sns_inputAnalog_ID;
  133.  
  134.         uint16_t AdValue=0;
  135.         /* For each channel */
  136.         for (uint8_t i=0; i<sns_inputAnalog_NUM_SUPPORTED; i++)
  137.         {
  138.             /* Do reading of AD channel */
  139.             switch (i)
  140.             {
  141.                 case 0:
  142.                     AdValue = ADC_Get(sns_inputAnalog0AD);
  143.                     break;
  144.                 case 1:
  145.                     AdValue = ADC_Get(sns_inputAnalog1AD);
  146.                     break;
  147.                 case 2:
  148.                     AdValue = ADC_Get(sns_inputAnalog2AD);
  149.                     break;
  150.                 case 3:
  151.                     AdValue = ADC_Get(sns_inputAnalog3AD);
  152.                     break;
  153.             }
  154.            
  155.             /* If this channel is configured as periodic transmission of voltage */
  156.             if (sns_inputAnalog_Config[i].Type == CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_PERIODICMEASURE)
  157.             {
  158.                 /* Count periodicity */
  159.                 sns_inputAnalog_Sensor[i].PeriodCnt += sns_inputAnalog_POLL_PERIOD_MS;
  160.                 /* If periodicity overflowed or AD value changed more than threshold since last sent value */
  161.                 if (sns_inputAnalog_Sensor[i].PeriodCnt >= sns_inputAnalog_Config[i].Periodicity ||
  162.                     MAX(AdValue,sns_inputAnalog_Sensor[i].LastSentAdVal)-MIN(AdValue,sns_inputAnalog_Sensor[i].LastSentAdVal) > sns_inputAnalog_Config[i].LowTh)
  163.                 //if (sns_inputAnalog_Sensor[i].PeriodCnt >= sns_inputAnalog_Config[i].Periodicity ||
  164.                 //  abs(AdValue-sns_inputAnalog_Sensor[i].LastSentAdVal) > sns_inputAnalog_Config[i].LowTh)
  165.                 {
  166.                     /* Reset periodicity counter */
  167.                     sns_inputAnalog_Sensor[i].PeriodCnt = 0;
  168.                     /* Store value as last sent */
  169.                     sns_inputAnalog_Sensor[i].LastSentAdVal = AdValue;
  170.                    
  171.                     /* send sensor value on CAN with command CAN_MODULE_CMD_PHYSICAL_VOLTAGE */
  172.                     txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_VOLTAGE;
  173.                     txMsg.Length = 3;
  174.                     /* The channel should be transmitted in byte 0 */
  175.                     txMsg.Data[0] = i;
  176.                    
  177.                     uint8_t analogScale = 10;
  178.                     /* Select parameters for AD conversion */
  179.                     switch (i)
  180.                     {
  181.                         case 0:
  182.                             analogScale = sns_inputAnalog0Scale;
  183.                             AdValue = AdValue * sns_inputAnalog0Factor;
  184.                             break;
  185.                         case 1:
  186.                             analogScale = sns_inputAnalog1Scale;
  187.                             AdValue = AdValue * sns_inputAnalog1Factor;
  188.                             break;
  189.                         case 2:
  190.                             analogScale = sns_inputAnalog2Scale;
  191.                             AdValue = AdValue * sns_inputAnalog2Factor;
  192.                             break;
  193.                         case 3:
  194.                             analogScale = sns_inputAnalog3Scale;
  195.                             AdValue = AdValue * sns_inputAnalog3Factor;
  196.                             break;
  197.                     }
  198.                     txMsg.Data[1] = (AdValue>>(analogScale-6+8))&0xff;
  199.                     txMsg.Data[2] = (AdValue>>(analogScale-6))&0xff;
  200.                    
  201.                     /* Send value on CAN */
  202.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
  203.                 }
  204.             }
  205.             /* If this channel is configured as digital input */
  206.             else if (sns_inputAnalog_Config[i].Type == CAN_MODULE_ENUM_INPUTANALOG_ANALOGCONFIG_SETTING_DIGITALINPUT)
  207.             {
  208.                 txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS;
  209.                 txMsg.Length = 2;
  210.                 /* The channel should be transmitted in byte 0 */
  211.                 txMsg.Data[0] = i;
  212.                 /* If status was low but voltage is above high theshold */
  213.                 if (sns_inputAnalog_Sensor[i].Status == LOW && AdValue > sns_inputAnalog_Config[i].HighTh)
  214.                 {
  215.                     /* Consider status to be high */
  216.                     sns_inputAnalog_Sensor[i].Status = HIGH;
  217.                     txMsg.Data[1] = CAN_MODULE_ENUM_PHYSICAL_PINSTATUS_STATUS_HIGH;
  218.                    
  219.                     /* send status on CAN with command CAN_MODULE_CMD_PHYSICAL_PINSTATUS */
  220.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  221.                 }
  222.                 /* If status was high but voltage is below low theshold */
  223.                 else if (sns_inputAnalog_Sensor[i].Status == HIGH && AdValue < sns_inputAnalog_Config[i].LowTh)
  224.                 {
  225.                     /* Consider status to be low */
  226.                     sns_inputAnalog_Sensor[i].Status = LOW;
  227.                     txMsg.Data[1] = CAN_MODULE_ENUM_PHYSICAL_PINSTATUS_STATUS_LOW;
  228.                    
  229.                     /* send status on CAN with command CAN_MODULE_CMD_PHYSICAL_PINSTATUS */
  230.                     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  231.                 }
  232.             }
  233.         }
  234.     }
  235. }
  236.  
  237. void sns_inputAnalog_HandleMessage(StdCan_Msg_t *rxMsg)
  238. {
  239.     if (    StdCan_Ret_class(rxMsg->Header) == CAN_MODULE_CLASS_SNS &&
  240.         StdCan_Ret_direction(rxMsg->Header) == DIRECTIONFLAG_FROM_OWNER &&
  241.         rxMsg->Header.ModuleType == CAN_MODULE_TYPE_SNS_INPUTANALOG &&
  242.         rxMsg->Header.ModuleId == sns_inputAnalog_ID)
  243.     {
  244.         uint8_t index=0;
  245.         switch (rxMsg->Header.Command)
  246.         {
  247.         case CAN_MODULE_CMD_INPUTANALOG_ANALOGCONFIG:
  248.             /* Find sensor id from incoming data */
  249.             index=rxMsg->Data[0]&0x0f;
  250.             /* Check if sensor id is in range */
  251.             if (index < sns_inputAnalog_NUM_SUPPORTED)
  252.             {
  253.                 /* Save all config values */
  254.                 sns_inputAnalog_Config[index].Type=(rxMsg->Data[0]>>4)&0x03;
  255.                 sns_inputAnalog_Config[index].PullupEnable=(rxMsg->Data[0]>>6)&0x01;
  256.                 sns_inputAnalog_Config[index].RefEnable=(rxMsg->Data[0]>>7)&0x01;
  257.                 sns_inputAnalog_Config[index].LowTh=(rxMsg->Data[2])|(rxMsg->Data[1]<<8);
  258.                 sns_inputAnalog_Config[index].HighTh=(rxMsg->Data[4])|(rxMsg->Data[3]<<8);
  259.                 sns_inputAnalog_Config[index].Periodicity=(rxMsg->Data[6])|(rxMsg->Data[5]<<8);
  260.                
  261.                 /* Convert voltage to AD value (0-1023) acording static config parameters */
  262.                 switch (index)
  263.                 {
  264.                     case 0:
  265.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh<<(sns_inputAnalog0Scale-8);
  266.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh / sns_inputAnalog0Factor;
  267.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh<<(sns_inputAnalog0Scale-8);
  268.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh / sns_inputAnalog0Factor;
  269.                         break;
  270.                     case 1:
  271.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh<<(sns_inputAnalog1Scale-8);
  272.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh / sns_inputAnalog1Factor;
  273.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh<<(sns_inputAnalog1Scale-8);
  274.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh / sns_inputAnalog1Factor;
  275.                         break;
  276.                     case 2:
  277.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh<<(sns_inputAnalog2Scale-8);
  278.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh / sns_inputAnalog2Factor;
  279.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh<<(sns_inputAnalog2Scale-8);
  280.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh / sns_inputAnalog2Factor;
  281.                         break;
  282.                     case 3:
  283.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh<<(sns_inputAnalog3Scale-8);
  284.                         sns_inputAnalog_Config[index].LowTh = sns_inputAnalog_Config[index].LowTh / sns_inputAnalog3Factor;
  285.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh<<(sns_inputAnalog3Scale-8);
  286.                         sns_inputAnalog_Config[index].HighTh = sns_inputAnalog_Config[index].HighTh / sns_inputAnalog3Factor;
  287.                         break;
  288.                 }
  289.                
  290.                 /* Store config to eeprom */
  291. #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)
  292.                 eeprom_update_block( &sns_inputAnalog_Config[index], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*index, sizeof(sns_inputAnalog_Config) );
  293. #else
  294.                 eeprom_write_block( &sns_inputAnalog_Config[index], &eeprom_sns_inputAnalog+sizeof(sns_inputAnalog_Config)*index, sizeof(sns_inputAnalog_Config) );
  295.                 #warning Using old version of AVRlibc, does not support eeprom_update-functions
  296. #endif
  297.             }
  298.             break;
  299.         }
  300.         /* Set pullups according config */
  301.         setPullups();
  302.         /* Set gnd references according config */
  303.         setReferences();
  304.     }
  305. }
  306.  
  307. void sns_inputAnalog_List(uint8_t ModuleSequenceNumber)
  308. {
  309.     StdCan_Msg_t txMsg;
  310.    
  311.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
  312.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  313.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_INPUTANALOG;
  314.     txMsg.Header.ModuleId = sns_inputAnalog_ID;
  315.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  316.     txMsg.Length = 6;
  317.  
  318.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  319.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  320.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  321.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  322.    
  323.     txMsg.Data[4] = NUMBER_OF_MODULES;
  324.     txMsg.Data[5] = ModuleSequenceNumber;
  325.    
  326.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  327. }
  328.