Programa de exemplo do Robô TON-BOT no modo seguidor de parede.
Dependencies: IOTON-API QEI USBDevice mbed-ton ton-bot
Fork of ton-bot_seguidor_linha by
Diff: controlador.cpp
- Revision:
- 4:f3c97c053b9f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/controlador.cpp Wed Jul 05 21:13:56 2017 +0000 @@ -0,0 +1,309 @@ +/** +****************************************************************************** +* @file controlador.cpp +* @author Kleber Lima da Silva (kleber@ioton.cc) +* @version V0.0.1 +* @date 05-Julho-2017 +* @brief Biblioteca para controle de velocidade usando os encoders. +****************************************************************************** +* @attention +* +* COPYRIGHT(c) 2017 IOTON Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +****************************************************************************** +*/ + +#include "controlador.h" + + +/******************************************************************************/ +/** @addtogroup Biblioteca do controlador de velocidade (perfil retangular) +* @{ +*/ + +/* Variáveis Externas --------------------------------------------------------*/ +int32_t distancia_mm = 0; +int32_t distancia_deg = 0; + + +/* Variáveis Privadas --------------------------------------------------------*/ +int8_t tipo_movimento = 0; +int32_t setpoint_dist = 0; +int32_t setpoint_speed_esquerda_cnt = 0, setpoint_speed_direita_cnt = 0; +int32_t encoder_esquerda_delta = 0, encoder_direita_delta = 0; +int32_t encoder_esquerda_anterior_cnt = 0, encoder_direita_anterior_cnt = 0; +int32_t pid_esquerda_out = 0, pid_direita_out = 0; +int32_t erro_esquerda_anterior = 0, erro_direita_anterior = 0; +bool bUsarSensores = false; +float frontal_esquerdo = 0, lateral_esquerdo = 0, lateral_direito = 0, frontal_direito = 0; + + +/******************************************************************************* +*Função principal do controle de velocidade ----------------------------------- +*/ +void controleVelocidade(void) +{ + getSensoresParede(&frontal_esquerdo, &lateral_esquerdo, &lateral_direito, &frontal_direito); + updateEncoders(); // Atualiza as distâncias e velocidades + controladorPID(); // Controlador de velocidade +} + + +/* Função para selecionar os parâmetros do movimento --------------------------- +* raio [mm]: 0 para movimento translacional ou raio para a curva +* dist_ou_angulo [mm ou deg]: distância(translational ou angular) do movimento +* speed [mm/s]: velocidade do movimento +*/ +void setMovimento(int32_t raio, int32_t dist_ou_angulo, int32_t speed) +{ + if (raio == 0) + { + tipo_movimento = TRANSLACIONAL; + + /* Usado para o controle de velocidade */ + setpoint_speed_esquerda_cnt = SPEED_TO_COUNTS(speed); + setpoint_speed_direita_cnt = setpoint_speed_esquerda_cnt; + } + else + { + tipo_movimento = ROTACIONAL; + + /* Calcula as velocidade a partir do raio */ + float speedX_mm_s = (float)speed; + float speedW_rad_s = speedX_mm_s / (float)raio; + + int32_t speedX_cnt = SPEED_TO_COUNTS(abs(speed)); + int32_t speedW_cnt = RAD_S_TO_COUNTS(speedW_rad_s); + + if (raio < RODA_RODA) + { + speedX_cnt -= (abs(speedW_cnt) / 2); + speedW_cnt /= 2; + } + + /* Usado para o controle de velocidade */ + setpoint_speed_esquerda_cnt = speedX_cnt - speedW_cnt; + setpoint_speed_direita_cnt = speedX_cnt + speedW_cnt; + } + + /* Usado para indicar o fim do movimento */ + setpoint_dist = dist_ou_angulo; +} + + +/* Atualiza a leitura dos encoders --------------------------------------------- +*/ +void updateEncoders(void) +{ + int32_t encoder_esquerda_cnt, encoder_direita_cnt; + + /* Atualiza a contagem dos encoders */ + encoder_esquerda_cnt = getEncoderEsquerda(); + encoder_direita_cnt = getEncoderDireita(); + + /* Atualiza a alteração dos encoders (speed) */ + encoder_esquerda_delta = encoder_esquerda_cnt - encoder_esquerda_anterior_cnt; + encoder_direita_delta = encoder_direita_cnt - encoder_direita_anterior_cnt; + + /* Guarda os valores anteriores */ + encoder_esquerda_anterior_cnt = encoder_esquerda_cnt; + encoder_direita_anterior_cnt = encoder_direita_cnt; + + /* Calcula a distância (mm) e o ângulo (deg) */ + distancia_mm = COUNTS_TO_MM((encoder_direita_cnt + encoder_esquerda_cnt) / 2); + distancia_deg = COUNTS_TO_DEG((encoder_direita_cnt - encoder_esquerda_cnt) / 2); +} + + +/* Controlador PID de velocidade dos motores ----------------------------------- +*/ +void controladorPID(void) +{ + int32_t erro_esquerda = 0, erro_direita = 0; + + /* Alinhamento através dos sensores */ + if (bUsarSensores == true) + { + int32_t sensor_feedback = (int32_t)getErroSensores() / K_SENSORES; + + erro_esquerda += sensor_feedback; + erro_direita -= sensor_feedback; + } + + /* Erro de velocidade */ + erro_esquerda += (setpoint_speed_esquerda_cnt - encoder_esquerda_delta); + erro_direita += (setpoint_speed_direita_cnt - encoder_direita_delta); + + /* PD - motor da esquerda */ + pid_esquerda_out += (KP * erro_esquerda) + + (KD * (erro_esquerda - erro_esquerda_anterior)); + + /* PD - motor da direita */ + pid_direita_out += (KP * erro_direita) + + (KD * (erro_direita - erro_direita_anterior)); + + /* Guarda os valores anteriores */ + erro_esquerda_anterior = erro_esquerda; + erro_direita_anterior = erro_direita; + + setMotores(pid_esquerda_out / 1000.0f, pid_direita_out / 1000.0f); +} + + +/* Indica o fim do movimento --------------------------------------------------- +*/ +bool isFinalMovimento(void) +{ + if (tipo_movimento == TRANSLACIONAL && distancia_mm >= setpoint_dist) + { + return true; + } + else if (tipo_movimento == ROTACIONAL && abs(distancia_deg) >= setpoint_dist) + { + return true; + } + else if ((tipo_movimento == TRANSLACIONAL) && (frontal_esquerdo > CENTRO_FRONTAL && frontal_direito > CENTRO_FRONTAL)) + { + return true; + } + + return false; +} + + +/* Reseta os encoders e as variáveis do controlador ---------------------------- +*/ +void resetControlador(void) +{ + resetEncoderEsquerda(); + resetEncoderDireita(); + + encoder_esquerda_anterior_cnt = 0; + encoder_direita_anterior_cnt = 0; + + distancia_mm = 0; + distancia_deg = 0; + + pid_esquerda_out = 0; pid_direita_out = 0; + erro_esquerda_anterior = 0; erro_direita_anterior = 0; + setpoint_speed_esquerda_cnt = 0; setpoint_speed_direita_cnt = 0; +} + + +/* Movimenta o micromouse para frente uma distância em [mm] -------------------- +* Se mm == 0: anda para frente até o próximo comando +*/ +void frente(int32_t mm) +{ + if (mm != 0) + { + bUsarSensores = true; + resetControlador(); + setMovimento(0, mm, SPEED_RETA); + + do + { + wait_ms(1); + } + while (isFinalMovimento() == false); + } + else + { + bUsarSensores = true; + setMovimento(0, mm, SPEED_RETA); + wait_ms(1); + } +} + + +/* Realiza uma curva em torno do próprio eixo (graus < 0: para direita) -------- +*/ +void curvaPivot(int16_t graus) +{ + bUsarSensores = false; + resetControlador(); + setMotores(0, 0); + wait_ms(100); + + /* Seleciona o movimento de acordo com o sentido da curva */ + if (graus > 0) setMovimento(RODA_RODA / 2, graus, SPEED_CURVA); + else setMovimento(RODA_RODA / 2, -graus, -SPEED_CURVA); + + do + { + wait_ms(1); + } + while (isFinalMovimento() == false); +} + + +/* Realiza uma curva em torno do próprio eixo e anda até a fronteira da célula +* (graus < 0: para direita) +*/ +void curva(int16_t graus) +{ + frente(CELULA / 2); + curvaPivot(graus); + frente(CELULA / 2); +} + +/* Retorna o erro de alinhamento dos sensores ---------------------------------- +*/ +int16_t getErroSensores(void) +{ + float erro = 0; + + /* ------ ALINHAMENTO LATERAL ------ */ + if (frontal_esquerdo < FRONTAL_TH && frontal_direito < FRONTAL_TH) + { +#if PID_TECNICA == 1 + if (lateral_esquerdo > CENTRO_LATERAL && lateral_direito < CENTRO_LATERAL) + { + erro = lateral_esquerdo - CENTRO_LATERAL; + } + else if (lateral_direito > CENTRO_LATERAL && lateral_esquerdo < CENTRO_LATERAL) + { + erro = CENTRO_LATERAL - lateral_direito; + } +#elif PID_TECNICA == 2 + if (lateral_esquerdo > LATERAL_TH && lateral_direito > LATERAL_TH) + { + erro = lateral_esquerdo - lateral_direito; + } + else if (lateral_esquerdo > LATERAL_TH) + { + erro = 2 * (lateral_esquerdo - CENTRO_LATERAL); + } + else if (lateral_direito > LATERAL_TH) + { + erro = 2 * (CENTRO_LATERAL - lateral_direito); + } +#endif + } + /* ------ ALINHAMENTO FRONTAL ------ */ + else if (frontal_esquerdo > ALINHAMENTO_FRONTAL && frontal_direito > ALINHAMENTO_FRONTAL) + { + erro = (frontal_direito - frontal_esquerdo); + } + + return ((int16_t)(erro * 4095));//return erro; +} + +/** +* @} +*/ + + +/************************ (C) COPYRIGHT IOTON Technology **********************/ +/***********************************END OF FILE********************************/