QUE MOTOR É ESSE? – Laboratório de Motor de Passo

Que motor é esse? Você já se fez essa pergunta? Pois bem, hoje vamos tratar das características elétricas de um motor. Isso porque a robótica de sucata sempre tem uma dose de frustação e, minha intenção, portanto, é evitar esse sentimento montando um LABORATÓRIO DE MOTOR DE PASSO. Sendo assim, vamos fazer uma introdução à programação Multitask no ESP32, calcular valores de tensão e correntes, além de testar diversos tipos de motores de passo.

Recursos utilizados

- ESP WROOM 32

- Módulo de Display TFT LCD 1,44” RGB

- Driver DRV8825

- 2 Potenciômetros: 10k e 50k

- Capacitor Eletrolítico 220uF

- Motor de Passo


Montagem

Na montagem nós temos um display e um motor de Floppy funcionando, daqueles modelos mais antigos, bipolar, que tirei de um computador. Temos o ESP32 enviando sinal para o DRV8825, além dos potenciômetros que permitem controlar a velocidade e a corrente. Mostramos ainda um potenciômetro Step Down que regula a tensão que eu jogo em cima do driver.
Portanto, montei aqui uma espécie de laboratório, com o qual consigo identificar qual é o pulso em microssegundos que eu envio para o potenciômetro, entre outros parâmetros de um motor, como seus máximos e mínimos valores, incluindo a corrente, o RPM (rotações por minuto), a resistência . 
No vídeo, faço algumas demonstrações, inclusive com um motor de 4 fios, equivalente a um Nema 23. Confira:
 

Montagem do display

Ligações do Display

Esta tabela indica como você deve ligar o Display ao ESP32.

Montagem do DRV8825

Ligações do DRV8825

Esta tabela indica como você deve ligar o Driver ao ESP32.

Ligação dos potenciômetros

Nesta etapa, para melhorar a manipulação do controle de corrente do DRV8825, trocamos o potenciômetro de ajuste do driver por outro maior, porém de mesma resistência (10K ohms). Essa ação facilita bastante a manipulação, mas exige cuidado e delicadeza na montagem.

Como calibrar a entrada de dados

Para fazer a calibração dos dados coletados para calcular a tensão sobre o cursor do potenciômetro do driver DRV8825 usamos o Excel.
Primeiro coletamos os valores de AD da porta de entrada do ESP que variam de 0 a 4095.
Com um multímetro, medimos a tensão do cursor do potenciômetro do driver em cada momento.
Quem faz o papel do multímetro, neste caso, é o ESP32, cuja entrada AD é de 12 bit e pega tensão de 3v3. Como já mencionado, a referência vai de 0 a 4095. Isso porque é de 12 bit. Se fosse de 10 bit, como o Arduino Uno, ele seria de 0 a 1024, ou seja, quatro vezes menos resolução. Portanto, o fato do ESP ter quatro vezes mais resolução é importante para nossa aplicação.
Pegamos a tensão em milivolts do potenciômetro do 8825 e vou variando e analisando qual a leitura equivalente ao valor do AD. Essa medição, no caso, eu faço com o multímetro, para ver o valor real. Isso porque a entrada AD do ESP consome energia, então, ela dá uma pequena diferença na leitura. Faço, portanto, uma compensação com Excel.
Na planilha do Excel, conforme a figura abaixo, preencha os valores coletados na tabela acima e crie um gráfico de dispersão de pontos.

Clique com o botão direito em qualquer ponto do gráfico e depois em “Adicionar Linha de Tendência”.

Depois selecione “Linear”, “Exibir Equação no gráfico” e “Exibir valor de R – quadrado no gráfico”.

O Excel, então, exibe uma equação de primeiro grau que corrige o problema da dispersão dos pontos e encontra uma média. Ou seja, depois que eu li o valor AD do potenciômetro, depois que eu girei o botão, a equação vai confirmar o que fazer com o motor.

Aqui, o Excel gera a equação linear, que será usada no código. O valor de 0,9944 é o desvio padrão, ou seja, quanto mais perto de 1, mais confiança tenho que os dados estão corretos.

Código

Nós programamos dois Core. Nosso diagrama é formado de Declarações Globais, Funções Globais, Configurações e, então, partimos para o Core 0 e o Core 1, cada um com uma Task e um Loop.


Declarações Globais

Aqui tenho algumas variáveis.

#include <adafruit_gfx .h>     // Biblioteca gráfica principal
#include <xtronical_st7735 .h> // Biblioteca específica do display
#include <spi .h>              // Biblioteca de comunicação SPI

// Configura os pinos que serão usados para a comunicação com o display
#define TFT_DC 2        // Seleção do registro
#define TFT_RST 4       // Pino de redefinição da tela
#define TFT_CS 5        // ativação do Display, se não ativado, não comunicará no barramento SPI


// Inicia a rotina de conversa com o display com os pinos configurados 
// Como não colocamos o TFT_SCLK e o TFT_MOSI, a rotina presume que estamos usando o barramento SPI
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);  

//Instancia as Tasks
TaskHandle_t Task1, Task2;

//Constantes e variáveis -----------------------------------------------------------------

const int RST = 25;              // Porta digital D25 - Reset do DRV8825
const int SLP = 26;              // Porta digital D26 - Dormir (Sleep) DRV8825
const int ENA = 34;              // Porta digital D34 - Ativa (enable) DRV8825
const int M0 = 35;               // Porta digital D35 - M0 do DRV8825
const int M1 = 32;               // Porta digital D32 - M1 do DRV8825
const int M2 = 33;               // Porta digital D33 - M2 do DRV8825
const int DIR = 14;              // Porta digital D14 - Direção (direction) do DRV8825
const int STP = 27;              // Porta digital D27 - Passo (Step) do DRV8825
const int POTD = 13;             // AD do potenciometro do driver
const int POTV = 12;             // AD do potenciometro de velocidade do motor

int MeioPeriodo;                 // Meio periodo do pulso em microsegundos 
float MMP;                       // Multiplicador de micropasso
int PPR = 200;                   // Número de passos por volta
int Pulsos;                      // Pulsos para o driver do motor
int Voltas;                      // voltas do motor
float RPM;                       // Rotacao por minuto
int leituraAd;                   // Valor da leitura do potenciômetro do driver
float tensaoPot;                 // Valor da tensão na saída do potenciômetro do driver
float correnteMot;               // Valor da corrente configurada no driver

Funções Globais

Aqui demonstro como imprimir no display. Portanto, o tempo todo, vamos observar a tensão em milivolts, a corrente em Ampere, o RPM do motor, o valor AD e o pulso.

// Funções ---------------------------------------------------------------------------------

// Imprime os valores das variáveis no Display
void Imprime(){
  
  // Cria um retângulo preto em cima dos dados impressos para apagá-los
  tft.fillRect(24, 0, 48, 16, ST7735_BLACK);
  // Posiciona o cursor na posição
  tft.setCursor(24,0);
  // Imprime os dados na posição do cursor
  tft.print(int(tensaoPot));
  
  tft.fillRect(24, 20, 48, 16, ST7735_BLACK);
  tft.setCursor(24,20);
  tft.print(correnteMot);
  
  tft.fillRect(48, 40, 80, 16, ST7735_BLACK);
  tft.setCursor(48,40);
  tft.print(int(RPM));

  tft.fillRect(36, 60, 48, 16, ST7735_BLACK);
  tft.setCursor(36,60);
  tft.print(analogRead(POTD));

  tft.fillRect(0, 100, 48, 16, ST7735_BLACK);
  tft.setCursor(0,100);
  tft.print(MeioPeriodo);
 
}

// Calcula a corrente máxima suportada pelo driver
//Os dados dessa equação foram tiradas do datasheet do DRV8825
float calculoCorrente(float tensao) {
  return (tensao / 1000) / (5 * 0.1);   // 0.1: valor do resistor do driver 
}

//Calcula o RPM do motor
float calculoRPM() {
  //TPV: tempo por volta(segundos), PPR: passo por revolucao, MMP: multiplicador de micro passo
  float TPV = (PPR * MMP * (MeioPeriodo * 2)) / 1000000;
  //converte o TPV em RPM      
  return ((1.0 / TPV) * 60.0);                                
}


Configurações

Aqui tenho o Setup, onde exponho o pinMode do display e os digitalWrite.

void setup() {

  //Inicia a comunicação serial
  Serial.begin(115200);
  
  // Configura as portas como saída
  pinMode(RST, OUTPUT);       
  pinMode(SLP, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(M0, OUTPUT);
  pinMode(M1, OUTPUT);
  pinMode(M2, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(STP, OUTPUT);
  // Configura as portas como entrada
  pinMode(POTD, INPUT);     
  pinMode(POTV, INPUT);

  //Configuração do driver----------------------------------------------------------------

  // MMP: Multiplicador de micro passo:
  // 1- passo inteiro
  // 2- meio passo
  // 4- 1/4 de passo
  // 8- 1/8 de passo
  // 16 - 1/16 de passo
  // 32 - 1/32 de passo
  MMP = 1;

  // Configura as portas do driver para passo inteiro                  
  digitalWrite(M0, LOW);
  digitalWrite(M1, LOW);
  digitalWrite(M2, LOW);
  // Desativa o modo sleep
  digitalWrite(SLP, HIGH);
  // Desativa o modo reset
  digitalWrite(RST, HIGH);
  // Ativa as saídas do driver
  digitalWrite(ENA, LOW);
  // Define a direção do motor
  digitalWrite(DIR, HIGH);


Temos ainda as funções para imprimir na tela, como todas as especificidades.

//Configuração do Display ---------------------------------------------------------------------

  // Inicializa o Display
  tft.init();  

  delay(100);

  // Gira a tela em 180 graus
  tft.setRotation(2);
  // Define o tamanho do texto
  tft.setTextSize(2);
  // Define a cor do texto
  tft.setTextColor(ST7735_WHITE);
  // Define a quebra de linha do texto
  tft.setTextWrap(false);
  // Pinta a tela de preto
  tft.fillScreen(ST7735_BLACK);

  delay(500);
  
  // Imprime as informações estáticas na tela
  tft.setCursor(0,0);
  tft.print("T:");
  tft.setCursor(72,0);
  tft.print("mv");

  tft.setCursor(0,20);
  tft.print("C:");
  tft.setCursor(72,20);
  tft.print("A");
  
  tft.setCursor(0,40);
  tft.print("RPM:");

  tft.setCursor(0,60);
  tft.print("AD:");

  tft.setCursor(48,100);
  // 229 é o código da letra "µ" na tabela ASCII
  tft.print((char)229);
  tft.print("s");

  delay(500);

Aqui começamos a programação multicore. Você tem uma função TaskCreatePinnedToCore e os nomes da função é são codeForTask1 e codeForTask2, que é um ponteiro para função. Você ainda vê a quantidade de memória, ou seja, o tamanho da pilha da Task que deve ser 2000 em ambos.

// Configuração das tasks
  xTaskCreatePinnedToCore(
    codeForTask1,       // Função Task
    "led1Task",         // Nome da Task
    2000,               // Tamanho da pilha da Task 
    NULL,               // Parâmetro da Task
    1,                  // Prioridade da Task
    &Task1,             // Identificação da Task para acompanhar a Task criada
    0);                 // Core usado

  //Delay necessário para iniciar a task 1
  delay(500);

  xTaskCreatePinnedToCore(
    codeForTask2,
    "led2Task",
    2000,
    NULL,
    1,
    &Task2,
    1);

    delay(500);
}// Fim do setup

Task1

No codeForTask1, ele faz um analogReaddo POTV, que é do potenciômetro que lê o valor da velocidade. Então, eu pego o valor da velocidade e calculo o MeioPeriodo, ou seja, divido por dois. No analogRead POTD calculamos a tensão do driver. Partimos para tensaoPot, pegamos a leituraAD e faço a correção matemática da curva com a equação de primeiro grau apontada pelo Excel. Depois de corrigir o valor que poderia estar errado, calculamos o valor da corrente o motor e do RPM. Imprimimos os dados e configuramos um delay.

// Task 1 ---------------------------------------------------------------------------------
void codeForTask1( void * parameter )
{
  for (;;) {

    // Lê o valor do potenciômetro de velocidade
    MeioPeriodo = (analogRead(POTV)) / 2;
    // Lê o valor do potenciômetro do driver
    leituraAd = analogRead(POTD);
    // Calcula a tensão da saída do potenciômetro do driver 
    tensaoPot = 0.7492*leituraAd + 185.92;
    //Calcula a corrente máxima suportada pelo driver
    correnteMot = calculoCorrente(tensaoPot);
    //Calcula o RPM do motor
    RPM = calculoRPM();
    //Imprime as informações no display
    Imprime();

    delay(100);
    
  }
}

Task2

No codeForTask2, fazemos um digitalWrite LOW e depois um digitalWrite HIGH de MeioPeriodo, formando uma onda completa, com período em alta e também em baixa, ou seja, o ciclo completo do passo.

// Task 2 ---------------------------------------------------------------------------------
void codeForTask2( void * parameter )
{
  for (;;) {
    //Aqui é gerado o pulso do motor
    digitalWrite(STP, LOW);                   // Pulso nível baixo
    delayMicroseconds(MeioPeriodo);           // MeioPeriodo de X microsegundos
    digitalWrite(STP, HIGH);                  // Pulso nível alto
    delayMicroseconds (MeioPeriodo);          // MeioPeriodo de X microsegundos
  }
}

 Aqui temos uma observação: quando você tem uma programação dualcore, o Loop não faz nada, pois quem faz tudo é o CodeForTask. Então, para o Loop, determinamos um delay.

Observação

// A função void loop() não será usada pelo programa
// Porém é necessária para funcionar corretamente
void loop() {
  
  delay(100);

}

Medindo a indutância dos motores de passo

Para medir a indutância, você precisa de um medidor de LCR. Mesmo as bobinas sendo iguais, por conta da posição do motor, as medidas em mH podem ser diferentes. A leitura correta é a de menor valor.

Por que ocorre diferença entre as bobinas?

Devido ao alinhamento dessas bobinas com o imã do eixo, as medidas podem sofrer alterações, pois o imã pode incidir no campo magnético das bobinas.
Repare que a bobina A está alinhada ao um conjunto de imãs do eixo, portanto, o valor medido maior que das outras bobinas medidas.
Quando as bobinas não estão alinhadas a um conjunto de imãs do eixo, o valor medido é o valor real da indutância do motor, portanto o menor valor medido.

Medindo Motores de Passo – Nema 17

Quando falamos em motor de passo, é interessante saber a resistência DC, indutância e corrente máxima.

Teste prático


Aqui temos o teste prático que foi exibido no vídeo mais para conhecimento da montagem. Mas, aconselho que você não monte no protoboard, mas, sim, na placa padrão, aquela furadinha, de forma soldada, pois essa montagem vai ser uma ferramenta que vai te ajudar com qualquer motor.

Medindo Motores de Passo – Motor grande de impressora


Teste prático


Medindo Motores de Passo – Motor de Driver de DVD


Teste prático



Faça o download dos arquivos:


Respondendo perguntas sobre onde comprei alguns recursos, aqui estão alguns links:
Módulo de Display
Módulo de Display 2



Nenhum comentário:

Tecnologia do Blogger.