Fig. 3.
8: Pulse diagram of 4x encoding
From the above pulses, we can draw out a table that describes the transition states
of the two channels A and B:
Table 3.3: The transition states of channel A and B
State Clockwise-Transition Counter-Clockwise
(CW) Transition (CCW)
0, 0 (0, 1) to (0, 0) (1, 0) to (0, 0)
1, 0 (0, 0) to (1, 0) (1, 1) to (1, 0)
1, 1 (1, 0) to (1, 1) (0, 1) to (1, 1)
0, 1 (1, 1) to (0, 1) (0, 0) to (0, 1)
The state transition diagram:
Fig. 3.9: The state transition diagram
The figure below (Fig. 3.10) is the code example of 4x encoder reading for channel
A. To complete reading encoder in 4x mode, we have to add another external interrupt
for channel B, the code for channel B is almost similar.
Note that: - Channel A is connected to GPIOB, PIN 4
- Channel B is connected to GPIOB, PIN 6
3.3.2 Calculating velocity/position
92
For simplicity, we use the following equation for estimating velocity of the motor:
60 CountValue
= (RPM) (3.8)
T MaxCnt
where, CountValue is the number of pulses counted in T (s). T is also timer interrupt for
reading encoder, and in this experiment, T is configured as 0.005 (s). MaxCnt equals to
encoder resolution multiplied by its mode (x1, x2 or x4).
Fig. 3.10: Code example of channel A encoding in 4x mode
3.4. PID controller
3.4.1 PID calculation
The mathematic equation of the PID controller:
t
de(t)
u(t) = K Pe ( t ) + K I e(t)d(t) + K D (3.9)
0
dt
When implementing the PID controller in practice, the input variable (error) is obtained
93
by sampling the plant’s output at the sample rate. Then, the PID algorithm is also
calculated at the same rate. At the step kth, we have:
u k = u Pk + u Dk + u Ik (3.10)
KP
e(t ) t u (t ) uˆ(t )
K I e( )d
0
de(t )
KD
dt
Fig 3.11: Block diagram of a PID controller
➢ P Calculation
u P k = K Pek (3.11)
➢ D calculation
ek − e k −1
u Dk = K D (3.12)
T
➢ I calculation
e(t) e(t) e(t)
ek ek ek
ek-1 ek-1 ek-1
t t t
(k-1)T kT (k-1)T kT (k-1)T kT
a) b) c)
Fig 3.12: Integral approximation methods
a) Backward rectangular approximation (backward Euler):
k
u Ik = K I Tei = u kI −1 + K I Tek (3.13)
i =1
b) Forward rectangular approximation (forward Euler):
k
u Ik = K I Tei−1 = u Ik−1 + K ITek −1 (3.14)
i =1
c) Trapezoidal approximation:
94
k
ei−1 + ei e +e
u Ik = K I T 2
= u Ik −1 + K IT k −1 k
2
(3.15)
i =1
Code example:
Fig 3.13: Code example of a simple PID algorithm
3.4.2 Low pass filter for D term:
D
E ( s) U D ( s) U (s )
1 f
KDs
Ns + 1
Fig 3.14: Low pass filter for D term
N T
u Df (k) = u D f (k − 1) + u D (k) (3.16)
N+T N+T
T
where, = (0 1) : coefficient of low pass filter
N +T
From (4.27), we derive the equation of low-pass filter calculation:
u D f (k) = (1 − )u D f (k − 1) + u D (k) (3.17)
3.4.3 Anti-windup
95
PID
e u û
e
Ki
edt
ereset
Kb
Fig 3.15: Block diagram of an anti-windup structure
From the block, we draw out the equation to calculate the anti-windup for I term
t
u (t) = K Ie( ) + K be reset () d
I
u I k = u I k −1 + K I Te k + K bTe reset k (3.18)
3.5. Experiments
3.5.1 Programming using STM32F103
Board STM32F103RX
96
Fig 3.17: Schematic of all I/O pinouts
Programmer/Debugger
Fig 3.18: Schematic and pinouts of SWD
H-Bridge
97
Fig 3.19: H-bridge pinouts
Specifications:
✓ Input voltage: 8V-32V; Continuous current: 16A
✓ Input level: 3.3-5V
✓ The PWM frequency max: 20 KHz
✓ Duty cycle: 0-100%
Hardware layout and wiring diagram
Investigating the components and hardware connection of the system, each group
has to draw its schematic and include it in the report.
3.5.2 Microcontroller programming
Using STM32CUBEMX to create a project
Step 1: Create a project using STM32F103RCT
98
Step 2: Clock configuration. Note that it is only an example, students can set up clocks
with other parameters but in that case, from now on, all calculations related to clocks
have to be modified.
99
Step 3: SWD configuration for programming
Step 4: Hardware declaration
We use two external interrupts to read encoder signals (Ch. A, Ch. B). In this
example, PB4 and PB6 will be connected and configured as the below figure.
Enable external interrupt to read encoder
100
PWM settings: A PWM channel is used for the H-bridge. In this case, TIM3_CH2
(PC7) is configured as the following figures:
The PWM frequency is calculated:
Timer_clock (APB1)
Timer_tick = (3.19)
Prescaller + 1
Timer_tick
f PWM = (3.20)
Counter Period + 1
Example: Timer_clock (APB1) = 24 Mhz (Clock configuration)
Prescaller = 11; Counter Period =100
24 106
Timer_tick = = 2 106 (Hz)
11 + 1
2 106
f PWM = 19.8 (KHz)
100 + 1
TIM3_CH2 is configured as follows:
101
USART settings: Using UART to communicate with computer
102
Timer Interrupt: Timer 4 is adopted to configure a cyclic interrupt 5 (ms). Using
Eq. 3.17 to calculate the setting parameters as follow
Enable TIM4 interrupt
103
Step 4: Code generation
3.5.3 Velocity control
Students have to modify the given code including:
✓ 2 external interrupts for encoder reading (x4 mode): EXTI4_IRQHandler,
EXTI9_5_IRQHandler. Using sample code in Fig. 3.10
✓ Velocity estimation in TIM4_IRQHandler using Eq. (3.8)
104
✓ HAL_UART_RxCpltCallback: based on the sample code to communicate with
Visual C# interface (appendix)
✓ Open the Visual studio program, choose parameters for RS232 connection. Note
that the BaudRate has to be compatible with the one already configured in
USART1.
✓ Identify the transfer function of the H-bridge and the motor by applying the
pwm signal 100% and plotting the velocity response. From the response,
calculating the parameters of the transfer function including gain (K) and time
constant ( )
✓ Write a PI algorithm with anti-windup based on the sample code in Fig. 3.13.
However, students must improve the algorithm by adding an anti-windup for I-
term (Eq. 3.18)
3.6. Report
Student have to show all their results including the hardware (schematic),
obtained transfer function, calculations for PI parameters, the code and the
controlled velocity responses.
105
APPENDIX
USART1 COMUNICATION
int16_t DesiredSpeed;
char Rx_indx, Rx_Buffer[20],Rx_data[2];
float DesiredPos;
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t*)&ch,1,100);
return ch;
}
// Ham ngat Uart
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
uint8_t i;
if(huart->Instance == USART1) { //uart1
if(Rx_indx==0) {for (i=0;i<20;i++) Rx_Buffer[i] = 0;}
switch(Rx_data[0]) {
/* dung dong co */
case 'e':
run =false;
break;
/* dong co chay */
case 'r':
run = true;
break;
case 'b':
106
// reset();
break;
case 's':
DesiredPos = atoi(Rx_Buffer);
memset(Rx_Buffer, 0, sizeof(Rx_Buffer));
Rx_indx = 0;
break;
case 'v':
DesiredSpeed = atoi(Rx_Buffer);
memset(Rx_Buffer, 0, sizeof(Rx_Buffer));
Rx_indx = 0;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '-':
Rx_Buffer[Rx_indx++] |= Rx_data[0];
break;
default:
break;
}
HAL_UART_Receive_IT(&huart1,(uint8_t*)Rx_data,1);
}
}
107