Subversion Repositories HomeAutomation

Rev

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

  1. /**
  2.  * CAN Servo.
  3.  *
  4.  * Input: 0 to 255
  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    2007-01-01
  9.  * @author  Erik Larsson
  10.  *
  11.  */
  12.  
  13. //#define TWO_BUTTON_MODE /* 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 <inttypes.h>
  22. #include <stdio.h>
  23. /* lib files */
  24. #include <bios.h>
  25. #include <config.h>
  26. #include <drivers/timer/timebase.h>
  27.  
  28. //#include <funcdefs.h>
  29.  
  30. /* defines */
  31. #define SERVOID_1 0x1
  32. #define SERVOID_2 0x2
  33. #define SERVOID_3 0x3
  34.  
  35. //#define GROUP_ID  0x01L // FIXME
  36.  
  37. #define FAILSAFE_MODE       0x0F
  38. #define FAILSAFE_TRESHOLD   50  // Degrees celcius when nodeBlinds goes into failsafe mode
  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 // ms
  53. #define STATUS_SEND_PERIOD      5000 // ms
  54. #define FAILSAFE_SEND_PERIOD    10000 // ms
  55. #define BOUNCE_TIME             10 // ms
  56. #define SERVO_FEED_TIME         5000 // ms
  57. #define BUTTON1                 1
  58. #define BUTTON2                 2
  59.  
  60. #define SERVO_FEED_PORT         PORTD
  61. #define SERVO_FEED_DDR          DDRD
  62. #define SERVO_FEED_PIN          PD2
  63.  
  64. #define APP_TYPE    CAN_APPTYPES_SERVO
  65. #define APP_VERSION 0x0001
  66.  
  67.  
  68. /*-------------------------------------------------------------------------
  69.  * Global variables
  70.  * -----------------------------------------------------------------------*/
  71. /*#if defined(TWO_BUTTON_MODE)
  72. Can_Message_t txMsg_Button;
  73. #endif*/
  74.  
  75. volatile uint8_t rxMsgFull;
  76.  
  77. volatile Can_Message_t rxMsg;
  78.  
  79. /*----------------------------------------------------------------------------
  80.  * Functions
  81.  * -------------------------------------------------------------------------*/
  82. void blindsFailsafe();
  83.  
  84. void can_receive(Can_Message_t *msg){
  85. // CAN callback function
  86.     if(!rxMsgFull){
  87.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  88.         rxMsgFull = 1;
  89.     }
  90. }
  91. /*----------------------------------------------------------------------------
  92.  * Interrupt routines
  93.  * -------------------------------------------------------------------------*/
  94. #if defined(TWO_BUTTON_MODE)
  95. #error two button mode is still untested
  96. ISR( PCINT2_vect )
  97. {
  98.     /*
  99.      * Auxiliary button pressed and released
  100.      * Check time between press and release to eliminate bounces
  101.      */
  102.     static uint32_t buttonTime[2];
  103.  
  104.     txMsg_Button.RemoteFlag = 0;
  105.     txMsg_Button.ExtendedFlag = 1;
  106.  
  107.     if( (PIND & (1<<PD1)) == 0){
  108.         /* Button pressed */
  109.         buttonTime[0] = Timebase_CurrentTime();
  110.     }else if( (PIND & (1<<PD1)) == 1){
  111.         if( Timebase_PassedTimeMillis( buttonTime[0] ) >= BOUNCE_TIME ){
  112.             /* No bounce, send message */
  113.             txMsg_Button.Id = BUTTON_ID;
  114.             txMsg_Button.DataLength = 1;
  115.             txMsg_Button.Data.bytes[0] = BUTTON1;
  116.             return;
  117.         }else{
  118.             /* Just bounces, ignore it */
  119.             return;
  120.         }
  121.     }
  122.     if( (PIND & (1<<PD2)) == 0){
  123.         /* Button pressed */
  124.         buttonTime[1] = Timebase_CurrentTime();
  125.     }else if( (PIND & (1<<PD2)) == 1){
  126.         if( Timebase_PassedTimeMillis( buttonTime[1] ) >= BOUNCE_TIME ){
  127.             /* No bounce, send message */
  128.             txMsg_Button.Id = BUTTON_ID;
  129.             txMsg_Button.DataLength = 1;
  130.             txMsg_Button.Data.bytes[0] = BUTTON2;
  131.             return;
  132.         }else{
  133.             /* Just bounces, ignore it */
  134.             return;
  135.         }
  136.     }
  137. }
  138. #endif
  139.  
  140. /*-----------------------------------------------------------------------------
  141.  * Main Program
  142.  *---------------------------------------------------------------------------*/
  143. int main(void) {
  144.     uint32_t act;
  145.     int8_t m;
  146.  
  147.     uint8_t acttype, temp_id;
  148.     uint16_t servoid;
  149.  
  150.     uint8_t //blindsStatus, /* Position (-128 to 127) */
  151.             servoToTurn,
  152.             turnDirection = BLINDS_TURN_STOP; /* Specifies direction to turn or stopped */
  153.     uint32_t boardTemperature = 0;
  154.     uint32_t timeStamp = 0, timeStampTurn = 0, servoFeed_timeStamp = 0;
  155.  
  156.     Can_Message_t txMsg;
  157.  
  158.     // Set up callback for CAN messages
  159.     BIOS_CanCallback = &can_receive;
  160.  
  161.     sei();
  162.  
  163.     Timebase_Init();
  164.     adcTemperatureInit();
  165.     rcServoInit();
  166.  
  167. #if defined(TWO_BUTTON_MODE)
  168.     /*
  169.      * Initialize buttons
  170.      * It is possible to use ie. sensors instead
  171.      * but then change this
  172.      */
  173.     /* Set as input and enable pull-up */
  174.     DDRD &= ~( (1<<DDD1)|(1<<DDD2) );
  175.     PORTD |= (1<<PD1)|(1<<PD2);
  176.  
  177.     /* Enable IO-pin interrupt */
  178.     PCICR |= (1<<PCIE2);
  179.     /* Unmask PD1 and SERVO_FEED_PIN */
  180.     PCMSK2 |= (1<<PCINT16) | (1<<PCINT17);
  181. #endif
  182.     /* Set output and turn off the servo current feed */
  183.     SERVO_FEED_DDR |= (1<<SERVO_FEED_PIN);
  184.     SERVO_FEED_PORT &= ~(1<<SERVO_FEED_PIN);
  185.  
  186.     txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
  187.     txMsg.RemoteFlag = 0;
  188.     txMsg.ExtendedFlag = 1;
  189.     txMsg.DataLength = 4;
  190.     txMsg.Data.words[0] = APP_TYPE;
  191.     txMsg.Data.words[1] = APP_VERSION;
  192.  
  193.     BIOS_CanSend(&txMsg); // Send startup message
  194.  
  195.     txMsg.Id = 0x08000c0b; //(CLASS_SNS << CLASS_MASK_BITS)|(SNS_ACT_STATUS_SERVO << TYPE_MASK_BITS)|(NODE_ID << SID_MASK_BITS);
  196.  
  197.     // Main loop
  198.     while (1) {
  199.         // check if any messages have been received
  200.         if(rxMsgFull){
  201.             if( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_ACT ){
  202.                 // Actuator package
  203.                 acttype = (uint16_t)((rxMsg.Id & CAN_MASK_ACT_TYPE) >> CAN_SHIFT_ACT_TYPE);
  204.                 servoid = (uint8_t)((rxMsg.Id & CAN_MASK_ACT_ID) >> CAN_SHIFT_ACT_ID);
  205.  
  206.         // Check if it is command to control this servo
  207.                 if(acttype == ACT_TYPE_SERVO && (servoid == SERVOID_1 || servoid == SERVOID_2 || servoid == SERVOID_3)){
  208.                     // This node that control a servo is adressed
  209.                     if(servoid == SERVOID_1){
  210.                         temp_id = 1; // First servo
  211.                     }else if(servoid == SERVOID_2){
  212.                         temp_id = 2; // and so on
  213.                     }else if(servoid == SERVOID_3){
  214.                         temp_id = 3;
  215.                     }
  216.  
  217.                     if(rxMsg.DataLength == 1 || (rxMsg.DataLength == 2 && rxMsg.Data.bytes[1] == BLINDS_CMD_ABS)){
  218.                         // Set absolute position to servo
  219.  
  220.                         setPosition( rxMsg.Data.bytes[0], temp_id );
  221.                         servoFeed_timeStamp = Timebase_CurrentTime();
  222.  
  223.                     }else if(rxMsg.DataLength == 2){
  224.                         if(rxMsg.Data.bytes[1] == BLINDS_CMD_REL){
  225.                             // Set relative position to servo
  226.  
  227.                             alterPosition( rxMsg.Data.bytes[0], temp_id );
  228.                             servoFeed_timeStamp = Timebase_CurrentTime();
  229.  
  230.                         }else if(rxMsg.Data.bytes[1] == BLINDS_CMD_START ){
  231.                             // Start turning the servo
  232.  
  233.                             turnDirection = rxMsg.Data.bytes[0]; // FIXME riktning beroende på positivt eller negativt tal?
  234.                             servoToTurn = temp_id;
  235.                             servoFeed_timeStamp = Timebase_CurrentTime();
  236.  
  237.                         }else if(rxMsg.Data.bytes[0] == BLINDS_CMD_STOP ){
  238.                             // Stop turning
  239.  
  240.                             turnDirection = BLINDS_TURN_STOP;
  241.  
  242.                         }/*else if(rxMsg.Data.bytes[0] == BLINDS_CMD_STATUS){
  243.                             // Send blinds status to CAN
  244.                             boardTemperature = getTC1047temperature();
  245.  
  246.                             if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  247.                                 blindsFailsafe();
  248.                             }else{
  249.                             txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  250.                             txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  251.                             txMsg.Data.bytes[2] = 0x00;
  252.                             txMsg.Data.bytes[3] = getPosition(1);
  253.                             txMsg.Data.bytes[4] = getPosition(2);
  254.                             txMsg.Data.bytes[5] = getPosition(3);
  255.                             txMsg.DataLength = 6;
  256.                             BIOS_CanSend(&txMsg);
  257.                         }*/
  258.                     }
  259.                 }
  260.             }
  261.  
  262.             rxMsgFull = 0;
  263.         }
  264.  
  265.         if( (Timebase_CurrentTime() - timeStamp)  >= STATUS_SEND_PERIOD ){
  266.             timeStamp = Timebase_CurrentTime();
  267.             // Send blinds status to CAN periodically
  268.  
  269.             boardTemperature = getTC1047temperature();
  270.  
  271.             if( (int32_t)boardTemperature >= FAILSAFE_TRESHOLD ){
  272.                 blindsFailsafe();
  273.                 }else{
  274.                 txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  275.                 txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  276.                 txMsg.Data.bytes[2] = 0x00;
  277.                 txMsg.Data.bytes[3] = getPosition(1);
  278.                 txMsg.Data.bytes[4] = getPosition(2);
  279.                 txMsg.Data.bytes[5] = getPosition(3);
  280.                 txMsg.DataLength = 6;
  281.  
  282.                 BIOS_CanSend(&txMsg);
  283.             }
  284.         }
  285.         // If start turning servo
  286. /*      if( turnDirection ){
  287.             if( Timebase_CurrentTime() - timeStampTurn >= TURN_PERIOD ){
  288.                 timeStampTurn = Timebase_CurrentTime();
  289.                 // Clockwise or counterclockwise?
  290.                 if( turnDirection == BLINDS_TURN_LEFT ){
  291.                     alterPosition( -STEPS_PER_TURN_PERIOD , servoToTurn);
  292.                 }else if( turnDirection == BLINDS_TURN_RIGHT ){
  293.                     alterPosition( STEPS_PER_TURN_PERIOD , servoToTurn);
  294.                 }
  295.             }
  296.         }
  297.         // Turn off the servo current feed
  298.         if( Timebase_CurrentTime() - servoFeed_timeStamp >= SERVO_FEED_TIME ){
  299.             SERVO_FEED_PORT &= ~(1<<SERVO_FEED_PIN);
  300.             servoDisable();
  301.         }else{
  302.             SERVO_FEED_PORT |= (1<<SERVO_FEED_PIN);
  303.             servoEnable();
  304.         }*/
  305.     }
  306.     return 0;
  307. }
  308.  
  309. void blindsFailsafe()
  310. {
  311. /*  uint32_t boardTemperature = 0, timeStamp = 0;
  312.  
  313.     // Turn of servo current feed
  314.     SERVO_FEED_PORT &= ~(1<<SERVO_FEED_PIN);
  315.  
  316.  
  317.     while(1){
  318.         // check if any messages have been received
  319.         while(rxMsgFull) {
  320.             // This relay is adressed
  321.             if(rxMsg.Data.bytes[0] == BLINDS_CMD_RESET ){
  322.                 // Return from failsafe mode
  323.                 return;
  324.             }
  325.         }
  326.  
  327.         if( Timebase_CurrentTime() - timeStamp >= FAILSAFE_SEND_PERIOD ){
  328.             timeStamp = Timebase_CurrentTime();
  329.             // Send relay status to CAN
  330.             boardTemperature = getTC1047temperature();
  331.  
  332.             txMsg.Data.bytes[0] = boardTemperature & 0x00FF;
  333.             txMsg.Data.bytes[1] = (boardTemperature & 0xFF00)>>8;
  334.             txMsg.Data.bytes[2] = FAILSAFE_MODE;
  335. #if NUMBER_OF_RCS >0
  336.             txMsg.Data.bytes[3] = getPosition(1);
  337. #endif
  338. #if NUMBER_OF_RCS >1
  339.             txMsg.Data.bytes[4] = getPosition(2);
  340. #endif
  341. #if NUMBER_OF_RCS >2
  342.             txMsg.Data.bytes[5] = getPosition(3);
  343. #endif
  344.             txMsg.DataLength = NUMBER_OF_RCS+3;
  345.  
  346.             BIOS_CanSend(&txMsg);
  347.         }
  348.     }*/
  349. }
  350.  
  351.