Example Code for Arduino-PWM mode drives the motor

The article explains how to use PWM mode to drive motors with Arduino, detailing hardware and software preparation, a truth table for PWM control, and sample code for implementation. It covers initializing pins, configuring mcpwm, and controlling motor speed, making it an invaluable resource for enthusiasts seeking to optimize motor functions.

Hardware Preparation

Software Preparation

PWM mode drives the motor

Truth table of PWM control mode

IN1 IN2 OUT1 OUT2 explain
0 0 Hi-Z Hi-Z Taxiing (H-bridge high impedance)
0 1 L H retreat (OUT2 → OUT1)
1 0 H L advance (OUT1 → OUT2)
1 1 L L Braking (low side slow attenuation)

Sample Code

/**
 *@brief motorSpeeddetectionbyPWM.ino
 *@ Motor driver in PWM mode
 */
#include "driver/mcpwm.h"
#include "soc/mcpwm_struct.h" 
#include "soc/mcpwm_reg.h"

//IO12->M1_IN1
//IO13->M1_IN2
#define MOTOR_PWM_IN1 12 
#define MOTOR_PWM_IN2 13

//Initialize the pins needed to generate the PWM signal
void mcpwm_init(void)
{
  // Binding needs to output the PWM pin to the PWM channel
  mcpwm_gpio_init(MCPWM_UNIT_0,MCPWM0A,MOTOR_PWM_IN1);
  mcpwm_gpio_init(MCPWM_UNIT_0,MCPWM0B,MOTOR_PWM_IN2);

  //Configure mcpwm information
  mcpwm_config_t pwm_config;
  pwm_config.frequency = 1000;/*!<Set frequency of MCPWM in Hz*/
  pwm_config.cmpr_a = 0;/*!<Set % duty cycle for operator a(MCPWMXA), i.e for 62.3% duty cycle, duty_a = 62.3*/
  pwm_config.cmpr_b = 0;/*!<Set % duty cycle for operator b(MCPWMXB), i.e for 48% duty cycle, duty_b = 48.0*/
  pwm_config.counter_mode/*!<Set  type of MCPWM counter*/ = MCPWM_UP_COUNTER/*!<For asymmetric MCPWM*/; 
  pwm_config.duty_mode/*!<Set type of duty cycle*/ = MCPWM_DUTY_MODE_0/*!<Active high duty, i.e. duty cycle proportional to high time for asymmetric MCPWM*/;

  //Initialize a unit of mcpwm and bind the clock
  mcpwm_init(MCPWM_UNIT_0,MCPWM_TIMER_0,&pwm_config);
}

void advance(/*range:0~100*/uint8_t speed)
{
  mcpwm_set_duty_type(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_A,MCPWM_DUTY_MODE_0);
  mcpwm_set_signal_low(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_B);
  mcpwm_set_duty(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_A,speed);
}

void retreat(/*range:0~100*/uint8_t speed)
{
  //Give MOTOR_DIRECTION_PIN a continuous low level
  mcpwm_set_signal_low(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_A);

  /*
   * Call function mcpwm_set_duty_type() every time after mcpwm_set_signal_high() 
   * or mcpwm_set_signal_low() to resume with previously set duty cycle.
   */
  mcpwm_set_duty_type(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_B,MCPWM_DUTY_MODE_0);
  
  //The MOTOR_STEP_PIN pin outputs a PWM wave with a duty cycle of "speed"
  mcpwm_set_duty(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_B,speed);
}

void stop(void)
{
  mcpwm_set_signal_low(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_A);
  mcpwm_set_signal_low(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_B);
}

void breake(void)
{
  mcpwm_set_signal_high(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_A);
  mcpwm_set_signal_high(MCPWM_UNIT_0,MCPWM_TIMER_0,MCPWM_GEN_B);
}

void setup() {
  mcpwm_init();
}

void loop() {
  advance(30);
  delay(2000);
  retreat(60);
  delay(2000);
  stop();
  delay(2000);
  advance(30);
  delay(2000);
  retreat(60);
  delay(2000);
  breake();
  delay(2000);
}

Was this article helpful?

TOP