229-2

import com.pi4j.wiringpi.SoftPwm;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioPin;

/**
 * Control class for servo motors
 * @author Stefan Fambach (With help of many others)
 * @version 0.1
 * 
 * This class can either set position by values between posMin and posMax
 * or it can caluculate the position by an angle where degMin <= angle <= degMax
 * 
 * No warranty free for use see GPL v3.
 */
public class Servo
{
    Pin pin;

    int degMin = -90;
    int degMax = 90;

    int posMin = 4; // to have a center
    int posMax = 25;
    int pos = -1;

    /**
     * range between min and max degree
     */
    double degDelta = degMax - degMin;

    /**
     * range between min and max position
     */
    double posDelta = posMax - posMin;

    /**
     * multiplier for degree to pos calculation
     */
    double multiplier = posDelta/degDelta;

    /**
     * Time in ms to wait after new position is set
     */
    int timeout = 1000;

    /**
     * Default constructor, default pin is GPIO_27
     */
    public Servo(){
        this(RaspiPin.GPIO_27);
    }

    /**
     * Constructor for objects of class Servo
     */
    public Servo(Pin controlPin) 
    {
        this.pin = controlPin;
        // initialize wiringPi library
        com.pi4j.wiringpi.Gpio.wiringPiSetup();

        // create soft-pwm pins (min=0 ; max=100)
        SoftPwm.softPwmCreate(this.pin.getAddress(), 0, 200);

        moveCenter();

    }

    /** 
     * set position in degree, only 20 positions are possible, each step will be calculated
     */
    boolean setDeg(int deg) throws Exception {
        if(deg > degMax){
            throw new Exception( "Entered deg: "+ deg + "is greater maxDeg "+degMax);
        }

        if(deg < degMin){
            throw new Exception( "Entered deg: "+ deg + "is smaller maxDeg "+degMin);            
        }

        if(deg < 0){
            deg = (-degMin)+ deg;
        }else{
            deg -= degMin;
        }

        return setPos((int) (deg * multiplier));
    }

    /** 
     * set position posMin - posMax (default 0-21)
     */
    public boolean setPos(int pos)throws Exception{
        if(pos < 0 ){
            throw new Exception (pos + " Pos to small (<0) ");
        }

        if(pos > posMax ){
            throw new Exception (pos + " Pos to big > "+posMax+")");
        }
        if(pos != this.pos){
            this.pos = pos;
            SoftPwm.softPwmWrite(pin.getAddress(), posMin + pos);
            sleep(timeout);
            SoftPwm.softPwmWrite(pin.getAddress(), 0);
            return true;
        }
        return false;
    }

    /** 
     * set Servo to center position
     */
    public void moveCenter(){
        try{
            setPos((posMax-posMin+1)/2);
        } catch (Exception ex){
            // will hopefully never happen
        }
    }

    /** 
     * set Servo to min position
     */
    public void moveToMinPos(){
        try{
            setPos(0);
        } catch (Exception ex){
            // will hopefully never happen
        }
    }

    /** 
     * set Servo to max position
     */
    public void moveToMaxPos(){
        try{
            setPos(posMax-posMin);
        } catch (Exception ex){
            // will hopefully never happen
        }
    }

    public int getPos(){
        return this.pos;
    }

    public int getDegMin(){
        return degMin;
    }

    public int getDegMax(){
        return degMax;
    }

    public void setDegMin(int min){
        this.degMin = min;
        calculateVariables();
    }

    public void getDegMax(int max){
        this.degMax = max;
        calculateVariables();
    }

    public void setPosMin(int min){
        this.posMin = min;
        calculateVariables();
    }

    public void setPosMax(int max){
        this.posMax = max;
        calculateVariables();
    }

    public int getPosMin(){
        return  this.posMin;
    }

    public int getPosMax(){
        return  this.posMax;
    }

    /**
     * calculate the ranges for deg and pos 
     * as well as the multiplier for degree positioning of the servo
     */
    private void calculateVariables(){
        degDelta = degMax - degMin;
        posDelta = posMax - posMin;
        multiplier = posDelta/degDelta;
    }

    private void sleep(int msec){
        try
        {
            Thread.sleep(msec);
        }
        catch ( InterruptedException e)
        {
        }
    }

    public void release(){
        SoftPwm.softPwmStop(pin.getAddress());
        GpioController gpio = GpioFactory.getInstance();
        gpio.unprovisionPin(new GpioPin[]{gpio.getProvisionedPin(pin)});


    }
}