Você está na página 1de 17

Universidade Federal de Uberlândia

Faculdade de Engenharia Elétrica

Trabalho 2

Controle de Velocidade de uma Máquina CC

Prof. Dr. Ernane Antônio Alves Coelho

Vinı́cius Carvalho Festozo 11811EEL018


Alailton José Alves Júnior 11821EEL020
Eduardo Maciel de Godoy 11821EEL025
Daniel Braga Melo 11911EEL009

Alailton José Alves Júnior

27 de novembro de 2023
Sumário
I Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
I - a) Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

II Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
II - a) IHM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
II - b) Inicialização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
II - c) Loop Principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
II - d) Entrada do Encoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
II - e) Controle da velocidade do motor . . . . . . . . . . . . . . . . . . . . . . . 7

III Simulação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

IV Algoritmo Completo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

Algoritmos
1 Inicialização dos componentes utilizados na planta para IHM . . . . . . . . . . 3
2 Inicialização do microcontrolador ATMega328 . . . . . . . . . . . . . . . . . 4
3 Código do Loop principal do microcontrolador . . . . . . . . . . . . . . . . . 5
4 Configuração das interrupções invocadas pelos pulsos do Encoder . . . . . . . 6
5 Configuração do Timer 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
6 Algoritmo de controle invocado pelo overflow do Timer 1 . . . . . . . . . . . . 8
7 Código do ATmega328P para controle de velocidade de uma máquina CC . . . 10
I Introdução

I Introdução
Neste projeto, foi desenvolvida uma proposta de compensador PI para o fechamento da
malha de velocidade da máquina JGA25-370. O compensador foi inicialmente projetado no
domı́nio contı́nuo e posteriormente discretizado a uma taxa de amostragem de 100Hz, utilizando
o método ”ZOH”(zero-order-hold).
A intuito deste trabalho consiste na reprodução experimental do controle de velocidade em
malha fechada para a mencionada máquina utilizando o controlador ATMega328, conforme
abordado na teoria de Realimentação de Sistemas Dinâmicos. O código projetado para a
implementação prática do controle de velocidade incorporou diversas caracterı́sticas associadas
à planta do sistema, como por exemplo: (i) um Display LCD, (ii) um keypad, (iii) Ponte H para
acionamento, entre outros.

I - a) Objetivos

O objetivo principal do projeto é alcançar um controle eficiente e preciso da velocidade da


máquina JGA25-370 utilizando o controlador ATMega328. Para isto, os seguintes objetivos
especı́ficos foram estabelecidos:

1. Desenvolver um código de controle da velocidade do motor da máquina JGA25-370, levando-


o à velocidade definida pelo usuário e mantendo essa velocidade até a aplicação de um
novo comando.
2. Definir uma faixa de velocidade permitida ao usuário entre -2,0 e 2,0 rotações por segundo
(rps), com uma resolução de uma casa decimal, assegurando precisão e ajustabilidade no
controle de velocidade.
3. Implementar uma interface homem-máquina (IHM) que permita a inserção de valores de
velocidade por meio de um teclado (keypad).
4. Desenvolver um mecanismo de segurança por meio de um ”comando de entrada”após a
digitação do valor desejado, com ação de ignorar entradas fora da faixa permitida. Além
disso, incluir funcionalidades de comando, como um comando de parada geral para inter-
romper a operação do motor e um comando de ativação para retomar a operação.
5. Integrar a exibição da velocidade corrente do eixo externo (caixa de mudança) no display da
interface, possibilitando uma visualização direta e em tempo real do estado operacional do
sistema.

2
II Metodologia

Todos os demais detalhes da implementação e funcionamento do sistema serão apresentados


nas próximas seções.

II Metodologia

II - a) IHM

Com o intuito controlar a velocidade do motor da máquina JGA25-370 conforme o ope-


rador desejar, foi desenvolvido um código de controle que permitisse a inserção de valores
de velocidade por meio de um teclado (keypad). Para isto, foi implementada uma interface
homem-máquina (IHM) que possibilita a inserção de valores de velocidade. Além do key-
pad, foi utilizado um display LCD para exibir a velocidade atual do eixo externo da máquina
JGA25-370.
A configuração destes componentes no microcontrolador é mostrada no Algoritmo 1.

Algoritmo 1: Inicialização dos componentes utilizados na planta para IHM

1 // Keypad Library
2 #include <Keypad_I2C.h>
3 #include <Keypad.h>
4 #include <Wire.h>
5 #define KEYPAD_ADDR 0x20
6
7 // LCD Library
8 #include <LiquidCrystal_I2C.h>
9 #define LCD_col 16
10 #define LCD_lin 4
11 #define LCD_ADDR 0x38
12
13 // ============ Keypad Config ==================================== //
14 const uint8_t ROWS = 4; // number of keypad lines
15 const uint8_t COLS = 4; // number of keypad columns
16 uint8_t keys[ROWS][COLS] = { // key specification
17 {’1’,’2’,’3’,’A’},
18 {’4’,’5’,’6’,’B’},
19 {’7’,’8’,’9’,’C’},
20 {’*’,’0’,’#’,’D’}
21 };

3
II Metodologia

22 //connection to the row pinouts of the keypad


23 uint8_t rowPins[ROWS] = {4, 5, 6, 7};
24 //connection to the column pinouts of the keypad
25 uint8_t colPins[COLS] = {0, 1, 2, 3};
26 TwoWire *jwire = &Wire;
27 Keypad_I2C kpd(makeKeymap(keys), rowPins, colPins, ROWS, COLS,
KEYPAD_ADDR, PCF8574, jwire);
28
29 // ========== LCD Config ======================================= //
30 LiquidCrystal_I2C lcd(LCD_ADDR,LCD_col,LCD_lin);

II - b) Inicialização

Na inicialização do microcontrolador, foi configurado os pinos de saı́da do PWM do Timer 1


e os pinos de entrada INT1 e INT2 para a leitura dos sinais do encoder. Além disso, inicializou-
se a variáveis de controle e os componentes da IHM. O código da inicialização é mostrado no
Algoritmo 2.

Algoritmo 2: Inicialização do microcontrolador ATMega328

1 cli(); // disable global interrupts


2 // ============ ATMega Initiate ====================================
3 init(); // Call ATMega initialization functions
4
5 // Initiate the peripherals
6 jwire->begin(); // Initiate the I2C bus
7 kpd.begin(); // Initiate the keypad
8 lcd.begin(LCD_col,LCD_lin); // Initiate the LCD
9 printHome(); // Print the home screen
10
11 // Configure the ports
12 PORTB = 0x00; // Reset the PORTB pins
13 DDRB = (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB5); // Set PB0, PB1, PB2 and
PB5 as output
14 configInput(); // Initiate the input interrupts
15 configTimer1(1200, 400); // Initiate the timer 1
16
17 // Initiate the variables
18 rpsConversion = 1.0/PulsePerRevolution*100;

4
II Metodologia

19 Serial.println(rpsConversion);
20 timerCounter = inputCounter = 0;
21 velocityRef = velocity = 0;
22 direction = None;
23 char key;
24 uint32_t time = 1;
25 // ================================================
26 sei(); // enable global interrupts

II - c) Loop Principal

No loop principal do microcontrolador, foi implmentado tanto as entradas de velocidade e


os comandos de parada e ativação do motor a partir do Keypad, quanto a atualização da tela do
display LCD. O código do loop principal é mostrado no Algoritmo 3.

Algoritmo 3: Código do Loop principal do microcontrolador

1 while(1){
2 key = kpd.getKey();
3 if (key != NO_KEY){
4 switch (key)
5 {
6 case ’2’:
7 // Turn the motor off
8 lcd.setCursor(16-3,0);
9 lcd.print("OFF");
10 PORTB &= ˜(1<<PB0); // Set PB0 to 0
11 break;
12 case ’1’:
13 // Turn the motor on
14 lcd.setCursor(16-3,0);
15 lcd.print("ON ");
16 PORTB |= (1<<PB0); // Set PB0 to 1
17 break;
18 case ’A’:
19 // Increase the reference velocity
20 velocityRef += SPD_STEP;
21 if (velocityRef > MAX_SPD) velocityRef = MAX_SPD;
22 break;

5
II Metodologia

23 case ’B’:
24 // Decrease the reference velocity
25 velocityRef -= SPD_STEP;
26 if (velocityRef < MIN_SPD) velocityRef = MIN_SPD;
27 break;
28 default:
29 break;
30 }
31 }
32 if(millis() - time > 500){
33 // Print the velocity and the reference velocity
34 PORTB ˆ= (1<<PB5);
35 time = millis();
36 lcd.setCursor(16+4,0);
37 lcd.print(velocity);
38 lcd.setCursor(16+9,0);
39 lcd.print(" | ");
40 lcd.setCursor(16+12,0);
41 lcd.print(velocityRef);
42 }
43 }

II - d) Entrada do Encoder

O algoritmo implementado no ATMega328 utilizou as entradas INT1 e INT2 do microcon-


trolador para a leitura dos sinais do Encoder. A partir destes sinais, foi possı́vel determinar a
velocidade do eixo externo da máquina JGA25-370 com base na quantidade de bordas de subida
e descida lidas pelo ATMega328 em um perı́odo de 0,01s. A configuração dos pinos de entrada
e a interrupção de hardware são mostrados no Algoritmo 4.

Algoritmo 4: Configuração das interrupções invocadas pelos pulsos do Encoder

1 /**
2 * @brief Configure the input INT0 and INT1 interrupts
3 */
4 void configInput(){
5 // Set the interrupt to trigger on the falling edge and rising edge
6 EICRA = (1 << ISC10) | (1 << ISC00);
7 // Enable interrupts for INT0 and INT1

6
II Metodologia

8 EIMSK = (1<<INT0)|(1<<INT1);
9 }
10 // Interrupt Service Routines for INT0
11 ISR(INT0_vect){
12 // Register the motor encoder input on the rising edge and falling
edge at the input INT0
13
14 inputCounter++;
15 // INT0-> PD2 (pin 2 of the Arduino connector)
16 if (PIND & (1<<PD2)){
17 // If the input 2 and 3 are high the motor is moving forward
18 if (PIND & (1<<PD3)) direction = Forward;
19 else direction = Backward;
20 }
21 }
22
23 // Interrupt Service Routines for INT1
24 ISR(INT1_vect){
25 // Register the motor encoder input on the rising edge and falling
edge at the input INT1
26 inputCounter++;
27 }

II - e) Controle da velocidade do motor

A operação que estima o número de bordas registradas pelo encoder e converte para a
velocidade do eixo em RPM, é invocada pela interrupção de hardware do Timer 1, ele foi
configurado de modo que a cada 0,2ms ele interrompe o microcontrolador por causa do overflow
e executa a função ISR(TIMER1 COMPA vect). O código da configuração do Timer 1 é
mostrado no Algoritmo 5.

Algoritmo 5: Configuração do Timer 1

1 /**
2 * @brief Configure the timer 1
3 * @param comp_A Compare value for the output A
4 * @param comp_B Compare value for the output B
5 */
6 void configTimer1(uint16_t comp_A, uint16_t comp_B){

7
II Metodologia

7 /*
8 Config Timer 1
9 - Wave Generation Mode 10 (PWM Phase Correct)
10 - Compare Output Mode 1A (Clear on Compare Match, Set at BOTTOM)
11 - Compare Output Mode 1B (Clear on Compare Match, Set at BOTTOM)
12 - Clock speed 16MHz
13 */
14 TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); // Set the
compare output mode for A and B
15 TCCR1B = (1 << WGM13) | (1 << CS10); // Set the wave generation mode
and the clock speed
16 // Set the compare values for input A and B
17 OCR1A = comp_A; OCR1B = comp_B;
18 TIMSK1=0x01; // enable overflow interrupt
19 ICR1=1600; // 16MHz/1600=10kHz
20 TCNT1=0; // clear the timer counter
21 }

Quando ocorre a interrupção do Timer 1, além do cálculo da velocidade, também é executado


o algoritmo de controle da velocidade do motor. O código da interrupção do Timer 1 é mostrado
no Algoritmo 6.

Algoritmo 6: Algoritmo de controle invocado pelo overflow do Timer 1

1 #define PI_B0 0.4556


2 #define PI_B1 -0.2419
3 const float PulsePerRevolution = 4*11*45;
4 #define MAX_SPD 2.0
5 #define MIN_SPD -2.0
6 #define SPD_STEP 0.2
7
8 // Interrupt Service Routines for Timer 1
9 ISR(TIMER1_OVF_vect){
10 /*
11 This interrupt is called every 0.2ms (5kHz) and when it’s counter
reaches 50,
12 it computes the velocity of the motor and the PI controller output,
updating the
13 compare value for the output A and B
14 */

8
III Simulação

15 timerCounter++;
16 if (timerCounter >= 50){
17 // Compute the velocity and the PI controller output
18 timerCounter = 0;
19 velocity = (float)inputCounter*rpsConversion*direction;
20 inputCounter = 0;
21 voltage_PI = voltage_PI + (PI_B0 * (velocityRef - velocity) + PI_B1
* PI_Error)*6.2831853;
22 if (voltage_PI > 10.8) voltage_PI = 10.8;
23 else if (voltage_PI < -10.8) voltage_PI = -10.8;
24 PI_Error = (velocityRef - velocity);
25
26 comp_A = 800 + (uint16_t)(voltage_PI*66.6666667);
27 OCR1A = comp_A;
28 OCR1B = 1600 - comp_A;
29 }
30 }

III Simulação
A planta do sistema foi simulada no software Proteus, o esquemático utilizado é mostrado
na Figura 1.
LP0
LP1
LP2

LP4
LP5
LP6
LP7

LCD I2C Connection


10

12
13
14
11
1
2
3

4
5
6

7
8
9

U2 LM041L
14 4
Dual Bridge Motor
VSS

VEE

RS

D0
D1
D2
D3
D4
D5
D6
D7
VDD

RW

SCL SCL P0 LP0


SDA 15 SDA P1 5 LP1
P2 6 LP2
13 INT P3 7 U3(VS)-12V
P4 9 LP4
1
2
3
A0
A1
P5
P6
10
11
12
LP5
LP6
ATMega 328 9 4 U3
A2 P7 LP7
PCF8574A ARD1 DB_IN1 5 IN1 VCC VS
LCD1 DB_IN2 7 IN2 OUT1 2 DB_OUT1
10
ON

IN3
Reset BTN

12 IN4 OUT2 3 DB_OUT2


Keypad I2C Connection 6
www.TheEngineeringProjects.com

DB_ENA ENA
11 ENB OUT3 13
AREF
KP4 A 1 2 3 A 13 1 SENSA OUT4 14
PB5/SCK 15
PB4/MISO 12 SENSB GND
RESET 11
U1 ~ PB3/MOSI/OC2A
SCL 14 SCL P0 4 KP0
KP5 B 4 5 6 B ~ PB2/OC1B
~ PB1/OC1A
10
9 DB_IN2
8 L298
SDA 15 SDA P1 5 KP1 8 DB_IN1
6 PB0/ICP1/CLKO
P2 KP2 DB_ENA
ATMEGA328P-PU

13 7
8
1121

INT P3 KP3 KP6 C 7 9 C


ANALOG IN

PD7/AIN1 7
P4 9 KP4 6
1 10 A0 ~ PD7/AIN1
A0 P5 KP5 PC0/ADC0 5
2
3
A1
A2
P6
P7
11
12
KP6
KP7 KP7 D * 0 # D
A1
A2
PC1/ADC1
PC2/ADC2
~ PD5/T1/OC0B
PD4/T0/XCK
~ PD3/INT1/OC2B
4
3 ENCODER B
Motor ENCODER B
ENCODER A
SDA A3 PC3/ADC3 PD2/INT0 2
PCF8574 A4 PC4/ADC4/SDA 1
PD1/TXD
1

A5 PC5/ADC5/SCL 0 ENCODER A
PD0/RXD
SCL DB_OUT1 DB_OUT2

KP0 KP1 KP2 KP3 ARDUINO UNO


+270

Figura 1: Esquemático utilizado no Software Proteus para simulação do circuito

9
IV Algoritmo Completo

IV Algoritmo Completo
O algoritmo completo do código implementado no ATMega328 é mostrado no Algoritmo 7.

Algoritmo 7: Código do ATmega328P para controle de velocidade de uma máquina CC

1 // Keypad Library
2 #include <Keypad_I2C.h>
3 #include <Keypad.h>
4 #include <Wire.h>
5 #define KEYPAD_ADDR 0x20
6
7 // LCD Library
8 #include <LiquidCrystal_I2C.h>
9 #define LCD_col 16
10 #define LCD_lin 4
11 #define LCD_ADDR 0x38
12
13 /*
14 PI Controller
15 - PI_B0: Proportional gain
16 - PI_B1: Derivative gain
17 - PulsePerRevolution: Number of pulses per revolution of the motor
18 - MAXSPD: Maximum velocity of the motor
19 - MINSPD: Minimum velocity of the motor
20 - Equation:
21 - G(z) = (PI_B0 * ( z - PI_B1 ) ) / (z-1)
22 - Voltage = Voltage_dot + PI_B0 * Error + PI_B1 * Error_dot
23 */
24 #define PI_B0 0.4556
25 #define PI_B1 -0.2419
26 const float PulsePerRevolution = 4*11*45; // (4 INTS per encoder pulses)
* (11 Encoder pulses per revolution) * (45 gearbox ratio)
27 #define MAX_SPD 2.0
28 #define MIN_SPD -2.0
29 #define SPD_STEP 0.2
30
31 enum Direction_E{
32 Forward = 1,
33 Backward = -1,

10
IV Algoritmo Completo

34 None = 0
35 };
36
37 void printHome();
38 void configTimer1(uint16_t comp_A, uint16_t comp_B);
39 void configInput();
40
41 // ============ Keypad Config ====================================
42 const uint8_t ROWS = 4; // number of keypad lines
43 const uint8_t COLS = 4; // number of keypad columns
44 uint8_t keys[ROWS][COLS] = { // key specification
45 {’1’,’2’,’3’,’A’},
46 {’4’,’5’,’6’,’B’},
47 {’7’,’8’,’9’,’C’},
48 {’*’,’0’,’#’,’D’}
49 };
50 uint8_t rowPins[ROWS] = {4, 5, 6, 7}; //connection to the row pinouts of
the keypad
51 uint8_t colPins[COLS] = {0, 1, 2, 3}; //connection to the column pinouts
of the keypad
52 TwoWire *jwire = &Wire;
53 Keypad_I2C kpd(makeKeymap(keys), rowPins, colPins, ROWS, COLS,
KEYPAD_ADDR, PCF8574, jwire);
54
55 // ========== LCD Config =======================================
56 LiquidCrystal_I2C lcd(LCD_ADDR,LCD_col,LCD_lin);
57
58 // ========== Global Variables ==================================
59 uint16_t inputCounter, timerCounter, comp_A;
60 float velocity, rpsConversion, PI_Error, voltage_PI, velocityRef;
61 Direction_E direction;
62
63 int main(){
64
65 cli(); // disable global interrupts
66 // ============ ATMega Initiate ====================================
67 init(); // Call ATMega initialization functions
68
69 // Initiate the peripherals

11
IV Algoritmo Completo

70 jwire->begin(); // Initiate the I2C bus


71 kpd.begin(); // Initiate the keypad
72 lcd.begin(LCD_col,LCD_lin); // Initiate the LCD
73 printHome(); // Print the home screen
74
75 // Configure the ports
76 PORTB = 0x00; // Reset the PORTB pins
77 DDRB = (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB5); // Set PB0, PB1, PB2 and
PB5 as output
78 configInput(); // Initiate the input interrupts
79 configTimer1(1200, 400); // Initiate the timer 1
80
81 // Initiate the variables
82 rpsConversion = 1.0/PulsePerRevolution*100;
83 timerCounter = inputCounter = 0;
84 velocityRef = velocity = 0;
85 direction = None;
86 char key;
87 uint32_t time = 1;
88 // ================================================
89 sei(); // enable global interrupts
90
91 while(1){
92 key = kpd.getKey();
93 if (key != NO_KEY){
94 switch (key)
95 {
96 case ’2’:
97 // Turn the motor off
98 lcd.setCursor(16-3,0);
99 lcd.print("OFF");
100 PORTB &= ˜(1<<PB0); // Set PB0 to 0
101 break;
102 case ’1’:
103 // Turn the motor on
104 lcd.setCursor(16-3,0);
105 lcd.print("ON ");
106 PORTB |= (1<<PB0); // Set PB0 to 1
107 break;

12
IV Algoritmo Completo

108 case ’A’:


109 // Increase the reference velocity
110 velocityRef += SPD_STEP;
111 if (velocityRef > MAX_SPD) velocityRef = MAX_SPD;
112 break;
113 case ’B’:
114 // Decrease the reference velocity
115 velocityRef -= SPD_STEP;
116 if (velocityRef < MIN_SPD) velocityRef = MIN_SPD;
117 break;
118 default:
119 break;
120 }
121 }
122 if(millis() - time > 500){
123 // Print the velocity and the reference velocity
124 PORTB ˆ= (1<<PB5);
125 time = millis();
126 lcd.setCursor(16+4,0);
127 lcd.print(velocity);
128 lcd.setCursor(16+9,0);
129 lcd.print(" | ");
130 lcd.setCursor(16+12,0);
131 lcd.print(velocityRef);
132 }
133 }
134 return 0;
135 }
136
137 /**
138 * @brief Initiliaze the LCD
139 */
140 void printHome(){
141
142 lcd.backlight(); // turn on the LCD backlight
143 lcd.clear(); // clears the LCD screen and positions
the cursor in the upper-left corner
144 lcd.setCursor(0,0); // moves the cursor at the beginning of
the first line

13
IV Algoritmo Completo

145 // lcd.print("Control Motor ");


146 lcd.print("Motor: Power ON ");
147 lcd.setCursor(0,1); // moves the cursor at the beginning of
the second line
148 lcd.print("0: ON 1: OFF");
149 lcd.setCursor(16,0); // moves the cursor at the beginning
of the third line
150 lcd.print("RPS: ");
151 lcd.setCursor(16,1); // moves the cursor at the beginning
of the fourth line
152 lcd.print("Left: A Right: B");
153 }
154
155 /**
156 * @brief Configure the timer 1
157 * @param comp_A Compare value for the output A
158 * @param comp_B Compare value for the output B
159 */
160 void configTimer1(uint16_t comp_A, uint16_t comp_B){
161 /*
162 Config Timer 1
163 - Wave Generation Mode 10 (PWM Phase Correct)
164 - Compare Output Mode 1A (Clear on Compare Match, Set at BOTTOM)
165 - Compare Output Mode 1B (Clear on Compare Match, Set at BOTTOM)
166 - Clock speed 16MHz
167 */
168 TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); // Set the
compare output mode for A and B
169 TCCR1B = (1 << WGM13) | (1 << CS10); // Set the wave generation mode
and the clock speed
170 // Set the compare values for input A and B
171 OCR1A = comp_A; OCR1B = comp_B;
172 TIMSK1=0x01; // enable overflow interrupt
173 ICR1=1600; // 16MHz/1600=10kHz
174 TCNT1=0; // clear the timer counter
175 }
176
177 /**
178 * @brief Configure the input INT0 and INT1 interrupts

14
IV Algoritmo Completo

179 */
180 void configInput(){
181 // Set the interrupt to trigger on the falling edge and rising edge
182 EICRA = (1 << ISC10) | (1 << ISC00);
183
184 // Enable interrupts for INT0 and INT1
185 EIMSK = (1<<INT0)|(1<<INT1);
186 }
187
188 // Interrupt Service Routines for INT0
189 ISR(INT0_vect){
190 // Register the motor encoder input on the rising edge and falling
edge at the input INT0
191
192 inputCounter++;
193
194 // INT0-> PD2 (pin 2 of the Arduino connector)
195 if (PIND & (1<<PD2)){
196 // If the input 2 and 3 are high the motor is moving forward
197 if (PIND & (1<<PD3)) direction = Forward;
198 else direction = Backward;
199 }
200 }
201
202 // Interrupt Service Routines for INT1
203 ISR(INT1_vect){
204 // Register the motor encoder input on the rising edge and falling
edge at the input INT1
205 inputCounter++;
206 }
207
208 // Interrupt Service Routines for Timer 1
209 ISR(TIMER1_OVF_vect){
210 /*
211 This interrupt is called every 0.2ms (5kHz) and when it’s counter
reaches 50,
212 it computes the velocity of the motor and the PI controller output,
updating the
213 compare value for the output A and B

15
IV Algoritmo Completo

214 */
215 timerCounter++;
216 if (timerCounter >= 50){
217 // Compute the velocity and the PI controller output
218 timerCounter = 0;
219 velocity = (float)inputCounter*rpsConversion*direction;
220 inputCounter = 0;
221 voltage_PI = voltage_PI + (PI_B0 * (velocityRef - velocity) + PI_B1
* PI_Error)*6.2831853;
222 if (voltage_PI > 10.8) voltage_PI = 10.8;
223 else if (voltage_PI < -10.8) voltage_PI = -10.8;
224 PI_Error = (velocityRef - velocity);
225
226 comp_A = 800 + (uint16_t)(voltage_PI*66.6666667);
227 OCR1A = comp_A;
228 OCR1B = 1600 - comp_A;
229 }
230 }

16

Você também pode gostar