Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
09-TDI
PROJETO E DESENVOLVIMENTO DE UM
CONTROLADOR DE MOTORES "BRUSHLESS" (BLDC)
PARA APLICAO EM VOLANTES DE INRCIA
INPE
So Jos dos Campos
2014
PUBLICADO POR:
Instituto Nacional de Pesquisas Espaciais - INPE
Gabinete do Diretor (GB)
Servio de Informao e Documentao (SID)
Caixa Postal 515 - CEP 12.245-970
So Jos dos Campos - SP - Brasil
Tel.:(012) 3208-6923/6921
Fax: (012) 3208-6919
E-mail: pubtc@sid.inpe.br
CONSELHO DE EDITORAO E PRESERVAO DA PRODUO
INTELECTUAL DO INPE (RE/DIR-204):
Presidente:
Marciana Leite Ribeiro - Servio de Informao e Documentao (SID)
Membros:
Dr. Gerald Jean Francis Banon - Coordenao Observao da Terra (OBT)
Dr. Amauri Silva Montes - Coordenao Engenharia e Tecnologia Espaciais (ETE)
Dr. Andr de Castro Milone - Coordenao Cincias Espaciais e Atmosfricas
(CEA)
Dr. Joaquim Jos Barroso de Castro - Centro de Tecnologias Espaciais (CTE)
Dr. Manoel Alonso Gan - Centro de Previso de Tempo e Estudos Climticos
(CPT)
Dra Maria do Carmo de Andrade Nono - Conselho de Ps-Graduao
Dr. Plnio Carlos Alval - Centro de Cincia do Sistema Terrestre (CST)
BIBLIOTECA DIGITAL:
Dr. Gerald Jean Francis Banon - Coordenao de Observao da Terra (OBT)
REVISO E NORMALIZAO DOCUMENTRIA:
Maria Tereza Smith de Brito - Servio de Informao e Documentao (SID)
Yolanda Ribeiro da Silva Souza - Servio de Informao e Documentao (SID)
EDITORAO ELETRNICA:
Maria Tereza Smith de Brito - Servio de Informao e Documentao (SID)
Andr Luis Dias Fernandes - Servio de Informao e Documentao (SID)
sid.inpe.br/mtc-m21b/2014/07.28.19.09-TDI
PROJETO E DESENVOLVIMENTO DE UM
CONTROLADOR DE MOTORES "BRUSHLESS" (BLDC)
PARA APLICAO EM VOLANTES DE INRCIA
INPE
So Jos dos Campos
2014
Esta obra foi licenciada sob uma Licena Creative Commons Atribuio-NoComercial 3.0 No
Adaptada.
This work is licensed under a Creative Commons Attribution-NonCommercial 3.0 Unported License.
ii
vi
vii
viii
AGRADECIMENTOS
Agradeo aos ensinamentos dos mestres do Instituto Nacional de Pesquisas
Espaciais que abriram meus horizontes para a pesquisa no ramo da
engenharia e tecnologias espaciais, em especial ao Dr. Valdemir Carrara pelo
empenho em orientar este trabalho. Agradeo s contribuies do Dr. Jos
Carlos de Souza Junior, do Dr. Rodrigo Alvite Romano e do Dr. Vanderlei
Cunha Parro do Instituto Mau de Tecnologia, pelas inestimveis informaes
prestadas e pelo constante apoio e incentivo ao meu desenvolvimento
profissional e acadmico. Por fim e no menos importante, agradeo a Deus
por estar presente em minha vida, agradeo a participao da esposa pelo
companheirismo e amor e agradeo tambm a famlia e amigos pelo estmulo
ao meu crescimento como ser humano, na pacincia pelo tempo investido e no
apoio recebido perante as dificuldades da vida.
ix
RESUMO
Este trabalho apresenta o projeto e o desenvolvimento de uma eletrnica para
controle de motores de corrente contnua sem escovas (Brushless DC Motor BLDC). A aplicao visada o emprego deste controlador em rodas de reao
para sistemas de controle de atitude de satlites. O principal objetivo e o foco
da aplicao foi o desenvolvimento e construo de vrios mtodos para
acionar o motor e medir os parmetros de desempenho. A placa projetada
criou uma plataforma adequada para o estudo do acionamento, e testes de
software para o acionamento das fases do BLDC. O uso de dispositivos
programveis, como micro-controladores e dispositivos programveis lgicos
como FPGA permitiram projetar diferentes estratgias de controle. Combinando
vrios tipos de sensores e dados externos adquiridos de sensores pela placa
eletrnica, procedimentos de controle em malha fechada puderam ser
experimentados com diferentes sensores. Os resultados so apresentados e o
desempenho comparado com o de uma roda de reao tpica.
xi
xii
ABSTRACT
This work presents the design and development of an electronic board to
control Brushless DC Motors (BLDC). The main application of this work is to
use the board to control the BLDC of a reaction wheel and to apply it to satellite
attitude control systems (ACS). The focus was the development and
construction of several methods to drive the motor and to measure the
performance parameters. The designed board created a plataform suitable for
BLDC driving studies and software testing. The use of programmable devices
like micro-controllers and logical programmable devices like FPGA allows to
project different control strategies. Combining many types of sensors and
external data acquired by the electronic board, closed loop control procedures
could be experimented with different sensors. The results collected from control
performance and a comparison of motor performance with a typical RW were
presented.
xiii
xiv
LISTA DE FIGURAS
xv
xvi
xvii
xviii
SID
TDI
SPG
Servio de Ps-Graduao
FPGA
BLDC
VHDL
VHSIC
SCD
PWM
ADC
LCD
MOSFET
ASIC
CC
Corrente Contnua
DMA
EMC
Electromagnetic Compatibility
LC
PID
RPM
xix
xx
SUMRIO
1.
INTRODUO ........................................................................................... 1
1.1.
Objetivo ...................................................................................................... 2
1.2.
Motivao ................................................................................................... 3
1.3.
Metodologia ................................................................................................ 6
2.
3.
3.1.
FPGA ....................................................................................................... 17
3.2.
Microcontroladores .................................................................................... 18
3.3.
MOSFETS ................................................................................................ 20
3.4.
3.5.
3.6.
Sensores.................................................................................................... 23
3.7.
Comunicao ............................................................................................. 26
3.8.
3.9.
4.
5.
5.1.
5.1.1.
5.1.2.
5.1.3.
5.2.
5.3.
xxi
5.4.
5.5.
5.6.
5.7.
5.8.
6.
CONCLUSES ......................................................................................... 55
xxii
1.
INTRODUO
jatos
de
gs
de
bobinas
geradoras
de
torque
magntico
Objetivo
Este trabalho tem por objetivo projetar e construir um prottipo de uma roda de
reao com caractersticas funcionais semelhantes quelas voltadas para
aplicaes espaciais. A roda desenvolvida capaz de realizar os acionamentos
eltricos de fase para motores de corrente contnua sem escovas (ou BLDC, do
Ingls Brushless DC motor) em diversas configuraes de polos e fases para
se criar os fundamentos requeridos pela eletrnica de uma roda de reao.
O circuito de acionamento eletrnico leva em conta a necessidade de estudar
os diversos mtodos para se energizar um motor BLDC e as muitas maneiras e
mtodos de constru-los, com a inteno de servir como um modelo
experimental, onde novas tcnicas de controle e mtodos de acionamento
possam ser geradas e testadas. Assim, a placa eletrnica para controle
capaz de permitir alterar o modo de acionamento das fases por software,
possibilitando diversos ensaios em uma mesma plataforma.
Em
resumo,
este
trabalho
apresenta
projeto,
desenvolvimento,
implementao e testes de um dispositivo eletrnico composto de um microcontrolador e uma unidade de FPGA para o controle e acionamento das fases
do motor BLDC, com capacidade de sensoriamento por meio de sensores Hall,
por sensor ptico (encoder), por medio da corrente das fases e medio das
tenses de cada fase. Alm da alimentao do motor, foi implementado o
monitoramento remoto e a medio da rotao e da corrente do motor, de
modo a permitir que se controle o funcionamento do motor numa aplicao
tpica para uma roda de reao em malha fechada.
1.2.
Motivao
espacial ou
gerados
satlite. A
1.3.
Metodologia
Fonte Chaveada
FPGA
Drivers
MOSFETS
Microprocessamento
Shunt
BLDC
Sensores Hall
USB RS232 RS485
M.Flash
ICSP
2.
Para o trabalho proposto, o motor BLDC a ser utilizado ser um motor DC sem
escovas convencional acoplado a um volante de inrcia com caractersticas
semelhantes s de uma roda de reao comercial de fabricao da SunSpace,
-3
H1
H2
H3
(a) Halls sensores
Va
Vb
Vc
(b) 6 passos de comutao
Vab
Vbc
Vca
0
10
11
12
13
14
3.
15
circuito
eletrnico
de
acionamento,
no
entanto,
precisa-se
16
3.1.
FPGA
17
FPGA
Acionamento dos
MOSFETS
Sensores Hall
Encoders ticos
Micro-controlador
Porta Paralela p/
troca de informaes
3.2.
Microcontroladores
18
Micro-controlador
Sinais de entrada
analgicos
(corrente do motor)
Acionamento dos
MOSFETS (via FPGA)
Sensores Hall
Encoders ticos
(via FPGA)
Comunicao Serial
ICSP
Memria Flash
Porta Paralela p/
troca de informaes
FPGA
19
Micro-controlador
Sinais de entrada
analgicos
(corrente do motor)
Acionamento dos
MOSFETS (via FPGA)
Sensores Hall
Encoders ticos
(via FPGA)
Comunicao Serial
ICSP
Memria Flash
Porta Paralela p/
troca de informaes
FPGA
3.3.
MOSFETS
20
FASE-A
FASE-B
FASE-C
FASE-D
FASE-E
+VCC
Q7
Q8
3
AT
5, 6
AB
Q10
3
CT
BB
5, 6
1
2
CB
3
ET
5, 6
1
2
Q11
3
DT
5, 6
1
2
Q9
3
BT
5, 6
1
DB
1
EB
7, 8
7, 8
7, 8
7, 8
7, 8
IRF7319TRPBF
IRF7319TRPBF
IRF7319TRPBF
IRF7319TRPBF
IRF7319TRPBF
R80
Resistor Shunt
0R1
21
EN-B
U2C
8
10
T/B-B
PRE-BT
MM74HCT08M
U3B
3
12
U2D
11
MM74HCT04M
13
PRE-BB
MM74HCT08M
3.5.
10K ; 5%
BT
R7
PRE-BB
R10
PRE-BT
Q2
BC817
BB
100R ; 5%
R9
10K ; 5%
100R ; 5%
22
+5V
CN10
R83
R84
R85
HALL1
HALL2
HALL3
L2
FASE-A
L3
FASE-B
L4
FASE-C
L5
FASE-D
L6
FASE-E
1K ; 5%
1K ; 5%
1K ; 5%
744901110
744901110
744901110
744901110
744901110
R87
R88
R89
R90
8K2 ; 5%
8K2 ; 5%
8K2 ; 5%
8K2 ; 5%
8K2 ; 5%
100nF
100nF
100nF
100nF
100nF
R86
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
52207-1590
R97
R98
R99
1K ; 5%
1K ; 5%
1K ; 5%
1K ; 5%
1K ; 5%
R96
R95
R91
1K ; 5%
R92
1K ; 5%
R93
1K ; 5%
R94
1K ; 5%
R100
1K ; 5%
VA
VB
VC
VD
VE
Figura 3.9 - Detalhe da conexo do motor, filtro LC e leitura das tenses das fases.
3.6.
Sensores
23
FASE-E
Q11
ET
+VCC
3
4
5, 6
+3V3A
1
EB
R77
C75
47K ; 5%
7, 8
IRF7319TRPBF
100nF
+3V3A
7
R78
R80
Resistor Shunt
0R1
1K ; 5%
3
R81
6
U16
MCP601-I/SN
R82
R79
I-FASE
1K ; 5%
NC
1K ; 5%
24
+5V
R101
R102
R103
PHOTO-B
Q12
330R ; 5%
330R ; 5%
330R ; 5%
PHOTO-A
Q13
D10
PT19-21B
PT19-21B
CONEXO ENCODER
PHOTO-A
PHOTO-B
R54
R55
R56
ENC-A
ENC-B
ROT
10k ; 5%
10k ; 5%
10k ; 5%
+5V
CN8
1
2
3
4
5
R60
R59
R58
10k ; 5%
10k ; 5%
10k ; 5%
25
Comunicao
Para se comunicar com o exterior a placa foi dotada de conexo ICSP para
gravar o programa em C, e uma conexo JTAG utilizada para depurao do
programa e para gravar programas no FPGA. O projeto da placa incorpora
ainda sadas seriais para habilitar comandos e para permitir o monitoramento
remoto por uma outra unidade computacional, como um PC, por exemplo. Essa
conexo remota permitir ajustar os pontos de operao (set-points) de
operao da roda de reao. Foi criada tambm uma porta paralela entre o
FPGA e o micro-controlador, para que se possa transmitir dados entre as
unidades de processamento. O circuito de comunicao apresentado na Fig.
3.13.
USB
Microprocessamento
Debug
ICSP/JTAG
RS232/458
I/Os
OU
26
Fonte de alimentao
3.8.
R68
(nc)
CN9
-
3
2
1
GS1M-LTP
D6
+VCC
U13
1
11.0183
DC-005 - J4
C65
C63
C64
5
3
VIN
FEEDBACK
4
R69
0R
ON-OFF
GND
VOUT
100nF
100nF
LM2576D2T
+5V
U14
L1
03.0071
744 770 968 1
680uH ; 1,1A
R70
C68
1K ; 5% C67
+3V3
VIN
VOUT
GND
3
C66
TC1262-3.3VDB
C69
100nF
100nF
D8
VD
POWER
100U F ; 25V
100U F ; 25V
SK 3 1 0 B - T PC T - N D
100U F ; 25V
D7
3.9.
27
17
1
16
1
1
2
1
3
10
11
12
13
14
15
2
1
1
1
2
1
2
8
1
14
13
12
11
2
9
4
1
2
8
6
3
6
3
10
2
4
12
13
14
1
11
10
11
3
5
10
12
13
2
1
14
1
2
2
4
5
2
2
1
1
8
10
2
2
11
12
13
14
1
1
2
1
2
1
1
1
2
1
16
15
14
13
12
11
10
10
1
4
1
1
2
1
1
2
1
1
1
1
2
2
2
2
1
2
2
1
1
2
19
2
20
1
1
17
18
15
16
13
1
14
11
12
10
1
1
7
2
5
2
1
8
1
2
1
2
2
1
1
4
3
28
4.
29
u (t ) = Kp.e(t ) + Ki e(t ) dt + Kd
0
d
e(t )
dt
(4.1)
bi=Ki*h/TT
ad=(2*Td-N*h)/(2*Td+N*h)
bd=2*Kd*N*Td/(2*Td+N*h)
aO=h/Tt
"Control algorithm
r=adin(chl)
y=adin(ch2)
"integral gain
"derivative gain
31
P=Kp*(b*ysp-y)
"compute proportional part
D=ad*D-bd*(y-yold)
"update derivative part
v=P+I+D
"compute temporary output
u=sat(v,ulow,uhigh)
"simulate actuator saturation
daout(chl)
"set analog output chl
I=I+bl*(ysp-y)+a0*(u-v)
"update integral
yold=y
"update old process output
PID_SPEED_N
PID_SPEED_H
PID_SPEED_TT
PID_SPEED_KP
PID_SPEED_KI
PID_SPEED_KD
20.0
40.0
40.0
500.0
10000.0
0.0
32
//Header
//0x7F
Address
0xF1
Packet ID
0x40
Data
0x00
0x00
0x7A
0x44
de interrupo do micro-
33
borda
de
flag
de
34
35
36
5.
37
38
Essa interface possibilita que seja alterado o alvo para o controlador, seja ele
alvo de corrente ou alvo de rotao, isto , consegue comandar a roda de
reao para que ela atue na rotao ou corrente que se deseja. Alm de
comandar a roda de reao, o software em questo tambm armazena os
valores de rotao e corrente em um arquivo de texto para posterior anlise.
Na Fig. 5.3 detalhada a construo e montagem do circuito eletrnico com o
volante de inrcia acoplado ao motor Maxxon.
Volante de Inrcia
39
5.1.
(5.1)
(5.2)
41
(5.3)
(5.4)
(5.5)
(5.6)
J w / km
b / km
c / km
( s c ) / k m ] (x1
T
x2
x3
x4
x5 )
(5.7)
(5.8)
Hk Iw k
0 0 0 0
(5.9)
Fator utilizado para ajuste da atenuao do termo relacionado a s; valores empricos so atribudos a ele
(Romano, 2010).
42
43
44
45
senoidal, comandada por um controlador PI embarcado em um microcontrolador, usado como controlador do motor BLDC.
Os resultados mostraram que os parmetros estimados variam pouco com a
velocidade angular, e apresentam mudanas mais acentuadas em baixas
rotaes. Isto sugere que o modelo do atrito necessita ser aprimorado, pois seu
efeito mais acentuado quando o rotor se encontra em baixas velocidades.
Alm disso, um projeto mecnico do mancal do volante de inrcia muito
importante para um ensaio mais realista condizente com uma roda de reao
apta para voo,
5.2.
RPM
1000
500
0
-500
10
15
20
25
30
35
40
45 t(s)
-1000
-1500
46
5.3.
10 15 20 25 30 35 40 45 50 55 60 65t(s)
47
3000
RPM
2500
2000
1500
1000
500
0
0
5 10 15 20 25 30 35 40 45 50 55 60 65
t(s)
5.4.
tpico
decorrente
de
um
atrito
viscoso
(decaimento
48
5.5.
Estabilidade em rotao
5.6.
Estabilidade em corrente
49
250
240
230
220
210
200
190
180
170
160
150
RPM
t(s)
0
10
5.7.
RPM
3000
2000
1000
0
0
50
100
150
200
250
300
350
400
450
500
t(s)
50
5000
RPM
4000
3000
2000
1000
0
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
170
180
190
200
210
220
230
240
250
260
270
t(s)
J nas Fig 5.17 e 5.18, nas quais se utilizou uma frequncia no sinal de
referncia de 0,022 Hz e 0,06 Hz respectivamente, observa-se uma queda
significativa na amplitude da rotao e um atraso entre a referncia e a
resposta da roda.
5000
RPM
4000
3000
2000
1000
0
0
10
20
30
40
50
60
70
80
90
100
110
120
130
t(s)
RPM
3000
2000
1000
0
0
10
15
20
25
30
35
40
45
t(s)
Pode-se notar na Fig. 5.19, para um comando em frequncia de 0,333 Hz, que
a roda j no responde ao sinal de referncia, e apresenta um ngulo de fase
de aproximandamente 90.
51
5000
4000
RPM
3000
2000
1000
0
0
t(s)
5.8.
Torque medido
52
(5.10)
53
54
6.
CONCLUSES
55
56
REFERNCIAS BIBLIOGRFICAS
57
58
59
60
61
62
63
64
65
66
67
68
69
70
1
2
3
4
1
2
3
1
3
3
2
10
19
20
17
2
18
15
16
13
14
11
1
1
12
10
2
8
3
1
1
2
4
3
6
5
1
2
3
1
3
2
1
10
19
20
17
2
18
15
16
13
14
11
1
1
12
10
2
8
3
6
1
2
4
3
6
5
71
72
17
1
16
1
1
2
1
3
10
11
12
13
14
15
2
4
5
1
2
1
2
1
10
14
13
12
13
14
10
11
2
4
12
1
8
11
4
8
1
2
1
2
8
2
11
3
5
10
12
13
14
2
3
1
2
1
1
2
4
5
2
2
1
10
1
2
12
2 1
13
14
1
11
2
1
2
1
2
1
16
15
14
4
1
2
8
5
4
13
12
11
10
1
10
1
1
2
1
5
1
2
1
1
2
2
2
2
2
2
1
3
2
1
4
2
1
1
1
2
19
2
20
17
18
15
2
16
13
1
14
11
12
1
1
10
7
2
5
2
1
2
1
2
2
1
1
4
3
2
2
6
2
17
16
1
1
1
10
11
12
13
14
15
1
1
2
1
4
2
1
1
1
1
1
1
2
3
2
3
1
2
1
1
3
2
1
2
1
1
2
2
1
2
1
4
1
10
1
1
2
1
2
1
1
19
2
20
17
2
18
15
16
13
14
11
12
10
7
2
2
8
5
2
1
2
4
3
6
5
73
74
Descrio
Valor
Quant.
15pF
Capacitor de tntalo
10uF ; 6V3
100nF
22
Capacitor de tntalo
10uF ; 10V
Capacitor cermico
100nF
28
Capacitor cermico
18pF
0u1F ; 25V
100UF ; 25V
Conector-BOX-header
10 vias (2 x 5)
USB
Led smd
Diodo de Sinal
LL4148
Diodo retificador
LL4007
Diodo Schottky
SK310B-TPCT-ND
Indutor
75R
Indutor
680uH ; 1,1A
Indutor
10nH ; 600mA
BC817
IRF7319TRPBF
NPN Phototransistor
PT19-21B
Resistor 10K ; 5%
Resistor 330R ; 5%
Resistor 1K ; 5%, 8K2 ; 5%, 10K ; 5%, 47K ; 5%, 100R ; 5%, N
50
34
Resistor 0R
Resistor 33R ; 5%
Resistor 220R ; 5%
75
Resistor 0R1
Microcontrolador PIC
PIC32MX675F512H
MM74HCT08M
Hex Inverter
MM74HCT04M
Cyclone II Family
EP2C8T144C8N
EPCS16
MAX485CSA
MAX3232CSE
Microcontroller,
ATSAM4S16CA-AU
LM2576
Regulador de tenso
TC1262-3.3
LT1963AES8#PBF
Amplificador Operacional
MCP601
Cristal oscilador
8MHz
Oscilador
50MHz
Cristal oscilador
32KHz
76
#ifndef
#define
_SW_H_
_SW_H_
#include "fw.h"
77
/*********************************************************************
*******************\
*******
*********
*******
MAPAS DE FLAGS
*********
*******
*********
\*********************************************************************
*******************/
extern union unsigned_char flags_sw1;
software
extern union unsigned_char flags_sw2;
software
// Flags de
// Flags de
/*********************************************************************
*******************\
*
Definio de constantes
*
\*********************************************************************
*******************/
/**************************************************\
*
Diretivas de compilao
*
\**************************************************/
// Modo
#define
#define
#define
/**************************************************\
*
Flags
*
\**************************************************/
#define FS_RESERVADO
flags_sw1.bit0
//
Indica se o cdigo de barras deve ser zerado ou no aps sair da tela
de solicitao do cdigo de barras
/**************************************************\
*
Auxiliares
*
\**************************************************/
typedef enum {
BLDC_PARALIZADO,
BLDC_ON,
} SM_BLDC;
#define TIMEOUT_BLDC
// 10 * 1ms
#define TIMEOUT_PROTOCOLO_AUTOMATICO
// 100 * 1ms
10
100
// PID:
#define PID_SPEED
0
// Comente esta linha caso no queira utilizar PID para o controle da
bomba BFP
78
#define PID_CURRENT
1
// Comente esta linha caso no queira utilizar PID para o controle da
bomba BFP
#define PID_SPEED_N
#define PID_SPEED_H
#define PID_SPEED_TT
#define PID_SPEED_KP
//500000.0
#define PID_SPEED_KI
#define PID_SPEED_KD
20.0
40.0
40.0
500.0
#define
#define
#define
#define
#define
#define
20.0
40.0
40.0
1000.0
10000.0
0.0
10000.0
0.0
PID_CURRENT_N
PID_CURRENT_H
PID_CURRENT_TT
PID_CURRENT_KP
PID_CURRENT_KI
PID_CURRENT_KD
#define QTD_MEDIA_RPM
#define QTD_MEDIA_CORRENTE
32
128
/*********************/
#define NUM_PAR_POLOS
#define NUM_FASES
#define PASSOS_COMUTACAO
#define PASSOS_POR_VOLTA
NUM_PAR_POLOS*NUM_FASES*PASSOS_COMUTACAO
#define HALLS_POR_VOLTA
NUM_PAR_POLOS*NUM_FASES*PASSOS_COMUTACAO
4
3
6
/*********************************************************************
*******************\
*
Macros
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Definio de estruturas do mdulo
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria de
programa
*
\*********************************************************************
*******************/
// - Globais ao sistema:
79
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Prototipagem
*
\*********************************************************************
*******************/
inline void inicializa_sw( void );
inline void sm_processo_bldc( void );
void calcula_rpm( void );
void calcula_rpm_medio( void );
void calcula_corrente_media( void );
void formata_valor( long numero, unsigned char casas_decimais,
unsigned char opcao, unsigned char *str_valor );
void copia_string( const unsigned char *origem, unsigned char
*destino, unsigned char tamanho );
unsigned char tamanho_string( unsigned char *str );
void inicializa_memoria_dados_eeprom( void );
void carrega_dados( void );
void salva_dados( void );
/*********************************************************************
*******************\
*
Mensagens de error ou warning
*
\*********************************************************************
*******************/
#endif //_SW_H_
80
/*********************************************************************
*******************\
*
Software para controle de motor BLDC
*
*
*
*
Desenvolvido por Fernando de Almeida Martins
*
*
*
*
E-mail: fmartins_eng@yahoo.com
*
*
*
* Data: 13/02/2012
Verso: 1.0 *
*
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Controle de Verses
*
*
*
* Responsvel
Verso
Data
Descrio
*
*
*
* Fernando Martins sw.c
13/02/2012 Rotinas bases
*
* Fernando Martins sw.h
13/05/2015 Sintonia para
prottipo
*
*
\*********************************************************************
*******************/
#include "sw.h"
/*********************************************************************
*******************\
*
Definio de variveis do software em memria
de programa
*
\*********************************************************************
*******************/
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Definio de variveis de flag
*
\*********************************************************************
*******************/
81
// Flags de
// Flags de
/*********************************************************************
*******************\
*
Definio de variveis do software em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao software:
// - Globais ao sistema:
SM_BLDC sm_bldc = BLDC_PARALIZADO;
// 1+6,
2+4,
3+4,
3+5,
1+5,
2+6,
( 0bABC )
/*********************************************************************
*******************\
*
Funo principal
*
\*********************************************************************
*******************/
int main( void )
{
static unsigned int ponteiro_alvo = 0;
static unsigned char contador = 0;
#if( TIPO_SW == SW_TESTE )
testa_firmware();
#endif
inicializa_sw();
InitializeSystem();
// init usb
#if defined(USB_INTERRUPT)
USBDeviceAttach();
#endif
while( 1 )
{
ClrWdt();
if( F_1MS )
{
F_1MS = 0;
sm_processo_bldc();
}
if( F_10MS )
{
F_10MS = 0;
82
le_fpga_poe_registros();
contador++;
if (contador > 1)
{
contador = 0;
//dados.rpm_alvo = senoide_rpm[ponteiro_alvo++];
if (ponteiro_alvo >= 300)
{
ponteiro_alvo = 0;
}
}
}
if( F_PORTA_SERIAL_PCT_RX )
{
trata_pct_serial_rx();
F_PORTA_SERIAL_PCT_RX = 0;
}
}
return( 0 );
}
/*********************************************************************
*******************\
*
Implementao das funes
*
\*********************************************************************
*******************/
void calcula_rpm( void )
{
unsigned char i = 0;
signed long aux;
static unsigned int buffer_rpm[30];
static unsigned char ponteiro = 0;
buffer_rpm[ponteiro++] = dados.contador_hall;
dados.contador_hall = 0;
if (ponteiro >= 30)
{
ponteiro = 0;
}
aux = 0;
for ( i = 0 ; i < 30 ; i++)
{
aux += buffer_rpm[i];
}
if (dados.sentido_rotacao_real == SENTIDO_HORARIO)
{
dados.rpm_real = aux * 10;
}
else
{
83
84
(dados.parametros.on == OFF)
sm_bldc = BLDC_PARALIZADO;
}
timeout2 --;
if (timeout2 == 0)
{
timeout2 = TIMEOUT_PROTOCOLO_AUTOMATICO;
if ( dados.tipo_protocolo == SIMPLIFICADO)
{
envia_resposta(ID_WR_SPEED_MEASURED,
dados.rpm_real_medio);
envia_resposta(ID_WR_CURRENT_MEASURED,
dados.corrente_real_media);
}
}
break;
}
}
85
86
ponteiro = 0;
}
aux = 0;
for (i = 0; i < QTD_MEDIA_CORRENTE; i++)
{
aux += acc[i];
}
if ((dados.sentido_rotacao_real == SENTIDO_ANTI_HORARIO) ||
(dados.freio == 1))
{
dados.corrente_real_media = -aux / (QTD_MEDIA_CORRENTE/8);
}
else
{
dados.corrente_real_media = aux / (QTD_MEDIA_CORRENTE/8);
}
}
/*********************************************************************
*******************\
* inicializa_sw
*
* Rotina de inicializao do software
*
*
*
* Parmetros: void
*
* Retorno
: void
*
\*********************************************************************
*******************/
void inicializa_sw( void )
{
unsigned char i;
inicializa_fw();
// Zera flags
flags_sw1.value = 0;
flags_sw2.value = 0;
//inicializa_memoria_dados_eeprom();;
// Inicializa mdulo controle
inicializa_controle();
#if( defined( PID_SPEED ) )
// Carrega parmetros de controle da bomba de fluxo positivo
controle.pid[ PID_SPEED ].N = PID_SPEED_N;
// Plo
limitador do ganho derivativo
controle.pid[ PID_SPEED ].H = PID_SPEED_H;
// Intervalo
de amostragem para PID, em segundos
87
controle.pid[ PID_SPEED
tracking para o anti-windup
controle.pid[ PID_SPEED
proporcional
controle.pid[ PID_SPEED
integral
controle.pid[ PID_SPEED
derivativo
#endif
].TT = PID_SPEED_TT;
// Tempo de
].bp = PID_SPEED_KP;
// Banda
].ti = PID_SPEED_KI;
// Tempo
].td = PID_SPEED_KD;
// Tempo
/*********************************************************************
*******************\
* time_out
*
* Rotina para contar e indicaqr quanto o tempo estourar
*
*
*
* Parmetros: tempo inicial
*
* Retorno
: 0 tempo estourado, >0 contagem em andamento , -1 j
acabou
*
\*********************************************************************
*******************/
unsigned int time_out ( unsigned char inicia, unsigned int
tempo_inicial)
{
88
89
/*********************************************************************
*******************\
*
Software para controle de motor BLDC
*
*
*
*
Desenvolvido por Fernando de Almeida Martins
*
*
*
*
E-mail: fmartins_eng@yahoo.com
*
*
*
* Data: 15/04/2014
Verso: 1.0 *
*
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Controle de Verses
*
*
*
* Responsvel
Verso
Data
Descrio
*
*
*
* Fernando Martins protocolo.h
15/04/2014 Rotinas
bases
*
*
*
*
*
\*********************************************************************
*******************/
#ifndef PROTOCOLO_SERIAL_H
#define
PROTOCOLO_SERIAL_H
#include "..\fw\fw.h"
// Arquivo de
definio de pinos, variveis e funes do firmware
/*********************************************************************
*******************\
*******
*********
*******
MAPAS DE FLAGS
*********
*******
*********
\*********************************************************************
*******************/
extern union unsigned_char flags_protocolo;
Flags de software
90
//
/*****
*
bit0:
F_PROTOCOLO_RESERVADO
****/
/*********************************************************************
*******************\
*
Definio de variveis do firmware em memria
de programa
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Definio de constantes
*
\*********************************************************************
*******************/
#define HEADER
#define NODE_ADDRESS
0x7F
0xF1
91
0x10
//RW speed
0x11
//RW motor
0x13
//Gyro
0x14
//Gyro raw
0x15
0x17
//Status
//Controller
0x18
//Software
0x19
//RW temperature
0x1A
//RW pressure
0x1B
//Inertial delta
0x1C
//RW speed
0x1D
//RW motor
0x40
//RW speed
0x41
//RW current
0x42
//Inertial rate
0x43
//Inertial ?
0x44
//Gain K1 for
//#define ID_K2_GAIN_INERTIAL_RATE
inertial rate PI controller
#define ID_K1_GAIN_SPEED
wheel speed PI controller
#define ID_K2_GAIN_SPEED
wheel speed PI controller
//#define ID_K1_GAIN_INERTIAL_ANGLE
inertial delta angle P controller
#define ID_RW_GYRO_ON_OFF
ON/OFF switch*
//#define ID_GYRO_OFFSET_BIAS
(bias) correction
0x45
//Gain K2 for
0x47
//Gain K1 for
0x48
//Gain K2 for
0x49
0x4A
0x4B
//Gain K1 for
//RW & Gyro
//Gyro offset
/**************************************************\
*
Diretivas de compilao
*
\**************************************************/
/**************************************************\
*
Flags
*
\**************************************************/
#define F_PROTOCOLO_RESERVADO
flags_protocolo.bit0
Indica se o mdulo I2C master por HW j foi inicializado (
necessrio, pois mais de um mdulo pode chamar a rotina de
inicializao e isto pode causar problemas)
/**************************************************\
*
constantes e estruturas
\**************************************************/
//
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria de
programa
*
\*********************************************************************
*******************/
// - Globais ao sistema:
// - Globais ao mdulo:
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao sistema:
// - Globais ao mdulo:
/*********************************************************************
*******************\
92
Macros
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Prototipagem
*
\*********************************************************************
*******************/
inline void trata_pct_serial_rx( void );
void trata_protocolo_serial(void);
void envia_resposta_curta( unsigned char id );
void envia_resposta( unsigned char id, signed long data );
/****************************************************************\
*
Funes do mdulo
*
\****************************************************************/
#endif
/* PROTOCOLO_SERIAL_H */
93
/*********************************************************************
*******************\
*
Software para controle de motor BLDC
*
*
*
*
Desenvolvido por Fernando de Almeida Martins
*
*
*
*
E-mail: fmartins_eng@yahoo.com
*
*
*
* Data: 15/04/2014
Verso: 1.0 *
*
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Controle de Verses
*
*
*
* Responsvel
Verso
Data
Descrio
*
*
*
* Fernando Martins protocolo.h
15/04/2014 Rotinas
bases
*
*
*
*
*
\*********************************************************************
*******************/
#include "protocolo_serial.h"
/*********************************************************************
*******************\
*
Flags do mdulo
*
\*********************************************************************
*******************/
union unsigned_char flags_protocolo;
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria de
programa
*
94
\*********************************************************************
*******************/
// - Globais ao mdulo:
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao mdulo:
typedef union {
long llong;
float ffloat;
} Unionlonttofloat;
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Funes estticas
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Vetores de interrupo
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Implementao das funes
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
*
95
96
97
/*
MUDA SPEED 1000RPM
7F F1 40 00 00 7A 44
SPEED 2000 RPM
7F F1 40 00 00 FA 44
SPEED -1000RPM
7F F1 40 00 00 7A C4
CORRENTE 100MA
7F F1 41 00 00 C8 42
CORRENTE 200MA
7F F1 41 00 00 48 43
REQUEST SPEED
7F F1 10
REQUEST CURRENT
98
7F F1 11
*/
/*********************************************************************
*******************\
* trata_pct_serial_rx
*
* Rotina para tratamento do pacote serial recebido. Os pacotes
recebidos aqui referem- *
* se aos dados enviados pelo leitor de cdigo de barras
*
*
*
* Parmetros: void
*
* Retorno
: void
*
\*********************************************************************
*******************/
inline void trata_pct_serial_rx( void )
{
if (( uart_1.rx[ 0 ] == HEADER) && ( uart_1.rx[ 1 ] ==
NODE_ADDRESS) )
{
trata_protocolo_serial();
dados.tipo_protocolo = SUNSPACE; // a partir de ento comeo a
trabalhar no protocolo sunspace
}
uart_1.tam_rx = 0;
}
void trata_protocolo_serial(void)
{
union unsigned_char aux;
static unsigned char buffer_serial[5];
Unionlonttofloat longtofloat;
buffer_serial[0] =
buffer_serial[1] =
buffer_serial[2] =
buffer_serial[3] =
buffer_serial[4] =
uart_1.tam_rx = 0;
uart_1.rx[
uart_1.rx[
uart_1.rx[
uart_1.rx[
uart_1.rx[
2
3
4
5
6
];
];
];
];
];
switch (buffer_serial[0])
{
case ID_WR_SPEED_MEASURED:
measured by shaft encoder (rpm)
envia_resposta(ID_WR_SPEED_MEASURED,
dados.rpm_real_medio);
break;
case ID_WR_CURRENT_MEASURED:
current measured (mA)
envia_resposta(ID_WR_CURRENT_MEASURED,
dados.corrente_real_media);
break;
case ID_STATUS:
//RW speed
//RW motor
//Status
99
Bit 1:
Bit 4:
Bit 5:
aux.value = 0;
aux.bit1 = (dados.parametros.on? 1 :
RW On.
aux.bit4 = (dados.tipo_controle? 0 :
Current loop active.
aux.bit5 = (dados.tipo_controle? 1 :
Speed loop active.
envia_resposta(ID_STATUS, aux.value
break;
0);
//
1);
//
0);
//
);
case ID_RW_SPEED_CONTROL_ON:
//RW speed
control ON & speed reference (rpm)
longtofloat.llong = buffer_serial[1] +
buffer_serial[2]*0x100 + buffer_serial[3]*0x10000 +
buffer_serial[4]*0x1000000;
dados.rpm_alvo = (unsigned long)longtofloat.ffloat;
envia_resposta_curta(ID_RW_SPEED_CONTROL_ON);
dados.tipo_controle = 0; //PID_SPEED;
break;
case ID_RW_CURRENTE_CONTROL_ON:
//RW current
control ON & current reference (mA)
longtofloat.llong = buffer_serial[1] +
buffer_serial[2]*0x100 + buffer_serial[3]*0x10000 +
buffer_serial[4]*0x1000000;
dados.corrente_alvo = (unsigned long)longtofloat.ffloat;
envia_resposta_curta(ID_RW_CURRENTE_CONTROL_ON);
dados.tipo_controle = 1; //PID_CURRENT;
break;
case ID_K1_GAIN_SPEED:
//Gain K1 for
wheel speed PI controller
longtofloat.llong = buffer_serial[1] +
buffer_serial[2]*0x100 + buffer_serial[3]*0x10000 +
buffer_serial[4]*0x1000000;
controle.pid[0].bp = (unsigned long)longtofloat.ffloat;
envia_resposta_curta(ID_K1_GAIN_SPEED);
break;
case ID_K2_GAIN_SPEED:
wheel speed PI controller
longtofloat.llong = buffer_serial[1] +
buffer_serial[2]*0x100 + buffer_serial[3]*0x10000 +
buffer_serial[4]*0x1000000;
controle.pid[0].ti = longtofloat.ffloat;
envia_resposta_curta(ID_K2_GAIN_SPEED);
break;
//Gain K2 for
case ID_RW_GYRO_ON_OFF:
//RW & Gyro
ON/OFF switch*
dados.parametros.on = (buffer_serial[1]? 1 : 0);
envia_resposta_curta(ID_RW_GYRO_ON_OFF);
break;
case ID_WR_SPEED_REFERENCE:
envia_resposta(ID_WR_SPEED_REFERENCE, dados.rpm_alvo);
break;
case ID_WR_CURRENT_REFERENCE:
envia_resposta(ID_WR_CURRENT_REFERENCE,
dados.corrente_alvo);
100
break;
default:
break;
}
}
void envia_resposta_curta( unsigned char id )
{
porta_serial.tx[0] = HEADER;
porta_serial.tx[1] = NODE_ADDRESS;
porta_serial.tx[2] = id;
porta_serial.tam_tx = 3;
tx_pacote_porta_serial();
}
void envia_resposta( unsigned char id, signed long data )
{
Unionlonttofloat longtofloat;
static unsigned char tam_pacote_atual = 0;
tam_pacote_atual = porta_serial.tam_tx;
longtofloat.ffloat = data;
porta_serial.tx[tam_pacote_atual] = HEADER;
porta_serial.tx[tam_pacote_atual + 1] = NODE_ADDRESS;
porta_serial.tx[tam_pacote_atual + 2] = id;
porta_serial.tx[tam_pacote_atual + 3] = longtofloat.llong;
porta_serial.tx[tam_pacote_atual + 4] = longtofloat.llong >> 8;
porta_serial.tx[tam_pacote_atual + 5] = longtofloat.llong >> 16;
porta_serial.tx[tam_pacote_atual + 6] = longtofloat.llong >> 24;
porta_serial.tam_tx = tam_pacote_atual + 7;
tx_pacote_porta_serial();
}
/*************************************************/
/*************************************************/
/*************************************************/
101
/*********************************************************************
*******************\
*
Mdulo Controle
*
\*********************************************************************
*******************/
#ifndef _CONTROLE_H_
#define _CONTROLE_H_
#define MOD_CONTROLE
#include "..\..\fw\fw.h"
// Arquivo de
definio de pinos, variveis e funes do firmware
/*********************************************************************
*******************\
*******
*********
*******
MAPAS DE FLAGS
*********
*******
*********
\*********************************************************************
*******************/
extern union unsigned_char flags_controle;
// Definio de
flags do
/*********************************************************************
*******************\
*
Definio de constantes
*
\*********************************************************************
*******************/
/********************************************\
*
Flags:
*
\********************************************/
/********************************************\
*
Auxiliares:
*
\********************************************/
// Nmero de controladores ONOFF
#define CONTROLE_TOTAL_ONOFF
// Ao do controle ONOFF
#define ONOFF_ACAO_NORMAL
#define ONOFF_ACAO_REVERSA
0
1
/*********************************************************************
*******************\
102
// x 10
struct
{
unsigned char on
: 1;
unsigned char acao : 1;
int histerese;
} onoff[ CONTROLE_TOTAL_ONOFF ];
} Controle;
// x 10
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria de
programa
*
\*********************************************************************
*******************/
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao sistema:
extern Controle controle;
/*********************************************************************
*******************\
*
Macros
*
\*********************************************************************
*******************/
103
/*********************************************************************
*******************\
*
Prototipagem
*
\*********************************************************************
*******************/
inline void inicializa_controle( void );
void inicia_pid_controle( unsigned char n );
inline void finaliza_pid_controle( unsigned char n );
unsigned int algoritmo_pid_controle( unsigned char n, float sp, float
y );
void inicia_onoff_controle( unsigned char n );
inline void finaliza_onoff_controle( unsigned char n );
unsigned int algoritmo_onoff_controle( unsigned char n, float sp,
float pv );
#endif // _CONTROLE_H_
104
/*********************************************************************
*******************\
*
Mdulo Controle
*
*
*
\*********************************************************************
*******************/
#include "mod_controle.h"
definio variveis e funes do mdulo Controle
// Arquivo de
/*********************************************************************
*******************\
*
Flags do mdulo
*
\*********************************************************************
*******************/
union unsigned_char flags_controle;
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria de
programa
*
\*********************************************************************
*******************/
// - Globais ao mdulo:
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao mdulo:
struct
{
unsigned char estado : 1;
unsigned char inicio : 1;
// Estado: ON/OFF
// Incio do controle
// Estado: ON/OFF
// Incio do controle
float ad;
// Termo ad
105
float bd;
float bi;
float bt;
float d_ant;
float y_ant;
float u;
com saturao (0..100%)
float v;
sem saturao
float p_n;
float i_n;
float d_n;
} pid[ CONTROLE_TOTAL_PID ];
//
//
//
//
//
//
Termo bd
Termo bi
Termo bt
d(n-1)
pv(n-1)
Esforo de controle
// Esforo de controle
// Termo proporcional
// Termo integral
// Termo derivativo
// - Globais ao sistema:
Controle controle;
/*********************************************************************
*******************\
*
Funes estticas
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Vetores de interrupo
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
*
Implementao das funes
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
* inicializa_controle
*
* Rotina para iniciar o mdulo Controle
*
*
*
* Parmetros: void
*
* Retorno
: void
*
\*********************************************************************
*******************/
106
// Zera flags do
// Zera variveis
for( i = 0 ; i < CONTROLE_TOTAL_ONOFF ; i++ )
{
onoff[ i ].estado = OFF;
onoff[ i ].inicio = 1;
onoff[ i ].saida = 0;
controle.onoff[ i ].on = 0;
controle.onoff[ i ].acao = ONOFF_ACAO_NORMAL;
}
for( i = 0 ; i < CONTROLE_TOTAL_PID ; i++ )
{
pid[ i ].estado = OFF;
pid[ i ].inicio = 1;
controle.pid[ i ].N = 1.0;
controle.pid[ i ].TT = 20.0;
controle.pid[ i ].H = 0.2;
controle.pid[ i ].on = 0;
}
}
/*********************************************************************
***********\
* inicia_pid_controle
*
* Rotina de liberao do algoritmo de PID
*
*
*
* Parmetros: ndice do controlador PID
*
* Retorno:
void
*
\*********************************************************************
***********/
void inicia_pid_controle( unsigned char n )
{
controle.pid[ n ].on = 1;
pid[ n ].estado = ON;
pid[ n ].inicio = 1;
pid[
pid[
pid[
pid[
n
n
n
n
].i_n
].d_n
].d_ant
].y_ant
=
=
=
=
0.0;
0.0;
0.0;
0.0;
107
/*********************************************************************
***********\
* finaliza_pid_controle
*
* Rotina de finalizao do algoritmo de PID
*
*
*
* Parmetros: ndice do controlador PID
*
* Retorno:
void
*
\*********************************************************************
***********/
inline void finaliza_pid_controle( unsigned char n )
{
controle.pid[ n ].on = 0;
pid[ n ].estado = OFF;
}
/*********************************************************************
***********\
* algoritmo_pid_controle
*
* Rotina de execuo do algoritmo de controle PID
*
*
*
* Parmetros: ndice do controlador PID, set-point e varivel de
controle (em *
*
ponto flutuante)
*
* Retorno:
esforo do controle, de 0 a 1000
*
\*********************************************************************
***********/
unsigned int algoritmo_pid_controle( unsigned char n, float sp, float
y )
{
if( pid[ n ].estado == ON )
{
// Clculo do termo ad
pid[ n ].ad = controle.pid[ n ].td / ( controle.pid[ n ].td +
( controle.pid[ n ].N * controle.pid[ n ].H ) );
// Clculo do termo bd
pid[ n ].bd = ( 100.0 / controle.pid[ n ].bp ) *
controle.pid[ n ].N * pid[ n ].ad;
// Se Ti = 0, garante ao integral nula
if( controle.pid[ n ].ti == 0 )
{
pid[ n ].bi = 0.0;
pid[ n ].i_n = 0.0;
pid[ n ].bt = 0.0;
108
}
else
{
pid[ n ].bi = ( ( 100.0 / controle.pid[ n ].bp ) *
controle.pid[ n ].H ) / controle.pid[ n ].ti;
pid[ n ].bt = controle.pid[ n ].H / controle.pid[ n ].TT;
}
// Clculo do termo proporcional
pid[ n ].p_n = ( 100.0 / controle.pid[ n ].bp
) * ( sp - y
);
// Clculo do termo derivativo (apenas se ainda no foi
calculado)
if( !pid[ n ].inicio )
{
pid[ n ].d_n = ( pid[ n ].ad * pid[ n ].d_ant ) + ( pid[ n
].bd * ( pid[ n ].y_ant - y ) );
// Atualiza regressor do termo derivativo
pid[ n ].d_ant = pid[ n ].d_n;
}
else
{
pid[ n ].inicio = 0;
}
// Esforo de controle sem saturao
pid[ n ].v = pid[ n ].p_n + pid[ n ].i_n + pid[ n ].d_n;
// Esforo de controle com saturao
if( pid[ n ].v < 0.0 )
{
pid[ n ].u = 0.0;
}
else if( pid[ n ].v > 100.0 )
{
pid[ n ].u = 100.0;
}
else
{
pid[ n ].u = pid[ n ].v;
}
// i(n+1)
pid[ n ].i_n = ( pid[ n ].bi * ( sp - y ) ) + ( pid[ n ].bt *
( pid[ n ].u - pid[ n ].v ) ) + pid[ n ].i_n;
// Atualiza regressor da varivel de processo
pid[ n ].y_ant = y;
// Retorna esforo do controle (0 a 100.0%)
return( pid[ n ].u * 10.0 );
}
return( 0 );
}
109
/*********************************************************************
***********\
* inicia_onoff_controle
*
* Rotina de liberao do algoritmo de ONOFF
*
*
*
* Parmetros: ndice do controlador ONOFF
*
* Retorno:
void
*
\*********************************************************************
***********/
void inicia_onoff_controle( unsigned char n )
{
controle.onoff[ n ].on = 1;
onoff[ n ].estado = ON;
onoff[ n ].inicio = 1;
onoff[ n ].saida
= 0;
/*********************************************************************
***********\
* finaliza_onoff_controle
*
* Rotina de finalizao do algoritmo de ONOFF
*
*
*
* Parmetros: ndice do controlador ONOFF
*
* Retorno:
void
*
\*********************************************************************
***********/
inline void finaliza_onoff_controle( unsigned char n )
{
controle.onoff[ n ].on = 0;
onoff[ n ].estado = OFF;
}
/*********************************************************************
***********\
* algoritmo_onoff_controle
*
* Rotina de execuo do algoritmo de controle ONOFF
*
*
*
* Parmetros: ndice do controlador ONOFF, set-point e varivel de
controle (em*
110
ponto flutuante)
*
* Retorno:
esforo do controle, de 0 a 1000
*
\*********************************************************************
***********/
unsigned int algoritmo_onoff_controle( unsigned char n, float sp,
float pv )
{
int histerese;
if( onoff[ n ].estado == ON )
{
if( onoff[ n ].inicio )
{
onoff[ n ].inicio = 0;
onoff[ n ].saida = 0;
}
histerese = controle.onoff[ n ].histerese / 10;
if( controle.onoff[ n ].acao == ONOFF_ACAO_REVERSA )
{
if( pv >= sp )
{
onoff[ n ].saida = 0;
}
else
{
if( pv <= ( sp - histerese ) )
{
onoff[ n ].saida = 1000;
}
}
}
else
{
if( pv <= sp )
{
onoff[ n ].saida = 0;
}
else
{
if( pv >= ( sp + histerese ) )
{
onoff[ n ].saida = 1000;
}
}
}
return( onoff[ n ].saida );
}
return( 0 );
}
111
/*********************************************************************
*******************\
*
Mdulo Capture
*
*
*
*
*
\*********************************************************************
*******************/
#include "mod_capture.h"
definio de variveis e funes do mdulo
// Arquivo de
/*********************************************************************
*******************\
*
Flags do mdulo
*
\*********************************************************************
*******************/
union unsigned_char flags_capture;
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria de
programa
*
\*********************************************************************
*******************/
// - Globais ao mdulo:
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao mdulo:
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Funes estticas
*
\*********************************************************************
*******************/
112
/*********************************************************************
*******************\
*
Vetores de interrupo
*
\*********************************************************************
*******************/
void __ISR(_EXTERNAL_1_VECTOR, IPL7) INT1Interrupt( void )
{
if (INTCONbits.INT1EP == 1)
{
executa_sensoreamento_hall( 1 );
}
else
{
executa_sensoreamento_hall( 0 );
}
INTCONbits.INT1EP = ~INTCONbits.INT1EP;
IFS0bits.INT1IF = 0;
flag de interrupo Input Capture 1
}
// Limpa
113
* Retorno:
void
*
\*********************************************************************
*******************/
void inicializa_captures( void )
{
INTCON = 0x000E;
IPC1bits.INT1IP =
IPC2bits.INT2IP =
IPC3bits.INT3IP =
IFS0bits.INT1IF =
IFS0bits.INT2IF =
IFS0bits.INT3IF =
IEC0bits.INT1IE =
IEC0bits.INT2IE =
IEC0bits.INT3IE =
7;
7;
7;
0;
0;
0;
1;
1;
1;
114
/*********************************************************************
*******************\
*
Mdulo Timer
*
*
*
*
*
*
*
\*********************************************************************
*******************/
#include "mod_timer.h"
definio de variveis e funes do mdulo Timer
// Arquivo de
/*********************************************************************
*******************\
*
Flags do mdulo
*
\*********************************************************************
*******************/
volatile union unsigned_char flags_timer;
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria de
programa
*
\*********************************************************************
*******************/
// - Globais ao mdulo:
// - Globais ao sistema:
/*********************************************************************
*******************\
*
Definio de variveis do mdulo em memria
de dados
*
\*********************************************************************
*******************/
// - Globais ao mdulo:
unsigned char tempo_10ms;
base de tempo de 10ms
unsigned char tempo_50ms;
base de tempo de 50ms
unsigned char tempo_100ms;
base de tempo de 100ms
unsigned char tempo_500ms;
base de tempo de 500ms
unsigned char tempo_1000ms;
base de tempo de 1000ms
// Contador para
// Contador para
// Contador para
// Contador para
// Contador para
// - Globais ao sistema:
115
/*********************************************************************
*******************\
*
Timer2 Interrupt Service Routine - 1ms
*
*
*
* Descrio: Base de tempo de 1ms
*
* Prioridade: 2 (baixa)
*
\*********************************************************************
*******************/
void __ISR(_TIMER_2_VECTOR, IPL4) _T2Interrupt( void )
{
calcula_base_tempo();
// Gera as bases
de tempo
IFS0bits.T2IF = 0;
interrupo Timer2
}
// Limpa flag de
/*********************************************************************
*******************\
*
Timer2 Interrupt Service Routine - 1mS
*
*
*
* Descrio: Base de tempo de 1mS
*
* Prioridade: 7 ( mxima)
*
\*********************************************************************
*******************/
void __ISR(_TIMER_3_VECTOR, IPL6) _T3Interrupt( void )
{
IFS0bits.T3IF = 0;
// Limpa flag de
interrupo Timer2
atualiza_pwm();
tempo
}
// Gera as bases de
/*********************************************************************
*******************\
*
Timer2 Interrupt Service Routine - 1mS
*
*
*
* Descrio: Base de tempo de 1mS
*
* Prioridade: 7 ( mxima)
*
\*********************************************************************
*******************/
void __ISR(_TIMER_4_VECTOR, IPL4) _T4Interrupt( void )
{
static unsigned long contador_anterior;
116
LED2 = ~LED2;
IFS0bits.T4IF = 0;
interrupo Timer4
// Limpa flag de
if (contador_anterior == dados.contador_hall)
{
if ((dados.rpm_alvo != 0) || (dados.corrente_alvo != 0))
{
atualiza_rpm ( 0 );
}
}
contador_anterior = dados.contador_hall;
}
/*********************************************************************
*******************\
*
Implementao das funes
*
\*********************************************************************
*******************/
/*********************************************************************
*******************\
* inicializa_timer
*
* Rotina de inicializao do Timer2
*
*
*
* Parmetros: void
*
* Retorno
: void
*
\*********************************************************************
*******************/
inline void inicializa_timer( void )
{
flags_timer.value = 0;
// Zera flags do
mdulo Timer
tempo_10ms
base de tempo de
tempo_50ms
base de tempo de
tempo_100ms
base de tempo de
tempo_500ms
base de tempo de
tempo_1000ms
base de tempo de
= T_10MS;
10ms
= T_50MS;
50ms
= T_100MS;
100ms
= T_500MS;
500ms
= T_1000MS;
1000ms
// Inicializa
// Inicializa
// Inicializa
// Inicializa
// Inicializa
117
// Timer2 parado,
// Zera contador
PR2 = VALOR_TMR2;
do Timer2
IPC2bits.T2IP = 4;
prioridade: 6 (quase mxima)
IFS0bits.T2IF = 0;
interrupo do Timer2
IEC0bits.T2IE = 1;
interrupo Timer2
T2CONbits.TON = 1;
// Carrega perodo
// Nvel de
// Limpa flag de
// Habilita
// Liga Timer2
// 200kHz
// Timer parado,
// Zera contador
// Carrega perodo
// Nvel de
// Limpa flag de
// Habilita
// Liga Timer2
/*********************************************************************
*******************\
* calcula_base_tempo
*
* Rotina para clculo das bases de tempo do sistema
*
*
*
* Parmetros: void
*
* Retorno
: void
*
\*********************************************************************
*******************/
void calcula_base_tempo( void )
{
F_1MS = 1;
// Informa que
passou-se 1ms
118
trata_uart();
// Envio de
pacotes de dados pela serial e teste de timeouts de transmisso e
recepo
tempo_10ms--;
tempo da base de 10ms
if( !tempo_10ms )
Sim
{
F_10MS = 1;
passou-se 10ms
tempo_10ms = T_10MS;
// Decrementa
// Fim do tempo?
// Informa que
// Recarrega tempo
tempo_50ms--;
tempo da base de 50ms
if( !tempo_50ms )
Sim
{
F_50MS = 1;
passou-se 50ms
tempo_50ms = T_50MS;
// Decrementa
tempo_100ms--;
tempo da base de 100ms
if( !tempo_100ms )
Sim
{
F_100MS = 1;
passou-se 100ms
tempo_100ms = T_100MS;
// Decrementa
tempo_500ms--;
tempo da base de 500ms
if( !tempo_500ms )
Sim
{
F_500MS = 1;
passou-se 500ms
tempo_500ms = T_500MS;
// Decrementa
tempo_1000ms--;
tempo da base de 1000ms
if( !tempo_1000ms )
Sim
{
F_1000MS = 1;
passou-se 1000ms
tempo_1000ms = T_1000MS;
}
}
}
}
}
}
// Decrementa
// Fim do tempo?
// Informa que
// Recarrega tempo
119
// Fim do tempo?
// Informa que
// Recarrega tempo
// Fim do tempo?
// Informa que
// Recarrega tempo
// Fim do tempo?
// Informa que
// Recarrega tempo