Subversion Repositories HomeAutomation

Rev

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