Subversion Repositories HomeAutomation

Rev

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