Advertisement
Guest User

Untitled

a guest
Mar 29th, 2017
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.15 KB | None | 0 0
  1. /**
  2.  * AVR program for control of the DC-servo process.
  3.  *  
  4.  * User communication via the serial line. Commands:
  5.  *   s: start controller
  6.  *   t: stop controller
  7.  *   r: change sign of reference (+/- 5.0 volt)
  8.  *
  9.  * To compile for the ATmega8 AVR:
  10.  *   avr-gcc -mmcu=atmega8 -O -g -Wall -o DCservo.elf DCservo.c  
  11.  *
  12.  * To upload to the ATmega8 AVR:
  13.  *   avr-objcopy -Osrec DCservo.elf DCservo.sr
  14.  *   avrdude -e -p atmega8 -P usb -c avrisp2 -U flash:w:DCservo.sr:a
  15.  *
  16.  * To compile for the ATmega16 AVR:
  17.  *   avr-gcc -mmcu=atmega16 -O -g -Wall -o DCservo.elf DCservo.c  
  18.  *
  19.  * To upload to the ATmega16 AVR:
  20.  *   avr-objcopy -Osrec DCservo.elf DCservo.sr
  21.  *   avrdude -e -p atmega16 -P usb -c avrisp2 -U flash:w:DCservo.sr:a
  22.  *
  23.  * To view the assembler code:
  24.  *   avr-objdump -S DCservo.elf
  25.  *
  26.  * To open a serial terminal on the PC:
  27.  *   simcom -38400 /dev/ttyS0
  28.  */
  29.  
  30. #include <avr/io.h>
  31. #include <avr/interrupt.h>
  32.  
  33. #define K 2.6133
  34. #define Ti 0.4523
  35. #define KBeta 1.3067
  36. #define KhTi 0.2889
  37.  
  38. /* Controller parameters and variables (add your own code here) */
  39.  
  40. int8_t on = 0;                     /* 0=off, 1=on */
  41. int16_t r = 255;                   /* Reference, corresponds to +5.0 V */
  42.  
  43.  
  44.  
  45. /**
  46.  * Write a character on the serial connection
  47.  */
  48. static inline void put_char(char ch){
  49.   while ((UCSRA & 0x20) == 0) {};
  50.   UDR = ch;
  51. }
  52.  
  53. /**
  54.  * Write 10-bit output using the PWM generator
  55.  */
  56. static inline void writeOutput(int16_t val) {
  57.   val += 512;
  58.   OCR1AH = (uint8_t) (val>>8);
  59.   OCR1AL = (uint8_t) val;
  60. }
  61.  
  62. /**
  63.  * Read 10-bit input using the AD converter
  64.  * chan = 0 or 1
  65.  * return [-512..511]
  66.  */
  67. static inline int16_t readInput(char chan) {
  68.   uint8_t low, high;
  69.   ADMUX = 0xc0 + chan;             /* Specify channel (0 or 1) */
  70.   ADCSRA |= 0x40;                  /* Start the conversion */
  71.   while (ADCSRA & 0x40);           /* Wait for conversion to finish */
  72.   low = ADCL;                      /* Read input, low byte first! */
  73.   high = ADCH;                     /* Read input, high byte */
  74.   return ((high<<8) | low) - 512;  /* 10 bit ADC value [-512..511] */
  75. }  
  76.  
  77. /**
  78.  * Interrupt handler for receiving characters over serial connection
  79.  * s = start controller
  80.  * t = stop controller
  81.  * r = change sign of ref
  82.  */
  83. ISR(USART_RXC_vect){
  84.   switch (UDR) {
  85.   case 's':                        /* Start the controller */
  86.     put_char('s');
  87.     on = 1;
  88.     break;
  89.   case 't':                        /* Stop the controller */
  90.     put_char('t');
  91.     on = 0;
  92.     break;
  93.   case 'r':                        /* Change sign of reference */
  94.     put_char('r');
  95.     r = -r;
  96.     break;
  97.   }
  98. }
  99.  
  100. /**
  101.  * Interrupt handler for the periodic timer. Interrupts are generated
  102.  * every 10 ms. The control algorithm is executed every 50 ms.
  103.  */
  104. ISR(TIMER2_COMP_vect){
  105.   static int8_t ctr = 0;
  106.   static float I = 0;
  107.  
  108.   if (++ctr < 5) return;
  109.   ctr = 0;
  110.   if (on) {
  111.     /* Insert your controller code here */
  112.     int16_t y = readInput(0);
  113.     float u = KBeta*r - K*y + I;
  114.     if (u > 511)
  115.       u = 511
  116.     else if (u < -512)
  117.       u = -512
  118.    
  119.     writeOutput(u);
  120.     I = I + KhTi*(r-y);
  121.   } else {                    
  122.     writeOutput(0);     /* Off */
  123.   }
  124. }
  125.  
  126. /**
  127.  * Main program
  128.  */
  129. int main(){
  130.  
  131.   DDRB = 0x02;    /* Enable PWM output for ATmega8 */
  132.   DDRD = 0x20;    /* Enable PWM output for ATmega16 */
  133.   DDRC = 0x30;    /* Enable time measurement pins */
  134.   ADCSRA = 0xc7;  /* ADC enable */
  135.  
  136.   TCCR1A = 0xf3;  /* Timer 1: OC1A & OC1B 10 bit fast PWM */
  137.   TCCR1B = 0x09;  /* Clock / 1 */
  138.  
  139.   TCNT2 = 0x00;   /* Timer 2: Reset counter (periodic timer) */
  140.   TCCR2 = 0x0f;   /* Clock / 1024, clear after compare match (CTC) */
  141.   OCR2 = 144;     /* Set the compare value, corresponds to ~100 Hz */
  142.  
  143.   /* Configure serial communication */
  144.   UCSRA = 0x00;   /* USART: */
  145.   UCSRB = 0x98;   /* USART: RXC enable, Receiver enable, Transmitter enable */
  146.   UCSRC = 0x86;   /* USART: 8bit, no parity */
  147.   UBRRH = 0x00;   /* USART: 38400 @ 14.7456MHz */
  148.   UBRRL = 23;     /* USART: 38400 @ 14.7456MHz */
  149.  
  150.   TIMSK = 1<<OCIE2; /* Start periodic timer */
  151.  
  152.   sei();          /* Enable interrupts */
  153.  
  154.   while (1);
  155. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement