0

I wanted to control a DC motor with pigpio in C++. I have first of all written a simple Python program for this, where I still use RPi.GPIO. For this you can find many solutions how a DC motor could be controlled. The code looks like this:

import RPi.GPIO as gpio
import time

gpio.setmode(gpio.BCM)

PWM_MAX = 70

gpio.setwarnings(False)

ENA = 21    # 40
IN1 = 20    # 38
IN2 = 16    # 36

gpio.setup(IN1, gpio.OUT)
gpio.setup(IN2, gpio.OUT)

gpio.output(IN1, False)
gpio.output(IN2, False)

gpio.setup(ENA, gpio.OUT)

motorpwm = gpio.PWM(ENA,100)

motorpwm.start(0)
motorpwm.ChangeDutyCycle(0)

def setMotorMode(mode):
    if mode == "reverse":
        gpio.output(IN1, True)
        gpio.output(IN2, False)
    elif  mode == "forward":
        gpio.output(IN1, False)
        gpio.output(IN2, True)
    else:
        gpio.output(IN1, False)
        gpio.output(IN2, False)

def setMotor(power):
   int(power)
   if power < 0:
      setMotorMode("reverse")
      pwm = -int(PWM_MAX * power)
      if pwm > PWM_MAX:
         pwm = PWM_MAX
   elif power > 0:
      setMotorMode("forward")
      pwm = int(PWM_MAX * power)
      if pwm > PWM_MAX:
         pwm = PWM_MAX
   else:
      setMotorMode("stopp")
      pwm = 0

   print("pwm is " + str(pwm))

   motorpwm.ChangeDutyCycle(pwm)

def exit():
   gpio.output(IN1, False)
   gpio.output(IN2, False)
   gpio.cleanup()

if __name__ == "__main__":
    print("Driving forward:\n")
    for i in range(10):
        speed = 0.1 * i
        print("set speed to " + str(speed) + "\n")
        setMotor(speed)
        time.sleep(1)

    time.sleep(3)

    setMotor(0)

    time.sleep(3)

    print("Driving reverse:\n")
    for i in range(10):
        speed = -0.1 * i
        print("set speed to " + str(speed) + "\n")
        setMotor(speed)
        time.sleep(1)

And then I started to translate the code from RPi.GPIO and Python to pigpio and C++. Also first in a non-object oriented style:

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pigpio.h>

using namespace std;

const uint8_t PWM_MAX = 70;
const uint8_t ENA = 21; // Pin 40   //enableMotor Pin
const uint8_t IN1 = 20; // Pin 38    //forwardPin
const uint8_t IN2 = 16; // Pin 36   //backwardPin

void init() {
    gpioSetMode(ENA, PI_OUTPUT);
    gpioSetMode(IN1, PI_OUTPUT);
    gpioSetMode(IN2, PI_OUTPUT);
    gpioSetMode(IN1, PI_LOW);
    gpioSetMode(IN2, PI_LOW);
    gpioSetPWMfrequency(ENA, 60);
    gpioSetPWMrange(ENA, 100);
    gpioPWM(ENA, 0);
}

void setMotorMode(const string &mode) {
    printf("set motor mode to %s \n", mode.c_str());
    if(mode == "forward") {
        gpioSetMode(IN1, PI_LOW);
        gpioSetMode(IN2, PI_HIGH);
    } else if(mode == "reverse") {
        gpioSetMode(IN1, PI_HIGH);
        gpioSetMode(IN2, PI_LOW);
    } else {
        gpioSetMode(IN1, PI_LOW);
        gpioSetMode(IN2, PI_LOW);
    }
}

void setMotor(const double &power) {
    uint8_t pwm;
    if(power > 0) {
        setMotorMode("forward");
        pwm = (int)(PWM_MAX * power);
    } else if(power < 0) {
        setMotorMode("reverse");
        pwm = -(int)(PWM_MAX * power);
    } else {
        setMotorMode("stopp");
        pwm = 0;
    }

    if(pwm > PWM_MAX) {
        pwm = PWM_MAX;
    }

    printf("set pwm to %d \n", pwm);
    gpioPWM(ENA, pwm);
}

int main()
{
    if (gpioInitialise() == -1)
        return -1;

    printf("Driving forward:\n");
    double speed;
    for (int i = 0; i < 10; i++) {
        speed = 0.1 * i;
        printf("set speed to %f \n", speed);
        setMotor(speed);
        usleep(1000000);
    }

    usleep(3000000);

    speed = 0;
    setMotor(speed);

    usleep(3000000);

    printf("Driving reverse:\n");
    for (int i = 0; i < 10; i++) {
        speed = -0.1 * i;
        printf("set speed to %f \n", speed);
        setMotor(speed);
        usleep(1000000);
    }

    usleep(3000000);

    speed = 0;
    setMotor(speed);
}

Don't get irritated, I have written simple scripts here. I will use this later in an object oriented class. Also I have extended this concept that I get the PWM signal from a PCA9685 servo driver. Now this is simple for my understanding how I implement that without. And apparently something in my C++ code doesn't work that way.

I use a L298N H-Bridge. It's actually the typical setup with an external battery for the motor driver and that the grounds are connected together.

When I run my program, I see that in Python the motor is moving. In C++ I only hear some noise of an electric motor, but nothing is doing. The noise also gets louder, which represents changing values.

Driving forward:
set speed to 0.000000
set motor mode to stopp
set pwm to 0
set speed to 0.100000
set motor mode to forward
set pwm to 7
set speed to 0.200000
set motor mode to forward
set pwm to 14
set speed to 0.300000
set motor mode to forward
set pwm to 21
set speed to 0.400000
set motor mode to forward
set pwm to 28
set speed to 0.500000
set motor mode to forward
set pwm to 35
set speed to 0.600000
set motor mode to forward
set pwm to 42
set speed to 0.700000
set motor mode to forward
set pwm to 49
set speed to 0.800000
set motor mode to forward
set pwm to 56
set speed to 0.900000
set motor mode to forward
set pwm to 63
set motor mode to stopp
set pwm to 0
Driving reverse:
set speed to -0.000000
set motor mode to stopp
set pwm to 0
set speed to -0.100000
set motor mode to reverse
set pwm to 7
set speed to -0.200000
set motor mode to reverse
set pwm to 14
set speed to -0.300000
set motor mode to reverse
set pwm to 21
set speed to -0.400000
set motor mode to reverse
set pwm to 28
set speed to -0.500000
set motor mode to reverse
set pwm to 35
set speed to -0.600000
set motor mode to reverse
set pwm to 42
set speed to -0.700000
set motor mode to reverse
set pwm to 49
set speed to -0.800000
set motor mode to reverse
set pwm to 56
set speed to -0.900000
set motor mode to reverse
set pwm to 63
set motor mode to stopp
set pwm to 0

If I also extend my Python program with outputs, I also see the same values.

Either gpioPWM(ENA, pwm); is not the equivalent to motorpwm.ChangeDutyCycle(pwm) or there is something wrong with the HIGH and LOW for EN1 and EN2.

For example, with servo motors or even ultrasonic sensors, I now have a working code for pigpio in C++. I can also use a PCA9685 servo driver via I2C in pigpio. If I can get DC motors working now, I will get a little closer to my goal of building robots.

Many thanks in advance.

1

1 Answer 1

0

You set the mode (normally PI_INPUT or PI_OUTPUT) with gpioSetMode.

You set the level (PI_LOW or PI_HIGH) with gpioWrite.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.