I would like to control a brushless motor with a Java program running on a Raspberry Pi model b+.

This is the code that I am using:

package de.ye.boat_eng;

import com.pi4j.wiringpi.Gpio;
import com.pi4j.wiringpi.SoftPwm;

public class ON implements Runnable{

public static boolean stop = false;

public void run() {
    SoftPwm.softPwmCreate(24, 0, 60);
    SoftPwm.softPwmWrite(24, 12);
        SoftPwm.softPwmWrite(24, 12);
        SoftPwm.softPwmWrite(24, 20);

            SoftPwm.softPwmWrite(24, 0);

But the motor isn't running "stable", it turns on and off sometimes slower sometimes faster...

Thanks in advance.


You are not using SoftPwm.softPwmWrite properly. You almost certainly want a delay between one call and the next.

SoftPwm.softPwmWrite(24, 5) will start to send pulses of I guess length 833 µs (1000000/60 * 5/100). It will send those pulses 60 times a second until told to change. You don't need to call the function 60 times a second.

At the moment you keep changing the pulse width so the motor never gets a chance to arrive and stay at the set throttle.

I would stop doing that. You will wear your motor out much faster than intended. Put a sleep of a tenth of a second or so between each call to give the motor time to reach the target speed.

  • Like that? I changed it in the main comment....
    – cy8berpunk
    May 15 '16 at 8:40
  • @YellowDev Possibly. Remember I do not know Pi4J so have no idea if sleep(100) sleeps for a 100 days, hours, minutes, seconds, miiliseconds, or microseconds. Also, I repeat, you will not properly control an ESC with Pi4J software PWM. It is the wrong tool for the job.
    – joan
    May 15 '16 at 8:46
  • Ok, what ist the right tool?
    – cy8berpunk
    May 15 '16 at 8:48
  • @YellowDev I have no idea for Java, and anyhow there may be other undeclared factors to take into consideration. Does Java allow access to the local file system? You can control servoblaster and my pigpio via a pipe (the same as writing to a local file). You can also control my pigpio via its socket interface.
    – joan
    May 15 '16 at 8:53
  • Yes java allows the acces to the local file system. But i tried it with servoblaster and it don t work the motors turn shortly on and than they go off.....
    – cy8berpunk
    May 15 '16 at 8:57

Raspberry Pi should be relatively bad for this task, because raspbian is not a real-time operating system. See this thread, hope it is helpful: Is it possible to run real time software?

  • Nevertheless, driving a pin in PWM mode should be possible in Linux. Sep 3 '20 at 12:11

As mentioned before, indeed Raspbian OS is not real-time so software controlled PWM will never be fully stable.

But luckily there is hardware support on specific GPIOs! As it is well described on https://techetrx.com/raspberry-pi-tutorials/using-gpio-and-pwm-in-raspberry-pi/:

The Raspberry Pi supports software configurable PWM on all its GPIO pins. You can essentially program a GPIO to output a PWM pulse of a varying duty cycle. Apart from software PWM, it also provides hardware PWM on GPIO12, 13, 18 and 19. It has 2 separate channels for hardware PWM. Channel zero i.e. PWM0 consisting of GPIO12 and GPIO18 and PWM1 with GPIO13 and GPIO19.

To answer to the comment of @joan, the sleep value in Thread.sleep(100); is in milliseconds.

You can find a nice PWM example in https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/PwmExample.java

public static void main(String[] args) throws InterruptedException {

        // create Pi4J console wrapper/helper
        // (This is a utility class to abstract some of the boilerplate code)
        final Console console = new Console();

        // print program title/header
        console.title("<-- The Pi4J Project -->", "PWM Example");

        // allow for user to exit program using CTRL-C

        // create GPIO controller instance
        GpioController gpio = GpioFactory.getInstance();

        // All Raspberry Pi models support a hardware PWM pin on GPIO_01.
        // Raspberry Pi models A+, B+, 2B, 3B also support hardware PWM pins: GPIO_23, GPIO_24, GPIO_26
        // by default we will use gpio pin #01; however, if an argument
        // has been provided, then lookup the pin by address
        Pin pin = CommandArgumentParser.getPin(
                RaspiPin.class,    // pin provider class to obtain pin instance from
                RaspiPin.GPIO_01,  // default pin if no pin argument found
                args);             // argument array to search in

        GpioPinPwmOutput pwm = gpio.provisionPwmOutputPin(pin);

        // you can optionally use these wiringPi methods to further customize the PWM generator
        // see: http://wiringpi.com/reference/raspberry-pi-specifics/

        // set the PWM rate to 500
        console.println("PWM rate is: " + pwm.getPwm());

        console.println("Press ENTER to set the PWM to a rate of 250");

        // set the PWM rate to 250
        console.println("PWM rate is: " + pwm.getPwm());

        console.println("Press ENTER to set the PWM to a rate to 0 (stop PWM)");

        // set the PWM rate to 0
        console.println("PWM rate is: " + pwm.getPwm());

        // stop all GPIO activity/threads by shutting down the GPIO controller
        // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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