Subversion Repositories HomeAutomation

Rev

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

  1. /*
  2.  * AntennaControl
  3.  *
  4.  * Build for use at ETA, http://www.eta.chalmers.se/, controlling their 2 meter quad antenna.
  5.  *
  6.  * @date 2007-09-22
  7.  * @author Erik Larsson
  8.  *
  9.  */
  10.  
  11. #include <inttypes.h>
  12. #include <avr/interrupt.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <avr/eeprom.h>
  16. #include <config.h> // All configuration parameters
  17. #include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
  18. //#include <drivers/uart/serial.h>
  19. #include <drivers/timer/timer.h>
  20.  
  21. #define APP_TYPE    0xf0a0
  22. #define APP_VERSION 0x0001
  23.  
  24. #define AZIMUTH 0
  25. #define ELEVATION 1
  26.  
  27. #define ROTATE_STOP 0
  28. #define ROTATE_PLUS 1
  29. #define ROTATE_MINUS 2
  30.  
  31. #define SET 0
  32. #define GET 1
  33. #define CALIBRATE_ELEVATION 0
  34. #define CALIBRATE_AZIMUTH 2
  35.  
  36. // Make sure this is a power of 2
  37. #define AVERAGE_SIZE 16
  38. #define AVERAGE_SIZE_SHIFT 4
  39.  
  40. // Essential pins
  41. // 0: PD2 azimuth plus
  42. // 1: PD1 azimuth minus
  43. // 2: PD0 elevation plus
  44. // 3: PD4 elevation minus
  45. // 8: PC4 ADC4 azimuth feedback
  46. // 9: PC5 ADC5 elevation feedback
  47.  
  48.  
  49.  
  50. // A simple message "queue", with space for one message only.
  51. // These are declared volatile to tell the compiler not to optimize away accesses.
  52. volatile Can_Message_t rxMsg; // Message storage
  53. volatile uint8_t rxMsgFull;   // Synchronization flag
  54.  
  55. //uint16_t actualElevationValue;
  56. //uint16_t desiredElevationValue;
  57. //uint16_t actualAzimuthValue;
  58. //uint16_t desiredAzimuthValue;
  59.  
  60. uint16_t azimuthReadout[ AVERAGE_SIZE ];
  61. uint16_t elevationReadout[ AVERAGE_SIZE ];
  62.  
  63. // CAN message reception callback.
  64. // This function runs with interrupts disabled, keep it as short as possible.
  65. void can_receive( Can_Message_t *msg ) {
  66.     if (!rxMsgFull) {
  67.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  68.         rxMsgFull = 1;
  69.     }
  70. }
  71.  
  72. // Calibration function
  73. // axis: Elevation / Azimuth
  74. // mode: set / get
  75. // value:
  76. int16_t calibration( uint8_t axis, uint8_t mode, uint16_t value );
  77.  
  78. // Turn rotors
  79. // axis: Elevation / Azimuth
  80. // position: 0-1024
  81. uint8_t turn( uint8_t axis, uint16_t position );
  82.  
  83. // Get position
  84. // axis: Elevation / Azimuth
  85. // Gets the average value for compensation of distorsions
  86. uint16_t getPosition( uint8_t axis );
  87.  
  88. // Read position
  89. // axis: Elevation / Azimuth
  90. // uses two adc
  91. uint16_t readPosition(uint8_t axis);
  92.  
  93. void changeFeedbackAxis( uint8_t axis );
  94.  
  95. // Initiate ADC
  96. void initAdcFeedback( void );
  97.  
  98. // Store result from ADC
  99. void readAdcFeedback( void );
  100.  
  101. // Control rotation relays
  102. // axis: Elevation / Azimuth
  103. void controlRelay( uint8_t axis, uint8_t direction );
  104.  
  105. // Timer callback function used for some timer tests
  106. void timer_callback( uint8_t timer ) {
  107.     Can_Message_t msg;
  108.    
  109.     msg.ExtendedFlag = 1;
  110.     msg.Id = (CAN_TST << CAN_SHIFT_CLASS) | NODE_ID;
  111.     msg.RemoteFlag = 0;
  112.     msg.DataLength = 1;
  113.     msg.Data.bytes[0] = timer;
  114.    
  115.     BIOS_CanSend(&msg);
  116. }
  117.  
  118.  
  119. ISR( ADC_vect ) // ADC Conversion Complete
  120. {
  121.    
  122. }
  123.  
  124. int main( void )
  125. {
  126.     // Enable interrupts as early as possible
  127.     sei();
  128.    
  129.     Timer_Init();
  130. //  Serial_Init();
  131.    
  132. //  unsigned long time;
  133.    
  134.     Can_Message_t txMsg;
  135.     txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
  136.     txMsg.DataLength = 4;
  137.     txMsg.RemoteFlag = 0;
  138.     txMsg.ExtendedFlag = 1;
  139.     txMsg.Data.words[0] = APP_TYPE;
  140.     txMsg.Data.words[1] = APP_VERSION;
  141.    
  142.     // Set up callback for CAN reception, this is optional if only sending is required.
  143.     BIOS_CanCallback = &can_receive;
  144.     // Send CAN_NMT_APP_START
  145.     BIOS_CanSend(&txMsg);
  146.    
  147.     printf("AVR Test Application\n");
  148.    
  149.     txMsg.Id = (CAN_TST << CAN_SHIFT_CLASS) | NODE_ID;
  150. //  txMsg.Data.dwords[0] = 0x01020304;
  151. //  txMsg.DataLength = 8;
  152.  
  153.     // Set up three timers (assume at least three has been defined)
  154.     // The timeout is specified in ticks, which is equal to ms if
  155.     // the tick frequency is set to 1000.
  156.     Timer_SetTimeout(0, 10, TimerTypeFreeRunning, 0);
  157. //  Timer_SetTimeout(1, 10768, TimerTypeOneShot, &timer_callback);
  158. //  Timer_SetTimeout(2, 3141, TimerTypeFreeRunning, &timer_callback);
  159.    
  160.     while (1) {
  161.         if (Timer_Expired(0)) {
  162. //          ad-omvandla
  163.         }
  164.        
  165.         if (rxMsgFull) {
  166. //          // Print the received message
  167. //          printf("RX: ID=%08lx, DLC=%u, EXT=%u, RTR=%u, data={ ",
  168. //                  rxMsg.Id,
  169. //                  (uint16_t)rxMsg.DataLength,
  170. //                  (uint16_t)rxMsg.ExtendedFlag,
  171. //                  (uint16_t)rxMsg.RemoteFlag);
  172. //          for (uint8_t i=0; i<rxMsg.DataLength; i++) {
  173. //              printf("%02x ", rxMsg.Data.bytes[i]);
  174. //          }
  175. //          printf("}\n");
  176.            
  177.            
  178.             rxMsgFull = 0; //  
  179.         }
  180.     }
  181.    
  182.     return 0;
  183. }
  184.  
  185.  
  186. int16_t calibration( uint8_t axis, uint8_t mode, uint16_t value )
  187. {
  188.     // set / get calibration value
  189.     if( SET == mode ){
  190.         if( ELEVATION == axis ){
  191.             eeprom_write_word( CALIBRATE_ELEVATION, value );
  192.         }else if( AZIMUTH == axis ){
  193.             eeprom_write_word( CALIBRATE_AZIMUTH, value );
  194.         }  
  195.     }else if( GET == mode ){
  196.         if( ELEVATION == axis ){
  197.             return eeprom_read_word( CALIBRATE_ELEVATION );
  198.         }else if( AZIMUTH == axis ){
  199.             return eeprom_read_word( CALIBRATE_AZIMUTH );
  200.         }      
  201.     }
  202.     return 0;
  203. }
  204.  
  205. uint8_t turn( uint8_t axis, uint16_t position )
  206. {
  207.     // start relay
  208.     // read feedback
  209.     // callibrate measurement
  210.    
  211.     while(0){
  212.        
  213.     }
  214.     return 0;
  215. }
  216.  
  217. uint16_t getPosition( uint8_t axis )
  218. {
  219. /*  uint16_t position = 0;
  220.    
  221.     // Get average value of position
  222.     for( uint8_t i ; i < 4 ; i++ ){
  223.         position += readPosition( axis );
  224.     }
  225.    
  226.     position = (position >> 2);
  227.    
  228.     return position;
  229. */
  230.     return 0;
  231. }
  232.  
  233. uint16_t readPosition( uint8_t axis )
  234. {
  235.     uint16_t averageValue = 0;
  236.     uint16_t *measuredAxis;
  237.    
  238.     if( ELEVATION == axis ){
  239.         // Calculate elevation value
  240.         measuredAxis = elevationReadout;
  241.     }else if( AZIMUTH == axis ){
  242.         // Calculate aximuth value
  243.         measuredAxis = azimuthReadout;
  244.     }else{
  245.         return 0;
  246.     }
  247.  
  248.     for(uint8_t i = 0 ; i<AVERAGE_SIZE ; i++ ){
  249.         // Summarize
  250.         averageValue += measuredAxis[i];
  251.     }
  252.    
  253.     averageValue = averageValue >> AVERAGE_SIZE_SHIFT;
  254.        
  255.        
  256.        
  257.     return averageValue;
  258. }
  259.  
  260.  
  261. void changeFeedbackAxis( uint8_t axis )
  262. {
  263.     if( AZIMUTH == axis ){
  264.         // Enable ADC4
  265.         ADMUX |= ( 1 << MUX2 );
  266.         ADMUX &= ~(( 1 << MUX0 )|( 1 << MUX1 )|( 1 << MUX3 ));
  267.     }else if( ELEVATION == axis ){
  268.         // Enable ADC5
  269.         ADMUX |= ( 1 << MUX0 )|( 1 << MUX2 );
  270.         ADMUX &= ~(( 1 << MUX1 )|( 1 << MUX3 ));
  271.     }  
  272. }
  273.  
  274. void initAdcFeedback( void )
  275. {
  276.     // ADC4: Azimuth feedback
  277.     // ADC5: Elevation feedback
  278.    
  279.     // Enable ADC4
  280.     ADMUX |= ( 1 << MUX2 );
  281.     ADMUX &= ~(( 1 << MUX0 )|( 1 << MUX1 )|( 1 << MUX3 ));
  282.  
  283.     // Prescaler /128
  284.     ADCSRA |= ( 1 << ADPS2)|( 1 << ADPS1)|( 1 << ADPS0);
  285.    
  286.     // Enable AVcc as Voltage Reference
  287.     ADMUX |= ( 1 << REFS0 );
  288.     ADMUX &= ~( 1 << REFS1 );
  289.    
  290.     // Right adjust the result
  291.     ADMUX &= ~( 1 << ADLAR );
  292.    
  293.     // Auto Trigger
  294. //  ADCSRA |= ( 1 << ADATE );
  295.    
  296.     // Disable digital input
  297.     DIDR0 |= ( 1 << ADC5D )|( 1 << ADC4D );
  298.    
  299.     // Wake uo ADC and enable it
  300.     PRR &= ~( 1 << PRADC );
  301.     ADCSRA |= ( 1 << ADEN );
  302. }
  303.  
  304. void controlRelay( uint8_t axis, uint8_t direction )
  305. {
  306.     if( AZIMUTH == axis ){
  307.        
  308.         if( ROTATE_PLUS == direction ){
  309.             PORTD &= ~(1 << PD2);
  310.             PORTD |= (1 << PD1);
  311.         }else if ( ROTATE_MINUS == direction ){
  312.             PORTD &= ~(1 << PD1);
  313.             PORTD |= (1 << PD2);
  314.         }else{
  315.             // stop azimuth rotor
  316.             PORTD |= (1 << PD1);
  317.             PORTD |= (1 << PD2);
  318.         }
  319.        
  320.     }else if( ELEVATION == axis ){
  321.        
  322.         if( ROTATE_PLUS == direction ){
  323.             PORTD &= ~(1 << PD0);
  324.             PORTD |= (1 << PD4);
  325.         }else if ( ROTATE_MINUS == direction ){
  326.             PORTD &= ~(1 << PD4);
  327.             PORTD |= (1 << PD0);
  328.         }else{
  329.             // stop elevation rotor
  330.             PORTD |= (1 << PD0);
  331.             PORTD |= (1 << PD4);
  332.         }
  333.        
  334.     }else{
  335.         // stop all rotors
  336.         PORTD |= (1 << PD0);
  337.         PORTD |= (1 << PD1);
  338.         PORTD |= (1 << PD2);
  339.         PORTD |= (1 << PD4);
  340.     }
  341.    
  342. }
  343.  
  344. void readAdcFeedback( void )
  345. {
  346.     static uint8_t azimuthArrayPosition = 0;
  347.     static uint8_t elevationArrayPosition = 0;
  348.     static uint8_t lastAxis = AZIMUTH;
  349.    
  350.     while( ADCSRA & (1 << ADSC) ); // Wait for conversion to be done
  351.        
  352.     // Get measurement
  353.     if( AZIMUTH == lastAxis ){
  354.         azimuthReadout[ azimuthArrayPosition ] = ADCW;
  355.         azimuthArrayPosition++;
  356.         if( AVERAGE_SIZE <= azimuthArrayPosition ){
  357.             azimuthArrayPosition = 0;
  358.         }
  359.        
  360.         lastAxis = ELEVATION;
  361.        
  362.     }else if( ELEVATION == lastAxis ){
  363.         elevationReadout[ elevationArrayPosition ] = ADCW;
  364.         elevationArrayPosition++;
  365.         if( AVERAGE_SIZE <= elevationArrayPosition ){
  366.             elevationArrayPosition = 0;
  367.         }
  368.        
  369.         lastAxis = AZIMUTH;
  370.     }
  371.    
  372.     // Next time read other axis
  373.     changeFeedbackAxis( lastAxis );
  374.    
  375.     // Start next measurement
  376.     ADCSRA |= (1 << ADSC);
  377. }
  378.