Subversion Repositories HomeAutomation

Rev

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