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:
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
Módulo de Display
Módulo de Display 2
1 Comentários
Muito Bom o artigo. Gostei do bloga!!!
ResponderExcluir