Introduction: Powerful 12V Motor With Inductive Encoder and ESP32

About: Do you like technology? Follow my channel on Youtube and my Blog. In them I put videos every week of microcontrollers, arduinos, networks, among other subjects.

Today we’ll do another DC motor video, using the one in the car fan. I’m using this specific one because I consider it to be potent. It has 12V for about 3 ampere and costs well under a hundred dollars. So in this video, we’ll evaluate the behavior of this automotive cooling fan motor in an automated way and draw a curve with the operating profile of this motor for this example using ESP32 LoRa.

Step 1: Demonstration

Step 2: Resources Used

· One ESP32 WiFi LoRa

· Four IRF1404s

· Three BC337s

· One CD4011

· Resistors

· Two 1uF electrolytic capacitors

· Two 1N4148 diodes

· USB cable for ESP

· 12V source for the load used

· Fan Motor

· Protoboard

· Wires

· Inductive proximity sensor

· 10komhs Pot

· Plastic disc (attached to shaft)

· Aluminum Adhesive Tape (or other metal for detection)

Step 3: Scheme

This is the scheme used in this example. It is the same as shown in the H-bridge video with MOSFET.

Step 4: Scheme - Detection

For detection, we will use an inductive proximity sensor.

Its operation principal is based on the change of the magnetic field (created by its own sensor) due to the proximity of a material capable of altering the magnetic flux enough to sensitize the sensor.

For the model used (the LJ8A3-2-Z / BX), we have:

It can be powered by a voltage of 6V to 36V.

• The detection distance is 2mm (+ -10%).

• Normal NPN output open (NO).

• Calibrated for detection of iron.

Although it’s calibrated for use with iron, we can apply it using other materials. But this should interfere with their detection capabilities. In the case of this example, we used an aluminum tape (fastened to one side of the disc) that adequately met the needs.

Step 5: Procedure

We’ll write a code that allows us to get the RPM value for several PWM values.

This time, instead of using the digital tachometer, we will use an inductive proximity sensor. We will use its digital output to detect the passage of a piece of aluminum tape attached to the plastic disk attached to the shaft.

The sensor output will be connected to one of the GPIOs of the ESP, configured as digital input. The period of 100 detections (100 revolutions) will be measured, from where we will obtain the average period of a rotation.

Knowing the average period of a rotation, we can easily determine the frequency of rotation, remembering what is showed in the image.

Step 6: Precautions

When working with the bridge, always be very careful:

· If the motor power supply does not have over-current protection, provide at least one fuse in case of an accident or failure. This prevents any damage to the source.

· Whenever possible, keep the logic part of the circuit in a source separate from the motor source to minimize possible unwanted effects caused by the motor crash.

· Although the IRF1404 can sustain high currents, keep the devices cool through coolers or heatsinks (or both). This will increase the life of the component and prevent adverse effects caused by the temperature variation of the component.

· MOSFET devices are very sensitive to electrostatic discharge. Whenever you handle them, take the proper precautions, such as using antistatic wrist straps.

Step 7: Source Code

#Includes and #Defines

//Bibliotecas para utilização do display OLED
#include <Wire.h> // Necessário apenas para o Arduino 1.6.5 e posterior #include "SSD1306.h" // o mesmo que #include "SSD1306Wire.h" //Os pinos do OLED estão conectados ao ESP32 pelos seguintes GPIO's: //OLED_SDA -- GPIO4 //OLED_SCL -- GPIO15 //OLED_RST -- GPIO16 #define SDA 4 #define SCL 15 #define RST 16 //RST pode ser ajustado por software

Objects, Constants, and Variables

SSD1306 display(0x3c, SDA, SCL, RST); //Instanciando e ajustando os pinos do objeto "display"
//PWM usado como oscilador do dobrador de tensão const int freq_osc = 1000; //Frequencia do PWM const int canal_osc = 0; // canal do PWM oscilador const int pin_osc = 21; //GPIO utilizada para o oscilador const int ciclo = 2048; //ciclo de trabalho de 50% //PWM usado para controle de velocidade const int freq_vel = 50; //Frequencia do PWM do controle de velocidade const int canal_vel = 1; // canal do PWM controle de velocidade const int pin_EN = 17; //Habilita ou desabilita a ponte (controla a velocidade) const int pin_DIR = 2; //Controla direção //Pino de leitura do sensor const int pin_Leitura = 22; //Captura detecção //Resolução dos PWM's const int resolucao = 12; // Resolução (4096 estados) //Constante que determinar o valor mínimo para o PWM const int min_vel = 800; // Variável usada para alternar a direção boolean dir = false; // variável para armazenar a velocidade atual int velocidade = 0;


void setup()
{ Serial.begin(115200); //para debug //seta a direção dos GPIO pinMode(pin_osc, OUTPUT); pinMode(pin_DIR, OUTPUT); pinMode(pin_EN, OUTPUT); pinMode(pin_Leitura, INPUT); // Ajusta o PWM do oscilador do dobrador ledcSetup(canal_osc, freq_osc, resolucao); ledcAttachPin(pin_osc, canal_osc); ledcWrite(canal_osc, ciclo); // Ajusta o PWM de controle de velocidade ledcSetup(canal_vel, freq_vel, resolucao); ledcAttachPin(pin_EN, canal_vel); ledcWrite(canal_vel, velocidade); //Ajusta a direção para LOW inicialmente digitalWrite(pin_DIR, dir); // Inicia o display display.init(); display.flipScreenVertically(); //Vira a tela verticalmente //ajusta o alinhamento para a esquerda display.setTextAlignment(TEXT_ALIGN_LEFT); //ajusta a fonte para Arial 10 display.setFont(ArialMT_Plain_10); display.clear(); //limpa o buffer do display display.drawString(0, 0, "Aquisição"); //escreve a velocidade no buffer display.drawString(0, 32, "RPM x PWM"); //escreve a velocidade no buffer display.display(); //mostra a mensagem delay(10000); //aguarda 10s antes de iniciar }


void loop()
{ //Varia os estados do PWM do máximo até o valor mínimo em passos de 136.5 unidades //para que todo o intervalo tenha 30 valores (4095 / 30 = 136.5 ) for (velocidade = 4095; velocidade >= min_vel ; velocidade = velocidade - 136.5) { int contador = -1; //define o valor inicial do contador unsigned long momento = 0.0; //zera a variável que armazenará o período boolean estado = digitalRead(pin_Leitura); //detecta o estado inicial do sensor int amostras = 100; //número de amostras para cálculo da média ledcWrite(canal_vel, velocidade);//ajusta o PWM para o novo valor de velocidade display.clear(); //limpa o buffer do display display.drawString(0, 0, "Ajustando PWM: " + String(velocidade)); //escreve a velocidade no buffer display.display(); //mostra a mensagem delay(2000); //aguarda um instante display.clear(); //limpa o buffer do display display.drawString(0, 0, "Medindo..."); //indica o incio da medida display.display(); //mostra a mensagem delay(10000); //aguarda 10s para velocidade se estabilizar while (contador < amostras) //inicia a detecção de 100 rotações { if ((estado == LOW) && (digitalRead(pin_Leitura) == HIGH)) //detecta a mudança para nível alto { estado = HIGH; //lembre que o nível alto foi detectado contador++; //incrementa o contador if (contador == 0) //se o contador assumiu zero, indica o início da marcação do tempo { momento = millis(); //captura o momento } } if ((estado == HIGH) && (digitalRead(pin_Leitura) == LOW)) //detecta mudança para nível baixo { estado = LOW; //marca o estado atual } } //envia para a serial os dados obtidos Serial.println(String(velocidade) + ";" + String(60.0 / ((millis() - momento) / 100000.0))); } }

Step 8: Characteristic Curve of This Motor

This was the curve obtained after the collection of approximately 400 pairs of points in several sweeps performed automatically and uninterruptedly.

Step 9: Files