Subversion Repositories HomeAutomation

Rev

Rev 190 | Rev 196 | 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.  *   Observera! Applikationen är endast testad på labplatta med m88, pot och lysdiod
  9.  *
  10.  *   ADC=Vin*1024/Vref
  11.  *   Vout=( 10 mV/C )( Temperature C ) + 500 mV
  12.  *
  13.  *  Transmitts: DATA: <temperature low byte> <temperature high byte> <relay status> <failsafe mode>
  14.  *
  15.  *
  16.  */
  17.  
  18. #define DEBUG           1 /* Prints debug messages to uart */
  19. #define TWO_BUTTON_MODE 1 /* If using two (or just one but nothing more) auxiliary buttons */
  20.  
  21. /*-----------------------------------------------------------------------------
  22.  * Includes
  23.  *---------------------------------------------------------------------------*/
  24. /* system files */
  25. #include <avr/io.h>
  26. #include <avr/interrupt.h>
  27. #include <avr/wdt.h>
  28. #include <stdio.h>
  29. /* lib files */
  30. #include <can.h>
  31. #include <serial.h>
  32. #include <timebase.h>
  33.  
  34. #include <tc1047.h>
  35.  
  36. /* defines */
  37. #define RELAY_OFF           0x01
  38. #define RELAY_ON            0x02
  39. #define FAILSAFE_MODE       0x0F
  40. #define FAILSAFE_TRESHOLD   60  /* Degrees when nodeRelay goes into failsafe mode */
  41.  
  42. #define RELAY_CMD_GET       0x1200
  43. #define RELAY_CMD_SEND      0x1201
  44. #define RELAY_CMD_ON        0x01
  45. #define RELAY_CMD_OFF       0x02
  46. #define RELAY_CMD_TOGGLE    0x03
  47. #define RELAY_CMD_STATUS    0x04
  48. #define RELAY_CMD_RESET     0x05
  49. #define STATUS_SEND_PERIOD  10000 /* milliseconds */
  50. #define FAILSAFE_SEND_PERIOD    10000 /* milliseconds */
  51. #define BOUNCE_TIME         10 /* milliseconds */
  52. #define BUTTON_ID           0x1202
  53. #define BUTTON1             1
  54. #define BUTTON2             2
  55.  
  56. /*-------------------------------------------------------------------------
  57.  * Global variables
  58.  * -----------------------------------------------------------------------*/
  59. #if TWO_BUTTON_MODE
  60. Can_Message_t txMsg_Button;
  61. #endif
  62.  
  63. /*----------------------------------------------------------------------------
  64.  * Functions
  65.  * -------------------------------------------------------------------------*/
  66. uint8_t relayOff();
  67. uint8_t relayOn();
  68. void relayFailsafe();
  69.  
  70. /*----------------------------------------------------------------------------
  71.  * Interrupt routines
  72.  * -------------------------------------------------------------------------*/
  73. #if TWO_BUTTON_MODE
  74. ISR( PCINT2_vect )
  75. {
  76.     /*
  77.      * Auxiliary button pressed and released
  78.      * Check time between press and release to eliminate bounces
  79.      */
  80.     static uint32_t buttonTime[2];
  81.  
  82.     txMsg_Button.RemoteFlag = 0;
  83.     txMsg_Button.ExtendedFlag = 1;
  84.  
  85.     if( (PIND & (1<<PD6)) == 0){
  86.         /* Button pressed */
  87.         buttonTime[0] = Timebase_CurrentTime();
  88. #if DEBUG
  89.         printf("Button 1 pressed\n");
  90. #endif
  91.     }else if( (PIND & (1<<PD6)) == 1){
  92.         if( Timebase_PassedTimeMillis( buttonTime[0] ) >= BOUNCE_TIME ){
  93.             /* No bounce, send message */
  94.             txMsg_Button.Id = BUTTON_ID;
  95.             txMsg_Button.DataLength = 1;
  96.             txMsg_Button.Data.bytes[0] = BUTTON1;
  97. #if DEBUG
  98.             printf("Button 1 pressed: message sent\n");
  99. #endif
  100.             return;
  101.         }else{
  102.             /* Just bounces, ignore it */
  103. #if DEBUG
  104.             printf("Button 1 just bounced\n");
  105. #endif
  106.             return;
  107.         }
  108.     }
  109.     if( (PIND & (1<<PD7)) == 0){
  110.         /* Button pressed */
  111.         buttonTime[1] = Timebase_CurrentTime();
  112. #if DEBUG
  113.         printf("Button 2 pressed\n");
  114. #endif
  115.     }else if( (PIND & (1<<PD7)) == 1){
  116.         if( Timebase_PassedTimeMillis( buttonTime[1] ) >= BOUNCE_TIME ){
  117.             /* No bounce, send message */
  118.             txMsg_Button.Id = BUTTON_ID;
  119.             txMsg_Button.DataLength = 1;
  120.             txMsg_Button.Data.bytes[0] = BUTTON2;
  121. #if DEBUG
  122.             printf("Button 2 pressed: message sent\n");
  123. #endif
  124.             return;
  125.         }else{
  126.             /* Just bounces, ignore it */
  127. #if DEBUG
  128.             printf("Button 2 just bounced\n");
  129. #endif
  130.             return;
  131.         }
  132.     }
  133. }
  134. #endif
  135.  
  136. //ISR( ADC_vect )
  137. //{
  138.     /*
  139.      * ADC conversion completed
  140.      */
  141.     // TODO använd denna rutin för att läsa värde när omvandlingen är klar
  142.  
  143. //}
  144.  
  145. /*-----------------------------------------------------------------------------
  146.  * Main Program
  147.  *---------------------------------------------------------------------------*/
  148. int main(void) {
  149.  
  150.     uint8_t relayStatus;
  151.     uint32_t boardTemperature = 0;
  152.  
  153.     adcTemperatureInit();
  154.  
  155.     Timebase_Init();
  156. #if DEBUG
  157.     Serial_Init();
  158. #endif
  159.  
  160. #if TWO_BUTTON_MODE
  161.     /*
  162.      * Initialize buttons
  163.      * It is possible to use ie. sensors instead
  164.      * but then change this
  165.      */
  166.     /* Set as input and enable pull-up */
  167.     DDRD &= ~( (1<<DDD6)|(1<<DDD7) );
  168.     PORTD |= (1<<PD6)|(1<<PD7);
  169.  
  170.     /* Enable IO-pin interrupt */
  171.     PCICR |= (1<<PCIE1);
  172.     /* Unmask PD6 and PD7 */
  173.     PCMSK2 |= (1<<PCINT22) | (1<<PCINT23);
  174.         /* Button pressed */
  175. #endif
  176.  
  177.  
  178.     sei();
  179.  
  180.     /* Turn relay off */
  181.     relayStatus = relayOff();
  182.  
  183. #if DEBUG
  184.     printf("\n------------------------------------------------------------\n");
  185.     printf(  "   CAN: Relay\n");
  186.     printf(  "------------------------------------------------------------\n");
  187.  
  188.  
  189.     printf("CanInit...");
  190.     if (Can_Init() != CAN_OK) {
  191.         printf("FAILED!\n");
  192.     }else{
  193.         printf("OK!\n");
  194.     }
  195. #else
  196.     Can_Init();
  197. #endif
  198.     uint32_t timeStamp = 0;
  199.  
  200.     Can_Message_t txMsg;
  201.     Can_Message_t rxMsg;
  202.     txMsg.Id = RELAY_CMD_SEND;
  203.     txMsg.RemoteFlag = 0;
  204.     txMsg.ExtendedFlag = 1;
  205.     txMsg.DataLength = 3;
  206.  
  207.     /* main loop */
  208.     while (1) {
  209.         /* service the CAN routines */
  210.         Can_Service();
  211.  
  212.         /* check if any messages have been received */
  213.         while (Can_Receive(&rxMsg) == CAN_OK) {
  214.             /* This relay is adressed*/
  215.             if( rxMsg.Id == RELAY_CMD_GET ){
  216.  
  217.                 if( rxMsg.Data.bytes[0] == RELAY_CMD_ON ){
  218.                     /* Turn relay on */
  219.                     relayStatus = relayOn();
  220.  
  221.                 }else if(rxMsg.Data.bytes[0] == RELAY_CMD_OFF){
  222.                     /* Turn relay off */
  223.                     relayStatus = relayOff();
  224.  
  225.                 }else if(rxMsg.Data.bytes[0] == RELAY_CMD_TOGGLE ){
  226.                     /* Toggle relay */
  227.  
  228.                     if(relayStatus == RELAY_OFF){
  229.                         relayStatus = relayOn();
  230.                     }else{
  231.                         relayStatus = relayOff();
  232.                     }
  233.  
  234.                 }else if(rxMsg.Data.bytes[0] == RELAY_CMD_STATUS){
  235.                     /* Send relay status to CAN */
  236.  
  237.                     boardTemperature = getTC1047temperature();
  238.  
  239.                     if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  240.                         relayFailsafe();
  241.                     }else{
  242.                         txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  243.                         txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  244.                         txMsg.Data.bytes[2] = relayStatus;
  245.  
  246.                         Can_Send( &txMsg );
  247.                     }
  248.                 }
  249.             }
  250.         }
  251.  
  252.         if( Timebase_PassedTimeMillis(timeStamp) >= STATUS_SEND_PERIOD ){
  253.             timeStamp = Timebase_CurrentTime();
  254.             /* Send relay status to CAN */
  255.  
  256.             boardTemperature = getTC1047temperature();
  257.  
  258.             if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  259.                 relayFailsafe();
  260.             }else{
  261.                 txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  262.                 txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  263.                 txMsg.Data.bytes[2] = relayStatus;
  264.  
  265.                 Can_Send( &txMsg );
  266. #if DEBUG
  267.                 printf("Periodic message sent...\n");
  268.                 printf("Temperature: %d\nRelay status: %u\n", boardTemperature, relayStatus);
  269. #endif
  270.             }
  271.         }
  272.     }
  273.     return 0;
  274. }
  275.  
  276. uint8_t relayOff()
  277. {
  278.     /* Set as output and sink */
  279.     PORTC &= ~(1<<PC1);
  280.     DDRC |= (1<<DDC1);
  281.  
  282. #if DEBUG
  283.     printf("relay turned off\n");
  284. #endif
  285.  
  286.     return RELAY_OFF;
  287. }
  288.  
  289. uint8_t relayOn()
  290. {
  291.     /* Set as input and enable pull-up */
  292.     DDRC &= ~(1<<DDC1);
  293.     PORTC |= (1<<PC1);
  294.  
  295. #if DEBUG
  296.     printf("relay turned on\n");
  297. #endif
  298.  
  299.     return RELAY_ON;
  300. }
  301.  
  302. void relayFailsafe()
  303. {
  304.     uint8_t relayStatus;
  305.     uint32_t boardTemperature = 0, timeStamp = 0;
  306.  
  307.     Can_Message_t txMsg;
  308.     Can_Message_t rxMsg;
  309.     txMsg.Id = RELAY_CMD_SEND;
  310.     txMsg.RemoteFlag = 0;
  311.     txMsg.ExtendedFlag = 1;
  312.     txMsg.DataLength = 4;
  313.  
  314.     relayStatus = relayOff();
  315.  
  316.     while(1){
  317.         /* service the CAN routines */
  318.         Can_Service();
  319.  
  320.         /* check if any messages have been received */
  321.         while (Can_Receive(&rxMsg) == CAN_OK) {
  322.             /* This relay is adressed*/
  323.             if( rxMsg.Id == RELAY_CMD_GET ){
  324.                 if( rxMsg.Data.bytes[0] == RELAY_CMD_RESET ){
  325.                     /* Return from failsafe mode */
  326.                     return;
  327.                 }
  328.             }
  329.         }
  330.  
  331.         if( Timebase_PassedTimeMillis(timeStamp) >= FAILSAFE_SEND_PERIOD ){
  332.             timeStamp = Timebase_CurrentTime();
  333.             /* Send relay status to CAN */
  334. #if DEBUG
  335.             printf("Failsafe mode!\n");
  336. #endif
  337.             boardTemperature = getTC1047temperature();
  338.  
  339.             txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  340.             txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  341.             txMsg.Data.bytes[2] = relayStatus;
  342.             txMsg.Data.bytes[3] = FAILSAFE_MODE;
  343.  
  344.             Can_Send( &txMsg );
  345.         }
  346.     }
  347. }
  348.  
  349.