-
-
Save fredoche/69c5f59cead4b7828653 to your computer and use it in GitHub Desktop.
rotary encoder with lock and somehow different decoding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package rotary; | |
import com.pi4j.io.gpio.GpioController; | |
import com.pi4j.io.gpio.GpioFactory; | |
import com.pi4j.io.gpio.GpioPinDigitalInput; | |
import com.pi4j.io.gpio.Pin; | |
import com.pi4j.io.gpio.PinPullResistance; | |
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent; | |
import com.pi4j.io.gpio.event.GpioPinListenerDigital; | |
import java.util.concurrent.locks.Lock; | |
import java.util.concurrent.locks.ReentrantLock; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
/** | |
* | |
* @author Mark de Reeper | |
*/ | |
public class RotaryEncoder { | |
private Lock lock = new ReentrantLock(true); | |
private final GpioPinDigitalInput inputA; | |
private final GpioPinDigitalInput inputB; | |
private final GpioController gpio; | |
private long encoderValue = 0; | |
private int lastEncoded = 0; | |
private boolean firstPass = true; | |
private RotaryEncoderListener listener; | |
private static final Logger LOGGER = Logger.getLogger(RotaryEncoder.class.getName()); | |
public RotaryEncoder(Pin pinA, Pin pinB, long initalValue) { | |
encoderValue = initalValue; | |
gpio = GpioFactory.getInstance(); | |
inputA = gpio.provisionDigitalInputPin(pinA, "PinA", PinPullResistance.PULL_UP); | |
inputB = gpio.provisionDigitalInputPin(pinB, "PinB", PinPullResistance.PULL_UP); | |
GpioPinListenerDigital inputListener = (GpioPinDigitalStateChangeEvent gpdsce) -> { | |
if (lock.tryLock()) { | |
int stateA = inputA.getState().getValue(); | |
int stateB = inputB.getState().getValue(); | |
LOGGER.log(Level.INFO, "{0}{1} encodedValue: {2}", new Object[]{stateA, stateB, encoderValue}); | |
try { | |
calcEncoderValue(stateA, stateB); | |
} finally { | |
lock.unlock(); | |
} | |
} else { | |
System.out.println("discarded redundant event"); | |
} | |
}; | |
inputA.addListener(inputListener); | |
inputB.addListener(inputListener); | |
Runtime.getRuntime().addShutdownHook(new Thread() { | |
@Override | |
public void run() { | |
LOGGER.info("RotarySwitch: Shutting down...."); | |
if (gpio != null) { | |
gpio.removeAllListeners(); | |
gpio.shutdown(); | |
} | |
} | |
}); | |
LOGGER.log(Level.INFO, "RotarySwitch initialised on pinA {0} and pinB {1}", | |
new String[]{pinA.getName(), pinB.getName()}); | |
} | |
public long getValue() { | |
return encoderValue; | |
} | |
public void setListener(RotaryEncoderListener listener) { | |
this.listener = listener; | |
} | |
private void calcEncoderValue(int stateA, int stateB) { | |
// converting the 2 pin value to single number to end up with 00, 01, 10 or 11 | |
int encoded = (stateA << 1) | stateB; | |
if (firstPass) { | |
firstPass = false; | |
} else { | |
// going up states, 01, 11 | |
// going down states 00, 10 | |
int sum = lastEncoded << 2 + encoded; | |
if (sum == 13 || sum == 4 || sum == 2 || sum == 11) { | |
encoderValue++; | |
listener.up(encoderValue); | |
} | |
if (sum == 14 || sum == 7 || sum == 1 || sum == 8) { | |
encoderValue--; | |
listener.down(encoderValue); | |
} | |
} | |
lastEncoded = encoded; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* @author Mark de Reeper | |
*/ | |
public interface RotaryEncoderListener { | |
void up(long encoderValue); | |
void down(long encoderValue); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For me a much simpler solution worked - https://gist.github.com/kachurovskiy/c819c01b8b8bfd15e7e5b4e77eea91d0