Introduction: Electric Turbine With ESP32
Today, I’ll be discussing an electric turbine with ESP32. The assembly has a part that was printed in 3D. I will present a PWM function of the ESP32 that is suitable for controlling electric motors. This will be used in a DC motor. I will also demonstrate the operation of this MCPWM (Motor Control PWM) in a practical application.
I used ESP32 LoRa in this project, and I think it is important to note here that this microcontroller has two blocks inside it. These blocks are capable of controlling three motors each. Thus, it is possible to control up to six motors with PWM, all independently. This means that the control I’ll use here is not the standard (which is something similar to the Arduino). Instead, the control is the chip itself, which guarantees the ESP32 a lot of flexibility with respect to motor control.
Step 1: Demonstration
Step 2: PWM Motor Control
General Diagram:
• The MCPWM function of the ESP32 can be used to control various types of electric motors. It has two units.
• Each unit has three PWM output pairs.
• Each output A / B pair can be synchronized with one of three synchronization timers 0, 1, or 2.
• One Timer can be used to synchronize more than one PWM output pair
Full Diagram:
• Each unit is also capable of collecting input signals as SYNCHRONIZATION SIGNS;
• Detect FAULT SIGNS for overcurrent or motor overvoltage;
• Obtain feedback with CAPTURE SIGNALS, such as the position of the Engine
Step 3: Resources Used
• Jumpers for connection
• Heltec Wifi LoRa 32
• Common DC motor
• Bridge H - L298N
• USB cable
• Protoboard
• Power supply
Step 4: ESP 32 Dev Kit - Pinout
Step 5: Turbine Mounting
Step 6: Circuit - Connections
Step 7: Measurement on Oscilloscope
Step 8: Source Code
Header
#include <Arduino.h> //Não é necessário caso use Arduino IDE
#include "driver/mcpwm.h" //inclui a biblioteca "Motor Control PWM" nativa do ESP32 #include <Wire.h> // Necessário apenas para o Arduino 1.6.5 e posterior #include "SSD1306.h" // o mesmo que #include "SSD1306Wire.h" //OLED_SDA -- GPIO4 //OLED_SCL -- GPIO15 //OLED_RST -- GPIO16 #define SDA 4 #define SCL 15 #define RST 16 SSD1306 display(0x3c, SDA, SCL, RST); //Instanciando e ajustando os pinos do objeto "display" #define GPIO_PWM0A_OUT 12 //Declara GPIO 12 como PWM0A #define GPIO_PWM0B_OUT 14 //Declara GPIO 14 como PWM0B
Setup
void setup() {
Serial.begin(115200); display.init(); //display.flipScreenVertically(); //Vira a tela verticalmente display.clear(); //ajusta o alinhamento para a esquerda display.setTextAlignment(TEXT_ALIGN_LEFT); //ajusta a fonte para Arial 16 display.setFont(ArialMT_Plain_16); //mcpwm_gpio_init(unidade PWM 0, saida A, porta GPIO) => Instancia o MCPWM0A no pino GPIO_PWM0A_OUT declarado no começo do código mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); //mcpwm_gpio_init(unidade PWM 0, saida B, porta GPIO) => Instancia o MCPWM0B no pino GPIO_PWM0B_OUT declarado no começo do código mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT); mcpwm_config_t pwm_config; pwm_config.frequency = 1000; //frequência = 500Hz, pwm_config.cmpr_a = 0; //Ciclo de trabalho (duty cycle) do PWMxA = 0 pwm_config.cmpr_b = 0; //Ciclo de trabalho (duty cycle) do PWMxb = 0 pwm_config.counter_mode = MCPWM_UP_COUNTER; //Para MCPWM assimetrico pwm_config.duty_mode = MCPWM_DUTY_MODE_0; //Define ciclo de trabalho em nível alto //Inicia(Unidade 0, Timer 0, Config PWM) mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //Define PWM0A & PWM0B com as configurações acima }
Functions
//Função que configura o MCPWM operador A (Unidade, Timer, Porcentagem (ciclo de trabalho))
static void brushed_motor_forward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num , float duty_cycle) { //mcpwm_set_signal_low(unidade PWM(0 ou 1), Número do timer(0, 1 ou 2), Operador (A ou B)); => Desliga o sinal do MCPWM no Operador B (Define o sinal em Baixo) mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B); //mcpwm_set_duty(unidade PWM(0 ou 1), Número do timer(0, 1 ou 2), Operador (A ou B), Ciclo de trabalho (% do PWM)); => Configura a porcentagem do PWM no Operador A (Ciclo de trabalho) mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle); //mcpwm_set_duty_tyoe(unidade PWM(0 ou 1), Número do timer(0, 1 ou 2), Operador (A ou B), Nível do ciclo de trabalho (alto ou baixo)); => define o nível do ciclo de trabalho (alto ou baixo) mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0); //Nota: Chame essa função toda vez que for chamado "mcpwm_set_signal_low" ou "mcpwm_set_signal_high" para manter o ciclo de trabalho configurado anteriormente } //Função que configura o MCPWM Do operador B (Unidade, Timer, Porcentagem (ciclo de trabalho)) static void brushed_motor_backward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num , float duty_cycle) { mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A); //Desliga o sinal do MCPWM no Operador A (Define o sinal em Baixo) mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_B, duty_cycle); //Configura a porcentagem do PWM no Operador B (Ciclo de trabalho) mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); //define o nível do ciclo de trabalho (alto ou baixo) } //Função que para o MCPWM de ambos os Operadores static void brushed_motor_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) { mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A); //Desliga o sinal do MCPWM no Operador A mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B); //Desliga o sinal do MCPWM no Operador B }
Loop
void loop() {
//Move o motor no sentido horário brushed_motor_forward(MCPWM_UNIT_0, MCPWM_TIMER_0, 50.0); oled("50"); delay(2000); //Para o motor brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_0); oled("0"); delay(2000); //Move o motor no sentido antihorário brushed_motor_backward(MCPWM_UNIT_0, MCPWM_TIMER_0, 25.0); oled("25"); delay(2000); //Para o motor brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_0); oled("0"); delay(2000); // Aceleracao i de 1 a 100 for(int i=10;i<=100;i++){ brushed_motor_forward(MCPWM_UNIT_0, MCPWM_TIMER_0, i); oled(String(i)); delay(200); } // Desaceleração i de 100 a 1 delay(5000); for(int i=100;i>=10;i--){ brushed_motor_forward(MCPWM_UNIT_0, MCPWM_TIMER_0, i); oled(String(i)); delay(100); } delay(5000); }