Pi4J has introduced V2 which is a whole new concept and approach. The most important thing, at least for me, is that pigpio has replaced the wiringPi library to access the RPi hardware.
Therefore, it is absolutely necessary to have the pigpio libraries installed. How to do this, is explained here.
Although I absolutely don't like the fact they've kicked out the devices and extensions part (already kicked out in version 1.4) I still want to give it a try...
If you want to use the pigpio library in combination with Pi4J v2 (you can also use the linux-fs library, but that's not explained here) the following preconditions must be met:
You must run your application as sudo (currently still a requirement of the pigpio library). Therefore, if you use NetBeans as a development environment, you have to add sudo in the Exec Prefix section of the Java platform you've created for the RPi, like shown in the image at the bottom.
You should not have the PiGpio daemon running. If you do, kill it with the command sudo killall pigpiod.
Not killing the daemon will result in an initialisation error.
The pigpio library is loaded through a call to
libraries/pi4j-library-pigpio/src/main/java/com/pi4j/library/pigpio/util/NativeLibraryLoader.java/load(String fileName, String libName)
This call comes from libraries/pi4j-library-pigpio/src/main/java/com/pi4j/library/pigpio/internal/PIGPIO.java where there's a static block defined calling the NativeLibraryLoader.load() method:
static {
// Load the platform library
NativeLibraryLoader.load("libpi4j-pigpio.so", "pi4j-pigpio");
}
In the load() method a check is done if the library cannot be found through the System properties. But that returns null on a RPi. Hence, the OS architecture is then requested and on a RPi this should be arm (unless you have the 64-bit OS in use, which should give arm64, I guess...).
Using NetBeans, create a new project. Call it I2cTest (what's in a name...). We're going to manipulate an MCP23016 IO expander very basically.
Next, once the project is created, include the necessary libraries: right-click on the Libraries node in the project and select Add Library...
Now add the following code into the I2cTest application:
import com.pi4j.Pi4J;
import com.pi4j.context.Context;
import com.pi4j.io.i2c.I2C;
import com.pi4j.io.i2c.I2CConfig;
import com.pi4j.io.i2c.I2CProvider;
import com.pi4j.util.Console;
public class I2cTest {
private static final int I2C_BUS = 15;
private static final int MCP23017_ADDRESS = 0x22;
private static final byte MCP23017_IODIR_A = 0x00;
private static final byte MCP23017_OLAT_A = 0x14;
private static final byte TCA9534_REG_ADDR_CFG = 0x03;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
I2cTest i2cTest = new I2cTest();
i2cTest.doStart();
}
private void doStart() {
Console console = new Console();
console.box("Welcome");
Context pi4j = Pi4J.newAutoContext();
I2CProvider i2CProvider = pi4j.provider("pigpio-i2c");
I2CConfig i2cConfig = I2C.newConfigBuilder(pi4j).id("MCP23017").bus(I2C_BUS).device(MCP23017_ADDRESS).build();
try (I2C mcp23017 = i2CProvider.create(i2cConfig)) {
int config = mcp23017.readRegister(MCP23017_IODIR_A);
if (config < 0) {
throw new IllegalStateException(
"Failed to read configuration from address 0x" + String.format("%02x", MCP23017_IODIR_A));
}
byte currentState = (byte) mcp23017.readRegister(MCP23017_IODIR_A);
if (config != 0x00) {
System.out.println("MCP23017 is not configured as OUTPUT, setting register 0x" + String
.format("%02x", MCP23017_IODIR_A) + " to 0x00");
currentState = 0x00;
mcp23017.writeRegister(MCP23017_IODIR_A, currentState);
mcp23017.writeRegister(MCP23017_IODIR_A, (byte) 0x00);
}
// bit 8, is pin 1 on the board itself, so set pins in reverse:
currentState = setPin(currentState, 8, mcp23017, true);
sleep(500);
currentState = setPin(currentState, 8, mcp23017, false);
sleep(500);
currentState = setPin(currentState, 7, mcp23017, true);
sleep(500);
currentState = setPin(currentState, 7, mcp23017, false);
sleep(500);
}
}
private void sleep(long time) {
try {
Thread.sleep(time);
}
catch (InterruptedException iex) {
System.out.println("Exception: [" + iex.getMessage() + "].");
}
}
private byte setPin(byte currentState, int pin, I2C mcp23017, boolean high) {
byte newState;
if (high) {
newState = (byte) (currentState | (1 << pin));
}
else {
newState = (byte) (currentState & ~(1 << pin));
}
System.out.println("Setting MCP23017 to new state " + asBinary(newState));
mcp23017.writeRegister(MCP23017_OLAT_A, newState);
return newState;
}
private String asBinary(byte b) {
StringBuilder sb = new StringBuilder();
sb.append("b");
sb.append(((b >>> 7) & 1));
sb.append(((b >>> 6) & 1));
sb.append(((b >>> 5) & 1));
sb.append(((b >>> 4) & 1));
sb.append("_");
sb.append(((b >>> 3) & 1));
sb.append(((b >>> 2) & 1));
sb.append(((b >>> 1) & 1));
sb.append(((b >>> 0) & 1));
return sb.toString();
}
}