0

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;

@Override
public void run() {
    System.out.println("ON_ENG");
    Gpio.wiringPiSetup();
    SoftPwm.softPwmCreate(24, 0, 60);
    SoftPwm.softPwmWrite(24, 12);
    Thread.sleep(100);
    while((true)){
        SoftPwm.softPwmWrite(24, 12);
        Thread.sleep(100);
        SoftPwm.softPwmWrite(24, 20);
        Thread.sleep(100);

        if(stop){
            SoftPwm.softPwmWrite(24, 0);
            Thread.currentThread().destroy();
        }
    }
}
}

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

Thanks in advance.

cy8berpunk
  • 29
  • 7

3 Answers3

0

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
    console.promptForExit();

    // 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/
    com.pi4j.wiringpi.Gpio.pwmSetMode(com.pi4j.wiringpi.Gpio.PWM_MODE_MS);
    com.pi4j.wiringpi.Gpio.pwmSetRange(1000);
    com.pi4j.wiringpi.Gpio.pwmSetClock(500);

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

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

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


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

    // set the PWM rate to 0
    pwm.setPwm(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)
    gpio.shutdown();
}

Frank
  • 318
  • 1
  • 8
0

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.

joan
  • 71,024
  • 5
  • 73
  • 106
  • Like that? I changed it in the main comment.... – cy8berpunk May 15 '16 at 08: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 08:46
  • Ok, what ist the right tool? – cy8berpunk May 15 '16 at 08: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 08: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 08:57
  • @YellowDev I think servoblaster will switch off the pulses after a few seconds of inactivity. That's sort of okay for a servo but no good for an ESC. If that's what is happening there should be a configuration option to disable that behaviour. – joan May 15 '16 at 09:13
0

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?

Andy A
  • 1