#define GPIO_A1 25
#define GPIO_A2 33
#define GPIO_B1 32
#define GPIO_B2 26
#define GPIO_C1 12
#define GPIO_C2 14
#define GPIO_D1 27
#define GPIO_D2 13
#define FREQUENCY_HZ 500
#define RESOLUTION_BITS 7 // 1 - 16
#define MAXIMUM_DUTY_CYCLE ((1 << RESOLUTION_BITS) - 1)
uint8_t pins[][2] = {{GPIO_A1, GPIO_A2}, {GPIO_B1, GPIO_B2}, {GPIO_C1, GPIO_C2}, {GPIO_D1, GPIO_D2}};
void setSpeed(uint8_t motor, int8_t speed){
ledcWrite(2 * motor, speed > 0 ? speed : 0);
ledcWrite(2 * motor + 1, speed < 0 ? -speed : 0);
}
void setup() {
for (uint8_t motor = 0; motor < 4; motor++){
ledcSetup(2 * motor, FREQUENCY_HZ, RESOLUTION_BITS);
ledcSetup(2 * motor + 1, FREQUENCY_HZ, RESOLUTION_BITS);
ledcAttachPin(pins[motor][0], 2 * motor);
ledcAttachPin(pins[motor][1], 2 * motor + 1);
}
}
void loop() {
for (uint16_t motor = 0; motor < 4; motor++){
int8_t step = 1;
for (int8_t speed = 1; !(speed == 0 && step == 1); speed += step){
setSpeed(motor, speed);
delay(30);
if (abs(speed) == MAXIMUM_DUTY_CYCLE)
step = -step;
}
}
}
The program will drive all the 4 motors, one by one, first gradually to maximum rotation, then gradually to maximum opposite rotation, and in the end towards stop.
First section defines GPIO pins as in the picture. A1 and A2 are 2 pins for the first motor, B2 and B2 for the second, etc. Frequency, FREQUENCY_HZ, will be 500 Hz. Original Arduino boards use frequencies from around 500 till 1000 Hz. 500 is more than enough because the motor has a high rotational inertia and it is not possible to change speed more than 500 times per second. RESOLUTION_BITS 7 defines speed range between -127 (=27-1) and 127. It defines MAXIMUM_DUTY_CYCLE as 127. Bit shifting 1 will do the math for us.
Next is defined an array consisting of GPIOs defined above. It is easier to use an array then a list of constants because we can iterate the array.
Function setSpeed(motor, speed) sets speed speed for motor number motor. speed must be in range -127 to 127, motor 0 - 3. No input values validation is done anywhere in our examples to keep them verbatim. Doing no input parameter checking is a big no-no for a production code. PWM/PWM motor drivers usually accept 0 V on pin 1 and pin 2 expects a variable PWM signal width in order to spin the motor in one direction. To spin it in the other direction, pin 1 accepts variable signal and pin 2 is at 0 V.
setup() iterates 4 motors, 2 pins each, and sets PWM's configuration, according to our selected constants, in the first 2 loop's commands. They use ledcSetup() functions, which accept channel number as first argument. Here we just choose increasing integers, from 0 up. They have to be different as every pin will use its own PWM signal. The last 2 use ledcAttachPin() function to attach PWM signal to selected pins.
loop() is a standard C code so there are no new things to learn about the hardware here. 2 nested loops and the inner one sets motor's speed.