Problems with controlling a servo with java and Pi4J on a Raspberry PI 2

2.2k views Asked by At

I want to control a MG90S Servo via the GPIO pins of my Raspberry PI using Pi4J.

I have created a Java application with an hz and a duty cycle("High in ms:") keyboard input.

import java.util.Scanner;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        GpioController gpioFactory = GpioFactory.getInstance();
        GpioPinDigitalOutput myServo =  gpioFactory.provisionDigitalOutputPin(
                    RaspiPin.GPIO_07, PinState.LOW);

        //Input of hz and duty cycle
        System.out.println("Hz:");
        Scanner scanner = new Scanner(System.in);
        float hz = scanner.nextFloat();
        System.out.println("High in ms:");
        float highTime = scanner.nextFloat();
        scanner.close();

        //Calculate GPIO low time: hz period time - duty time
        float lowTime = 1000 / hz - highTime;

        while (true) {
            myServo.high();
            long upMs = new Float(highTime).longValue(); // Up time miliseconds
            int upNanos = new Float(highTime * 1000000 % 1000000).intValue(); // Up time nanoseconds
            java.lang.Thread.sleep(upMs, upNanos);

            myServo.low();
            long lowMs = new Float(lowTime).longValue();
            int lowNanos = new Float(lowTime * 1000000 % 1000000).intValue();

            java.lang.Thread.sleep(lowMs, lowNanos);

        }
    }
}

Example 1: With the following input I expect that the servo is at Rotation.

hz: 50 high in ms: 1

Result: The servo is at as expected.

Example 2: With the following input I expect that the servo is at 180° Rotation.

hz: 50 high in ms: 2

Result: The servo is at ~80° rotation.

Has anyone an idea what I'm doing wrong?

2

There are 2 answers

0
Rhias On BEST ANSWER

The problem had nothing to do with Pi4J. The sleep period wasn't exact enougth.

"The granularity of sleeps is generally bound by the thread scheduler's interrupt period. In Linux, this interrupt period is generally 1ms in recent kernels. In Windows, the scheduler's interrupt period is normally around 10 or 15 milliseconds" - qwerty https://stackoverflow.com/a/11498647/5049836

0
chris On

I had a similar problem with another servo (i think it was arduino stuff).

I just calibrated the given values that way that the result is correct. I don't know where it comes from but the servo did what i want to.