Subversion Repositories HomeAutomation

Rev

Rev 196 | Blame | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * CAN Relay.
  3.  *
  4.  *
  5.  * @date    2006-12-17
  6.  * @author  Erik Larsson
  7.  *
  8.  *   ADC=Vin*1024/Vref
  9.  *   Vout=( 10 mV/C )( Temperature C ) + 500 mV
  10.  *
  11.  *  Transmitts: DATA: <temperature low byte> <temperature high byte> <relay status> <failsafe mode>
  12.  *
  13.  *
  14.  */
  15.  
  16. #define TWO_BUTTON_MODE 0 /* If using two (or just one but nothing more) auxiliary buttons */
  17.  
  18. /*-----------------------------------------------------------------------------
  19.  * Includes
  20.  *---------------------------------------------------------------------------*/
  21. /* system files */
  22. #include <avr/io.h>
  23. #include <avr/interrupt.h>
  24. #include <stdio.h>
  25. /* lib files */
  26. #include <bios.h>
  27. #include <tc1047.h>
  28. #include <funcdefs.h>
  29.  
  30. /* defines */
  31. #define GROUP_ID        0x01
  32.  
  33. #define RELAY_OFF           0x01
  34. #define RELAY_ON            0x02
  35. #define FAILSAFE_MODE       0x0F
  36. #define FAILSAFE_TRESHOLD   60  /* Degrees when nodeRelay goes into failsafe mode */
  37.  
  38. #define RELAY_CMD_ON        0x01
  39. #define RELAY_CMD_OFF       0x02
  40. #define RELAY_CMD_TOGGLE    0x03
  41. #define RELAY_CMD_STATUS    0x04
  42. #define RELAY_CMD_RESET     0x05
  43. #define STATUS_SEND_PERIOD  10000 /* milliseconds */
  44. #define FAILSAFE_SEND_PERIOD    10000 /* milliseconds */
  45. #define BOUNCE_TIME         10 /* milliseconds */
  46. #define BUTTON1             1
  47. #define BUTTON2             2
  48.  
  49. /*-------------------------------------------------------------------------
  50.  * Global variables
  51.  * -----------------------------------------------------------------------*/
  52. #if TWO_BUTTON_MODE
  53. Can_Message_t txMsg_Button;
  54. #endif
  55.  
  56. uint8_t relayStatus, failsafe_flag;
  57. uint32_t boardTemperature = 0;
  58. Can_Message_t txMsg;
  59.  
  60. /*----------------------------------------------------------------------------
  61.  * Functions
  62.  * -------------------------------------------------------------------------*/
  63. uint8_t relayOff();
  64. uint8_t relayOn();
  65. void relayFailsafe();
  66.  
  67. void can_receive(Can_Message_t *msg){
  68.     uint32_t act;
  69.     uint8_t m, act_type, group, node;
  70.  
  71.     if( ((msg->Id & CLASS_MASK)>>CLASS_MASK_BITS) == CLASS_ACT){
  72.  
  73.         act = (msg->Id & TYPE_MASK) >> TYPE_MASK_BITS;
  74.         act_type = (act & ACT_TYPE_MASK) >> ACT_TYPE_BITS;
  75.         group = (act & ACT_GROUP_MASK) >> ACT_GROUP_BITS;
  76.         node = (act & ACT_NODE_MASK) >> ACT_NODE_BITS;
  77.  
  78.         if( act_type == ACT_TYPE_RELAY && (group == GROUP_ID || node == NODE_ID) ){
  79.             if(msg->Data.bytes[0] == RELAY_CMD_ON){
  80.                 // Turn relay on
  81.                 relayStatus = relayOn();
  82.  
  83.             }else if(msg->Data.bytes[0] == RELAY_CMD_OFF){
  84.                 // Turn relay off
  85.                 relayStatus = relayOff();
  86.  
  87.             }else if(msg->Data.bytes[0] == RELAY_CMD_TOGGLE ){
  88.                     // Toggle relay
  89.                     if(relayStatus == RELAY_OFF){
  90.                         relayStatus = relayOn();
  91.                     }else{
  92.                         relayStatus = relayOff();
  93.                     }
  94.  
  95.             }else if(msg->Data.bytes[0] == RELAY_CMD_STATUS){
  96.                 // Send relay status to CAN
  97.                 boardTemperature = getTC1047temperature();
  98.  
  99.                 if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  100.                     // Goto failsafe mode
  101.                     relayFailsafe();
  102.                 }else{
  103.                     // Transmitt node status
  104.                     txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  105.                     txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  106.                     txMsg.Data.bytes[2] = relayStatus;
  107.                     txMsg.DataLength = 3;
  108.                     bios->can_send( &txMsg );
  109.                 }
  110.             }else if(msg->Data.bytes[0] == RELAY_CMD_RESET){
  111.                 // Return to normal operation
  112.                 failsafe_flag = 1;
  113.             }
  114.         }
  115.     }
  116. }
  117.  
  118. /*----------------------------------------------------------------------------
  119.  * Interrupt routines // FIXME ordna och testa tryckknappar/rotary encoder
  120.  * -------------------------------------------------------------------------*/
  121. #if TWO_BUTTON_MODE
  122. ISR( PCINT2_vect )
  123. {
  124.     /*
  125.      * Auxiliary button pressed and released
  126.      * Check time between press and release to eliminate bounces
  127.      */
  128.     static uint32_t buttonTime[2];
  129.  
  130.     txMsg_Button.RemoteFlag = 0;
  131.     txMsg_Button.ExtendedFlag = 1;
  132.  
  133.     if( (PIND & (1<<PD6)) == 0){
  134.         /* Button pressed */
  135.         buttonTime[0] = Timebase_CurrentTime();
  136.     }else if( (PIND & (1<<PD6)) == 1){
  137.         if( Timebase_PassedTimeMillis( buttonTime[0] ) >= BOUNCE_TIME ){
  138.             /* No bounce, send message */
  139.             txMsg_Button.Id = BUTTON_ID;
  140.             txMsg_Button.DataLength = 1;
  141.             txMsg_Button.Data.bytes[0] = BUTTON1;
  142.             return;
  143.         }else{
  144.             /* Just bounces, ignore it */
  145.             return;
  146.         }
  147.     }
  148.     if( (PIND & (1<<PD7)) == 0){
  149.         /* Button pressed */
  150.         buttonTime[1] = Timebase_CurrentTime();
  151.     }else if( (PIND & (1<<PD7)) == 1){
  152.         if( Timebase_PassedTimeMillis( buttonTime[1] ) >= BOUNCE_TIME ){
  153.             /* No bounce, send message */
  154.             txMsg_Button.Id = BUTTON_ID;
  155.             txMsg_Button.DataLength = 1;
  156.             txMsg_Button.Data.bytes[0] = BUTTON2;
  157.             return;
  158.         }else{
  159.             /* Just bounces, ignore it */
  160.             return;
  161.         }
  162.     }
  163. }
  164. #endif
  165.  
  166. /*-----------------------------------------------------------------------------
  167.  * Main Program
  168.  *---------------------------------------------------------------------------*/
  169. int main(void) {
  170.  
  171.     adcTemperatureInit();
  172.  
  173. #if TWO_BUTTON_MODE
  174. #error two button mode not yet tested
  175.     /*
  176.      * Initialize buttons
  177.      * It is possible to use ie. sensors instead
  178.      * but then change this
  179.      */
  180.     // Set as input and enable pull-up
  181.     DDRD &= ~( (1<<DDD6)|(1<<DDD7) );
  182.     PORTD |= (1<<PD6)|(1<<PD7);
  183.  
  184.     // Enable IO-pin interrupt
  185.     PCICR |= (1<<PCIE1);
  186.     // Unmask PD6 and PD7
  187.     PCMSK2 |= (1<<PCINT22) | (1<<PCINT23);
  188. #endif
  189.  
  190.     // Control channel for relay
  191.     DDRC |= (1<<DDC1);
  192.  
  193.     // Set up callback for CAN messages
  194.     bios->can_callback = &can_receive;
  195.  
  196.     sei();
  197.  
  198.     // Turn relay off
  199.     relayStatus = relayOff();
  200.  
  201.     uint32_t timeStamp = 0;
  202.  
  203.     txMsg.RemoteFlag = 0;
  204.     txMsg.ExtendedFlag = 1;
  205.     txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_STATUS_RELAY<<TYPE_MASK_BITS )|(NODE_ID);
  206.  
  207.     // Main loop
  208.     while (1) {
  209.  
  210.         if( bios->timebase_get() - timeStamp >= STATUS_SEND_PERIOD ){
  211.             timeStamp = bios->timebase_get();
  212.             // Send relay status to CAN
  213.  
  214.             boardTemperature = getTC1047temperature();
  215.  
  216.             if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  217.                 relayFailsafe();
  218.             }else{
  219.                 txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  220.                 txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  221.                 txMsg.Data.bytes[2] = relayStatus;
  222.                 txMsg.DataLength = 3;
  223.                 bios->can_send( &txMsg );
  224.             }
  225.         }
  226.     }
  227.     return 0;
  228. }
  229.  
  230. uint8_t relayOff()
  231. {
  232.     // Turn off relay
  233.     PORTC &= ~(1<<PC1);
  234.  
  235.     return RELAY_OFF;
  236. }
  237.  
  238. uint8_t relayOn()
  239. {
  240.     // Turn on relay
  241.     PORTC |= (1<<PC1);
  242.  
  243.     return RELAY_ON;
  244. }
  245.  
  246. void relayFailsafe()
  247. {
  248.     uint32_t timeStamp = 0;
  249.  
  250.     relayStatus = relayOff();
  251.     failsafe_flag = 0;
  252.  
  253.     while(1){
  254.  
  255.         if( failsafe_flag ){
  256.             // Return from failsafe mode
  257.             return;
  258.         }
  259.  
  260.         if( bios->timebase_get() - timeStamp >= FAILSAFE_SEND_PERIOD ){
  261.             timeStamp = bios->timebase_get();
  262.             // Send relay status to CAN
  263.             boardTemperature = getTC1047temperature();
  264.  
  265.             txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  266.             txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  267.             txMsg.Data.bytes[2] = relayStatus;
  268.             txMsg.Data.bytes[3] = FAILSAFE_MODE;
  269.  
  270.             bios->can_send( &txMsg );
  271.         }
  272.     }
  273. }
  274.  
  275.