blog-eletrogate-logo-desktop blog-eletrogate-logo-mobile
  • Categorias
    • Voltar
    • INICIANTES
    • INTERMEDIÁRIOS
    • AVANÇADOS
    • divide
    • Automação Residencial
    • Componentes Eletrônicos
    • Impressão 3D
    • IoT
    • Modelagem 3D
    • Módulos Wifi
    • Por trás da tecnologia
    • Projetos
    • Raspberry Pi
    • Robótica
    • Sensores
    • Shields
    • Sistemas Operacionais
    • Tipos de Arduino
    • Tutoriais
  • Apostilas
  • Quem Somos
  • Seja um redator
  • Trabalhe Conosco
    • Categorias
      • Voltar
      • INICIANTES
      • INTERMEDIÁRIOS
      • AVANÇADOS
      • divide
      • Automação Residencial
      • Componentes Eletrônicos
      • Impressão 3D
      • IoT
      • Modelagem 3D
      • Módulos Wifi
      • Por trás da tecnologia
      • Projetos
      • Raspberry Pi
      • Robótica
      • Sensores
      • Shields
      • Sistemas Operacionais
      • Tipos de Arduino
      • Tutoriais
    • Apostilas
    • Quem Somos
    • Seja um redator
    • Trabalhe Conosco
Loja Eletrogate
voltar
  • Introdução
  • O Problema
  • A Biblioteca
  • Algoritmo com Proteção
  • Conclusão
  • Referências
  • Sobre o Autor
Robótica

Controle de Corrente em Servomotores

Eletrogate 12 de janeiro de 2023

Introdução

Servomotores como os SG90 não possuem proteção contra sobrecorrente ou sobrecorrente embutidas, podendo queimar se submetidos, por longos períodos, a altos esforços. Para evitar isso, foi desenvolvido um algoritmo que permite o ajuste do sinal enviado ao servo para manter a corrente abaixo de um valor estipulado. Aqui, esse é apresentado como a biblioteca ServoProtegido.h. Para as demonstrações e testes, serão utilizados:

  • 4 x Micro Servo 9g SG90 TowerPro
  • Uno R3 + Cabo Usb para Arduino
  • CI LM358
  • Fonte 5V 1A Bivolt
  • Protoboard 830 Pontos
  • Protoboard 400 Pontos
  • 4 x Potenciômetro Linear 200KΩ
  • Capacitor Eletrolítico 1000uF x 16V
  • Capacitor Eletrolítico 1uF x 50V
  • Resistor 4K7 1/4W (10 Unidades) (*obs I)
  • Resistor 2K7 1/4W (10 Unidades) (*obs I)
  • Resistor 1K 1/4W (10 Unidades) (*obs I)
  • Resistor 22K 1/4W (10 Unidades) (*obs I)
  • 2 x Resistor 0R10 5% 5W (1 unidade)
  • Jumpers – Macho/Macho – 20 Unidades de 20cm
  • Jumpers – Macho/Macho – 40 Unidades de 10cm
  • Kit com 140 Jumpers Rígidos em U para Protoboard
  • Conector Adaptador Plug P4 Femea com Borne KRE

Estes estarão conectados conforme o esquemático abaixo.

Diagrama do sistema montado para demonstrações.

ATENÇÃO: ESTE CIRCUITO NÃO DEVE SER ENERGIZADO SE O CÓDIGO CARREGADO NA PLACA UNO REALIZAR LEITURAS ANALÓGICAS SEM QUE A FUNÇÃO analogReference(EXTERNAL) TENHA SIDO EXECUTADA.

Quando montado em uma protoboard, todos os jumpers de alimentação, incluindo os dos servos, devem estar trançados em pares (cada positivo trançado com seu negativo). Estes devem ser mantidos distantes dos jumpers de sinais. Os resistores de potência devem estar distantes um do outro e do ampop. A fonte utilizada para alimentar os servos deve ser distinta da utilizada para alimentar a Uno.

Obs. I: Os resistores devem ser escolhidos para atender, simultaneamente:

  • A distorção no sinal de saída do Amp-Op esteja dentro da faixa aceitável;
  • Seja Imax a maior corrente que pode vir a circular pelo servo (não a estimada no código, mas a corrente máxima do servo), Rp a resistência do resistor de potência (neste caso, 0.1 ohm), Vcc a tensão de alimentação do circuito de sinais e R1, R2, R3 e R4 destacados no diagrama:

O Problema

O código abaixo não utiliza a biblioteca, somente monitora os sensores.

#include <Servo.h>

Servo servo1, servo2, servo3, servo4;               //declara os objetos referentes aos servos que serão controlados
Servo servos[] = {servo1, servo2, servo3, servo4};  //inicializa um vetor com estes objetos

int filtro(int sensor)  {
  static const uint8_t tamFiltro = 128;                       //define o tamanho do vetor de amostras para cada entrada
  static const uint8_t entradas[] = {A0, A1, A2, A3, A4, A5}; //inicializa o vetor de entradas analogicas
  static unsigned medicoes[sizeof(entradas)][tamFiltro];      //declara a matriz com os vetores de amostra
  unsigned long soma = 0;                                     //inicia soma com 0
  static uint8_t i;                                           //declara o iterador
  for(i = 0; i < tamFiltro - 1; medicoes[sensor][i] = medicoes[sensor][i + 1], i ++)  //de 0 a tamFiltro - 2, deslocando cada valor para o endereço anterior a cada iteração, iterar de 1 em 1
    soma += medicoes[sensor][i];                                                      //a cada iteração, acumular o valor do respectivo endereço
  soma += (medicoes[sensor][tamFiltro - 1] = analogRead(entradas[sensor]));           //substituir o ultimo valor pela leitura do sensor e acumular esta
  return soma / tamFiltro;                                                            //retornar o valor acumulado divido pelo tamanho do vetor de amostras
}

void setup()  {
  analogReference(EXTERNAL);            //seleciona a tensão no pino AREF como referência para as leituras 
  Serial.begin(115200);                 //inicia a interface UART
  const int saidas[] = {11, 10, 9, 6};  //inicializa o vetor com os pinos referentes às saídas de sinal para os servos
  for(uint8_t i = 0; i < 4; i ++)       //de 0 a 3, incrementando 1 a 1
    (servos[i]).attach(saidas[i]);      //conectar cada saída ao respectivo servo
}

void loop() {
  static uint8_t q;                 //declara o iterador
  static unsigned valorFiltrado[6]; //declara o vetor com as leituras filtradas
  for(q = 0; q < 4; q ++) {                                 //de 0 a 3, incrementando 1 a 1
    valorFiltrado[q] = map(filtro(q), 0, 1023, 500, 2500);  //armazena, em cada posição do vetor, a leitura filtrada e mapeada para a faixa da respectiva saída
    (servos[q]).writeMicroseconds(valorFiltrado[q]);        //define o sinal enviado para o respectivo servo
  }

  static unsigned long tempo;   //declara a variavel auxiliar para o controle das mensagens
  valorFiltrado[4] = filtro(4); //armazena cada leitura
  valorFiltrado[5] = filtro(5); //em uma posição do vetor
  if(millis() - tempo > 100) {  //a cada 100 milisegundos
    Serial.print(",usBase/2:"); Serial.println(valorFiltrado[0]/2);  //registra o sinal enviado para os servos
    Serial.print(",usGarra/2:"); Serial.println(valorFiltrado[3]/2); //divido por 2, para melhor visualização
    Serial.print(",sensorBase:"); Serial.println(valorFiltrado[4]);  //registra o valor lido
    Serial.print(",sensorGarra:"); Serial.println(valorFiltrado[5]); //pelos respectivos sensores
    tempo = millis(); //atualiza a variavel auxiliar
  }
}

Executando-o, tem-se o resultado visto no vídeo abaixo. Como não há ajustes automáticos em prol da redução da corrente consumida, se o operador mantiver os potenciômetros em posições que forcem os servos, a corrente de cada um é mantida em valores que podem o danificar rapidamente.

https://blog.eletrogate.com/wp-content/uploads/2023/01/SemControle-Final.mp4

A Biblioteca

As classes e estruturas de ServoProtegido, assim como o uso interface de seus métodos, são explicados abaixo. Seus arquivos podem ser baixados de nosso repositório.

A classe EntradaAnalogica, como o nome sugere, visa abstrair as entradas analógicas do micro. Seus métodos são:

  • EntradaAnalogica(const uint8_t pino): declara um objeto correspondente à entrada pino e com tamanho padrão para o filtro;
  • EntradaAnalogica(const uint8_t pino, const uint8_t _tamFiltro): declara um objeto correspondente à entrada pino e com tamanho _tamFiltro para o filtro;
  • ~EntradaAnalogica(): libera o espaço alocado para o filtro;
  • void setPino(const uint8_t pino): altera a entrada pela qual as leituras são feitas;
  • uint8_t getPino(): informa a entrada pela qual as leituras são feitas;
  • unsigned medeComFiltro(): realiza uma leitura e retorna a média das últimas _tamFiltro leituras.

A classe ServoProtegido herda todos os membros da Servo e acrescenta a camada de proteção. Seus métodos são:

  • ServoProtegido(const uint8_t pinoSensor): declara um objeto que abstrai a proteção contra sobrecorrente de um servo e define que a leitura da corrente deste servo será feita pelo pinoSensor;
  • ~ServoProtegido(): libera o espaço alocado para a EntradaAnalogica referente à leitura do sensor deste servo;
  • void setLimiteSaida(const bool extremo, const unsigned novoLimite): se extremo for ServoProtegido::inferior, novoLimite passa a ser o menor valor que o sinal gerado automaticamente pode assumir. Se for ServoProtegido::superior, novoLimite passa a ser o maior valor que o sinal gerado automaticamente pode assumir;
  • unsigned getLimiteSaida(const bool extremo): informa o valor limite definido para o extremo extremo da saída;
  • void setSensorMax(const unsigned novoMax): define o valor a partir do qual as leituras do sensor levam ao controle automático do sinal de saída;
  • unsigned getSensorMax(): informa o valor a partir do qual as leituras do sensor levam ao controle automático do sinal de saída;
  • void setMargemEntradas(const uint8_t novaMargem): novaMargem é utilizado como referência em duas computações, principalmente:
    • o controle automático do sinal de saída tenta reduzir a leitura do sensor a sensorMax - novaMargem;
    • o controle da saída volta a ser manual somente quando a diferença entre o valor automático e o manual for maior do que novaMargem na oposta à que aumenta o sinal do sensor;
  • uint8_t getMargemEntradas(): informa o valor definido para a margem das entradas;
  • void setPasso(const uint8_t novoPasso): define o valor base para a variação do sinal de saída automático a cada computação do controle. Quanto maior, mais rápido o ajuste é feito, mas maior a probabilidade da posição do servo ser alterada mais do que deveria;
  • uint8_t getPasso(): informa o valor base para a variação do sinal de saída automático a cada computação do controle;
  • void setIntervaloControle(const unsigned novoIntervalo): define o período mínimo entre as computações referentes ao controle do servo;
  • unsigned getIntervaloControle(): informa o período mínimo entre as computações referentes ao controle do servo;
  • struct DetalhesExecucao controlaServo(const unsigned usManual): processa, primeiro, o sinal lido pelo sensor da corrente do servo. A depender do valor desta, processa usManual e envia este ou o valor automático para o servo. Retorna uma struct que contém as principais informações pertinentes ao controle:
    • unsigned ultimaLeitura: a leitura feita pelo sensor de corrente nesta computação;
    • uint8_t usUsado: qual sinal foi escolhido pelo controle, DetalhesExecucao::manual ou DetalhesExecucao::automatico;
    • unsigned valorUs: o valor do sinal escolhido;

Algoritmo com Proteção

Este código utiliza os principais recursos desta biblioteca.

#include <ServoProtegido.h>

Servo servoBraco, servoAntebraco;             //declara os objetos referentes aos servos sem proteção
ServoProtegido servoGarra(A5), servoBase(A4); //declara os objetos referentes aos servos protegidos

void setup()  {
  analogReference(EXTERNAL);  //seleciona a tensão no pino AREF como referência para as leituras
  Serial.begin(115200);       //inicia a interface UART
  servoBraco.attach(10);      //conecta cada
  servoAntebraco.attach(9);   //servo à
  servoGarra.attach(6);       //respectiva
  servoBase.attach(11);       //saída
}

void loop() {
  static EntradaAnalogica potenciometro0(A0), potenciometro1(A1),   //declara os objetos referentes
                            potenciometro2(A2), potenciometro3(A3); //às entradas analógicas
  static struct DetalhesExecucao detalhes[2];                       //declara as estruturas referentes aos resultados do controle dos servos
  servoBraco.writeMicroseconds(494 + potenciometro0.medeComFiltro());           //envia, para o servo, a leitura do
  servoAntebraco.writeMicroseconds(988 + potenciometro1.medeComFiltro());       //potenciometro somada a um valor de compensação
  detalhes[0] = servoGarra.controlaServo(988 + potenciometro2.medeComFiltro()); //passa o sinal que seria enviado pela função de controle, que avalia
  detalhes[1] = servoBase.controlaServo(988 + potenciometro3.medeComFiltro());  //a possibilidade de o enviar ao servo e registra os resultados do processo

  static unsigned long tempo; //declara a variavel auxiliar para o controle das mensagens
  if(millis() - tempo > 100) {
    Serial.print(",usGarra/2:"); Serial.println(detalhes[0].valorUs/2);       //escreve o sinal enviado para os servos
    Serial.print(",usBase/2:"); Serial.println(detalhes[1].valorUs/2);        //divido por 2, para melhor visualização
    Serial.print(",sensorGarra:"); Serial.println(detalhes[0].ultimaLeitura); //escreve o valor lido
    Serial.print(",sensorBase:"); Serial.println(detalhes[1].ultimaLeitura);  //pelos respectivos sensores
    tempo = millis(); //atualiza a variavel auxiliar
  }
}

Executando-o, tem-se o resultado visto no vídeo abaixo. A leitura escolhida como máxima do sensor ainda leva a algum aquecimento, mas muito menor.

https://blog.eletrogate.com/wp-content/uploads/2023/01/videoControle.mp4

Conclusão

A biblioteca explorada neste post implementa o básico do controle proposto. Há possibilidade de muita melhoria, tanto em performance, quanto em legibilidade, o que é incentivado. Além disso, há outros recursos de segurança que podem ser implementados, como a proteção contra sobreaquecimento com base em um sensor de temperatura.


Referências

  • https://blog.eletrogate.com/amperimetro-pratico-com-lcd/;

Créditos à Lorena pela edição dos vídeos. Obrigado, Lorena!


Sobre o Autor


Eduardo Henrique
LinkedIn

Formado técnico em mecatrônica no CEFET-MG, atualmente estuda Engenharia de Controle e Automação na UFMG. É apaixonado por eletrônica, controle, arte e, principalmente, por sua companheira, Beatriz.


Eletrogate

12 de janeiro de 2023

A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.

Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!

Componentes Eletronicos

Conceitos Básicos sobre Solda Eletrônica

Eletrogate26 de janeiro de 2023

Este post aborda os tipos de ferro de solda, tipos de solda, acessórios para o processo e procedimentos para manutenção do ferro de solda.

Componentes Eletronicos

Conceitos Básicos sobre Solda Eletrônica

Eletrogate26 de janeiro de 2023

Este post aborda os tipos de ferro de solda, tipos de solda, acessórios para o processo e procedimentos para manutenção do ferro de solda.

Sensores

MPU6050 com BluePill e STM32CubeIDE

Eletrogate19 de janeiro de 2023

Neste post, veremos como medir aceleração e velocidade angular utilizando o MPU6050 junto de uma BluePill programada pelo STM32CubeIDE.

Sensores

MPU6050 com BluePill e STM32CubeIDE

Eletrogate19 de janeiro de 2023

Neste post, veremos como medir aceleração e velocidade angular utilizando o MPU6050 junto de uma BluePill programada pelo STM32CubeIDE.

Robótica

Controle de Corrente em Servomotores

Eletrogate12 de janeiro de 2023

Este post trata acerca de um simples sistema que visa ajustar o período do pulso de controle de um servomotor evitando que este permaneça em um estado de alto consumo de corrente.

Robótica

Controle de Corrente em Servomotores

Eletrogate12 de janeiro de 2023

Este post trata acerca de um simples sistema que visa ajustar o período do pulso de controle de um servomotor evitando que este permaneça em um estado de alto consumo de corrente.

Tipos de Arduino

BluePill com STM32CubeIDE

Eletrogate6 de janeiro de 2023 Atualizado em: 09 jan 2023

Neste post, desenvolveremos, utilizando recursos do STM32CubeIDE, um simples piscaLED para a placa BluePill.

Tipos de Arduino

BluePill com STM32CubeIDE

Eletrogate6 de janeiro de 2023 Atualizado em: 09 jan 2023

Neste post, desenvolveremos, utilizando recursos do STM32CubeIDE, um simples piscaLED para a placa BluePill.

Eletrogate Robô

Cadastre-se e fique por
dentro de novidades!

blog-eletrogate-logo-footer

Rua Rio de Janeiro, 441 - Sala 1301
Centro - Belo Horizonte/MG
CEP 30160-041
*Não temos atendimento físico

ANWAR SLEIMAN HACHOUCHE - ME
CNPJ: 18.917.521/0001-73

Atendimento

(31) 3142-3800

contato@eletrogate.com


Seg a Sex - das 8h às 17h

Institucional

  • Apostilas
  • Quem Somos
  • Privacidade
  • Seja um Redator
  • Trabalhe Conosco

Nos acompanhe

Facebook Instagram Youtube

© ELETROGATE 2023 - Todos os direitos reservados. Termos de uso e Política de privacidade.