Subversion Repositories HomeAutomation

Rev

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

  1. /**
  2.  * CanBlinds.
  3.  * Takes incomming packages and adjusts PWM output.
  4.  * Input: -128 to +127
  5.  * Position msg: <byte0 BLINDS_CMD> <byte1 position>
  6.  * Turning msg: <byte0 START/STOP> <byte 1 direction>
  7.  *
  8.  * @date    2001-01-01
  9.  * @author  Erik Larsson
  10.  */
  11.  
  12. #define DEBUG           0 /* Prints debug messages to uart */
  13. #define TWO_BUTTON_MODE 0 /* If using two (or just one but nothing more) auxiliary buttons */
  14.  
  15. /*-----------------------------------------------------------------------------
  16.  * Includes
  17.  *---------------------------------------------------------------------------*/
  18. /* system files */
  19. #include <avr/io.h>
  20. #include <avr/interrupt.h>
  21. #include <avr/wdt.h>
  22. #include <stdio.h>
  23. /* lib files */
  24. #include <can.h>
  25. #if DEBUG
  26. #include <serial.h>
  27. #endif
  28. #include <timebase.h>
  29.  
  30. #include <tc1047.h>
  31. #include <rc_servo.h>
  32.  
  33. /* defines */
  34. #define FAILSAFE_MODE       0x0F
  35. #define FAILSAFE_TRESHOLD   60  /* Degrees celcius when nodeBlinds goes into failsafe mode */
  36.  
  37. #define BLINDS_CMD_GET      0x1300
  38. #define BLINDS_CMD_SEND     0x1301
  39.  
  40. #define BLINDS_CMD_ABS      0x01 /* Absolute position */
  41. #define BLINDS_CMD_REL      0x02 /* Relative position */
  42. #define BLINDS_CMD_START    0x03 /* Start turning RC-servo */
  43. #define BLINDS_CMD_STOP     0x04 /* Stop turning RC-servo */
  44. #define BLINDS_CMD_RESET    0x05
  45. #define BLINDS_CMD_STATUS   0x06
  46.  
  47. #define BLINDS_TURN_STOP    0x00
  48. #define BLINDS_TURN_LEFT    0x01
  49. #define BLINDS_TURN_RIGHT   0x02
  50.  
  51. #define STEPS_PER_TURN_PERIOD 10 /* number of steps for each adjustment */
  52. #define TURN_PERIOD         100 /* milliseconds */
  53. #define STATUS_SEND_PERIOD  10000 /* milliseconds */
  54. #define FAILSAFE_SEND_PERIOD    10000 /* milliseconds */
  55. #define BOUNCE_TIME         10 /* milliseconds */
  56. #define BUTTON_ID           0x1202
  57. #define BUTTON1             1
  58. #define BUTTON2             2
  59.  
  60. /*-------------------------------------------------------------------------
  61.  * Global variables
  62.  * -----------------------------------------------------------------------*/
  63. #if TWO_BUTTON_MODE
  64. Can_Message_t txMsg_Button;
  65. #endif
  66.  
  67. /*----------------------------------------------------------------------------
  68.  * Functions
  69.  * -------------------------------------------------------------------------*/
  70. void blindsFailsafe();
  71.  
  72. /*----------------------------------------------------------------------------
  73.  * Interrupt routines
  74.  * -------------------------------------------------------------------------*/
  75. #if TWO_BUTTON_MODE
  76. ISR( PCINT2_vect )
  77. {
  78.     /*
  79.      * Auxiliary button pressed and released
  80.      * Check time between press and release to eliminate bounces
  81.      */
  82.     static uint32_t buttonTime[2];
  83.  
  84.     txMsg_Button.RemoteFlag = 0;
  85.     txMsg_Button.ExtendedFlag = 1;
  86.  
  87.     if( (PIND & (1<<PD6)) == 0){
  88.         /* Button pressed */
  89.         buttonTime[0] = Timebase_CurrentTime();
  90. #if DEBUG
  91.         printf("Button 1 pressed\n");
  92. #endif
  93.     }else if( (PIND & (1<<PD6)) == 1){
  94.         if( Timebase_PassedTimeMillis( buttonTime[0] ) >= BOUNCE_TIME ){
  95.             /* No bounce, send message */
  96.             txMsg_Button.Id = BUTTON_ID;
  97.             txMsg_Button.DataLength = 1;
  98.             txMsg_Button.Data.bytes[0] = BUTTON1;
  99. #if DEBUG
  100.             printf("Button 1 pressed: message sent\n");
  101. #endif
  102.             return;
  103.         }else{
  104.             /* Just bounces, ignore it */
  105. #if DEBUG
  106.             printf("Button 1 just bounced\n");
  107. #endif
  108.             return;
  109.         }
  110.     }
  111.     if( (PIND & (1<<PD7)) == 0){
  112.         /* Button pressed */
  113.         buttonTime[1] = Timebase_CurrentTime();
  114. #if DEBUG
  115.         printf("Button 2 pressed\n");
  116. #endif
  117.     }else if( (PIND & (1<<PD7)) == 1){
  118.         if( Timebase_PassedTimeMillis( buttonTime[1] ) >= BOUNCE_TIME ){
  119.             /* No bounce, send message */
  120.             txMsg_Button.Id = BUTTON_ID;
  121.             txMsg_Button.DataLength = 1;
  122.             txMsg_Button.Data.bytes[0] = BUTTON2;
  123. #if DEBUG
  124.             printf("Button 2 pressed: message sent\n");
  125. #endif
  126.             return;
  127.         }else{
  128.             /* Just bounces, ignore it */
  129. #if DEBUG
  130.             printf("Button 2 just bounced\n");
  131. #endif
  132.             return;
  133.         }
  134.     }
  135. }
  136. #endif
  137.  
  138. /*-----------------------------------------------------------------------------
  139.  * Main Program
  140.  *---------------------------------------------------------------------------*/
  141. int main(void) {
  142.  
  143.     uint8_t blindsStatus, /* Position (-128 to 127) */
  144.             turnDirection = BLINDS_TURN_STOP; /* Specifies direction to turn or stopped */
  145.     uint32_t boardTemperature = 0;
  146.     uint32_t timeStamp = 0, timeStampTurn = 0;
  147.  
  148.     adcTemperatureInit();
  149.     Timebase_Init();
  150.     rcServoInit();
  151. #if DEBUG
  152.     Serial_Init();
  153. #endif
  154.  
  155. #if TWO_BUTTON_MODE
  156.     /*
  157.      * Initialize buttons
  158.      * It is possible to use ie. sensors instead
  159.      * but then change this
  160.      */
  161.     /* Set as input and enable pull-up */
  162.     DDRD &= ~( (1<<DDD6)|(1<<DDD7) );
  163.     PORTD |= (1<<PD6)|(1<<PD7);
  164.  
  165.     /* Enable IO-pin interrupt */
  166.     PCICR |= (1<<PCIE1);
  167.     /* Unmask PD6 and PD7 */
  168.     PCMSK2 |= (1<<PCINT22) | (1<<PCINT23);
  169. #endif
  170.     sei();
  171. #if DEBUG
  172.     printf("\n------------------------------------------------------------\n");
  173.     printf(  "   CAN: Blinds\n");
  174.     printf(  "------------------------------------------------------------\n");
  175.  
  176.     printf("CanInit...");
  177.     if (Can_Init() != CAN_OK) {
  178.         printf("FAILED!\n");
  179.     }else{
  180.         printf("OK!\n");
  181.     }
  182. #else
  183.     Can_Init();
  184. #endif
  185.  
  186.     Can_Message_t txMsg;
  187.     Can_Message_t rxMsg;
  188.     txMsg.Id = BLINDS_CMD_SEND;
  189.     txMsg.RemoteFlag = 0;
  190.     txMsg.ExtendedFlag = 1;
  191.     txMsg.DataLength = 3;
  192.  
  193.     /* main loop */
  194.     while (1) {
  195.         /* service the CAN routines */
  196.         Can_Service();
  197.  
  198.         /* check if any messages have been received */
  199.         while (Can_Receive(&rxMsg) == CAN_OK) {
  200.             /* This node that control a servo is adressed */
  201.             if( rxMsg.Id == BLINDS_CMD_GET ){
  202.  
  203.                 if( rxMsg.Data.bytes[0] == BLINDS_CMD_ABS ){
  204.                     /* Set absolute position to servo */
  205.                     setPosition( rxMsg.Data.bytes[1] );
  206.  
  207.                 }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_REL){
  208.                     /* Set relative position to servo */
  209.                     alterPosition( rxMsg.Data.bytes[1] );
  210.  
  211.                 }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_START ){
  212.                     /* Start turning the servo */
  213.                     turnDirection = rxMsg.Data.bytes[1];
  214.  
  215.                 }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_STOP ){
  216.                     /* Stop turning */
  217.                     turnDirection = BLINDS_TURN_STOP;
  218.  
  219.                 }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_STATUS){
  220.                     /* Send blinds status to CAN */
  221.                     boardTemperature = getTC1047temperature();
  222.  
  223.                     if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  224.                         blindsFailsafe();
  225.                     }else{
  226.                         txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  227.                         txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  228.                         txMsg.Data.bytes[2] = getPosition();
  229.  
  230.                         Can_Send( &txMsg );
  231.                     }
  232.                 }
  233.             }
  234.         }
  235.  
  236.         if( Timebase_PassedTimeMillis(timeStamp) >= STATUS_SEND_PERIOD ){
  237.             timeStamp = Timebase_CurrentTime();
  238.             /* Send blinds status to CAN */
  239.  
  240.             boardTemperature = getTC1047temperature();
  241.  
  242.             if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  243.                 blindsFailsafe();
  244.             }else{
  245.                 txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  246.                 txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  247.                 txMsg.Data.bytes[2] = getPosition();
  248.  
  249.                 Can_Send( &txMsg );
  250. #if DEBUG
  251.                 printf("Periodic message sent...\n");
  252.                 printf("Temperature: %d\nBlinds status: %u\n", boardTemperature, getPosition());
  253. #endif
  254.             }
  255.         }
  256.         /* If start turning servo */
  257.         if( turnDirection ){
  258.             if( Timebase_PassedTimeMillis( timeStampTurn ) >= TURN_PERIOD ){
  259.                 timeStampTurn = Timebase_CurrentTime();
  260.                 /* Clockwise or counterclockwise? */
  261.                 if( turnDirection == BLINDS_TURN_LEFT ){
  262.                     alterPosition( -STEPS_PER_TURN_PERIOD );
  263.                 }else if( turnDirection == BLINDS_TURN_RIGHT ){
  264.                     alterPosition( STEPS_PER_TURN_PERIOD );
  265.                 }
  266.             }
  267.         }
  268.     }
  269.     return 0;
  270. }
  271.  
  272. void blindsFailsafe() // TODO fixa failsafe, vad ska hända med PWM?
  273. {
  274.     uint8_t relayStatus;
  275.     uint32_t boardTemperature = 0, timeStamp = 0;
  276.  
  277.     Can_Message_t txMsg;
  278.     Can_Message_t rxMsg;
  279.     txMsg.Id = BLINDS_CMD_SEND;
  280.     txMsg.RemoteFlag = 0;
  281.     txMsg.ExtendedFlag = 1;
  282.     txMsg.DataLength = 4;
  283.  
  284.     while(1){
  285.         /* service the CAN routines */
  286.         Can_Service();
  287.  
  288.         /* check if any messages have been received */
  289.         while (Can_Receive(&rxMsg) == CAN_OK) {
  290.             /* This relay is adressed*/
  291.             if( rxMsg.Id == BLINDS_CMD_GET ){
  292.                 if( rxMsg.Data.bytes[0] == BLINDS_CMD_RESET ){
  293.                     /* Return from failsafe mode */
  294.                     return;
  295.                 }
  296.             }
  297.         }
  298.  
  299.         if( Timebase_PassedTimeMillis(timeStamp) >= FAILSAFE_SEND_PERIOD ){
  300.             timeStamp = Timebase_CurrentTime();
  301.             /* Send relay status to CAN */
  302. #if DEBUG
  303.             printf("Failsafe mode!\n");
  304. #endif
  305.             boardTemperature = getTC1047temperature();
  306.  
  307.             txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  308.             txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  309.             txMsg.Data.bytes[2] = getPosition();
  310.             txMsg.Data.bytes[3] = FAILSAFE_MODE;
  311.  
  312.             Can_Send( &txMsg );
  313.         }
  314.     }
  315. }
  316.  
  317.