B4J Library JPI4J2b Library for use GPIO,I2C and SPI with Raspberry Pi4B and Java 11

For years I have been using the JPI4J library to control the GPIOs and I2C bus of the Raspberry 3B with Java8.

With the appearance of the Raspberry 4B with Java11, this library stopped working, and after a while Erel gave us the JPI4J2 that works perfectly with the GPIOs but does NOT have the I2C bus methods.

There is some librarys for I2C but not all the methods are there, and so I finally decided to write a library that contains the GPIOs, the I2C bus and the SPI bus, all together.

This library works perfectly on the Raspberry 4B with Java11 or later and is tested with different I2C devices, and all the GPIOs. The SPI bus is not tested because I don't have any devices right now, but I'm sure it will work.

I attach a code example in B4J to use it.

B4X:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True

    'path to Java11
    #JavaCompilerPath: 11, C:\Java\jdk-11.0.1\bin\javac.exe

    'jar containing I2C, SPI and GPIO code
    #AdditionalJar: JPI4J2b.jar
 
    #AdditionalJar: pi4j-core.jar
    #AdditionalJar: pi4j-device.jar
    #AdditionalJar: pi4j-gpio-extension.jar
    #AdditionalJar: pi4j-library-pigpio.jar
    #AdditionalJar: pi4j-plugin-pigpio.jar
    #AdditionalJar: pi4j-plugin-raspberrypi.jar
    #AdditionalJar: slf4j-api.jar
    #AdditionalJar: slf4j-simple.jar
#End Region

Sub Process_Globals
    Dim timer1 As Timer
    Dim pinpon As Boolean

    Dim pi4 As PI4wrapper 'or your name of the class <<<<<<<<<<<<<<<<<<<<<<<<<<<<
    Dim Pot1,Pot2 As Int
    Dim ADC1 As Int
    Dim Add_Pot1,Add_Pot2 As Int
    Dim Add_ADC1 As Int
End Sub

Sub AppStart (Args() As String)
    Log("Welcome to PI4J for raspberry 4 and Java11 !!!")
    timer1.Initialize("timer1",3000)

    Add_Pot1=40 'Address of first DS1882 (Digital Audio Potentiometer) in bus I2c
    Add_Pot2=41 'Address of second DS1882 (Digital Audio Potentiometer) in bus I2c
    Add_ADC1=72 'or 0x48 address of ADS1115 (ADC converter) in bus I2C
 
    CallSubDelayed(Me,"start")
    StartMessageLoop
End Sub

Sub start
'init
    pi4.Initialize

'GPIO
    'init GPIO as output .Pins numbered following PI4J2 description (different from PI4J)
    pi4.initOutput(15)
    pi4.initOutput(21)
    'init GPIO as input
    pi4.initInput(24,True)
    pi4.initInput(25,True)
    pi4.initInput(4,True)
    pi4.initInput(8,True)
  
'I2C  
    'init I2Cdevices
        pi4.initializeI2C(1,3) 'bus 1, 3 I2C devices
        Pot1=pi4.setI2CDevice(Add_Pot1)
        Pot2=pi4.setI2CDevice(Add_Pot2)
        ADC1=pi4.setI2CDevice(Add_ADC1)
 
        'Digital Pots DS1882 I2C devices
        'configure POT1 and POT2 for 33 steps
        pi4.WriteI2C(Pot1,135)
        pi4.WriteI2C(Pot2,135)
        'ADC ADS1115
        pi4.WritebytesI2C(ADC1, Array As Byte(0x01,0xC2,0x83)) 'Configuration. View datasheet
        pi4.WritebytesI2C(ADC1,Array As Byte(0x00)) ' 0x00 = Change to Conversion Register.


'SPI
    pi4.InitSPI(1,0, 500000) 'chip select, address, bitrate
              
    timer1.Enabled=True  
End Sub

Sub timer1_Tick
    If pinpon Then
        pinpon=False
        pi4.WriteI2C(Pot1,0) '0 attenuation in Pot1 channel L
        pi4.WriteI2C(Pot1,64)'0 attenuation in Pot1 channel R
        pi4.WriteI2C(Pot2,0) '0 attenuation in Pot2 channel L
        pi4.WriteI2C(Pot2,64)'0 attenuation in Pot2 channel R
  
        'write GPO output
        pi4.WritePin(21,True)

        'write to SPI
        pi4.writeSPI(Array As Byte(0,1,1)) 'no real data. I haven't any SPI device to test
    Else
        pinpon=True
        pi4.WriteI2C(Pot1,33)   'full attenuation in Pot1 channel L
        pi4.WriteI2C(Pot1,33+64)'full attenuation in Pot1 channel R
        pi4.WriteI2C(Pot2,33)   'full attenuation in Pot2 channel L
        pi4.WriteI2C(Pot2,33+64)'full attenuation in Pot2 channel R
  
        'write GPO output
        pi4.WritePin(21,False)

        'write to SPI
        pi4.writeSPI(Array As Byte(0,2,3)) 'no real data. I haven't any SPI device to test
    End If



    'read devices
 
    'read position of pots 1 and 2<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    Log("POT0= "&pi4.ReadI2C(Pot1))
    Log("POT1= "&pi4.ReadI2C(Pot2))
 
    'read state of an input <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    Log("Read pin24 "&pi4.readInputPin(24))
 
    'read state of an output
    Log("Read pin21 "&pi4.readOutputPin(21))'attention. is the value off an output


    'read level in ADC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    Dim rcvbuffer() As Byte
    rcvbuffer = pi4.ReadbytesI2C(ADC1,2) 'read 2 bytes . View datasheet
    For i = 0 To 1
        rcvbuffer(i) = Bit.And(0xff, rcvbuffer(i)) 'Convert Signed(-128 to 127) byte to Unsigned (0 to 255)
    Next
    Dim VAlue As Int = (255* rcvbuffer(0)) + rcvbuffer(1)
    Log("Value read from AnalogtoDigital converter = "&VAlue)
 
 
    'SPI <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    Log("SPIvalue="&pi4.readSPI(3)) 'read 3 bytes


    Log("---------------------")
End Sub

Sub PinState(nPin As Int,state As Boolean)
    'this function receives callback from the classe when a GPI changes
    Log("pin="&nPin&" state="&state)
End Sub

The class that controls it is (Named PI4wrapper or your choice):

B4X:
'PI4J2b for use in B4J and raspberry Pi4B with Java11
'Class named PI4wrapper in this example <<<<<<<<<<<<<<<<<

Sub Class_Globals
    Private pi4b As JavaObject
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
        pi4b.InitializeNewInstance("JPI4J2b", Null)
        pi4b.RunMethod("initializeContext", Null)
        pi4b.RunMethod("setB4JCallback", Array(Me))
            
        Log("Library version="&pi4b.RunMethod("getVersion", Null))      
End Sub

#region setup
    Sub initializeI2C(nBus As Int,numberDevices As Int)
        pi4b.RunMethod("initializeI2C", Array(nBus,numberDevices))
    End Sub

    Sub setI2CDevice(device As Int) As Int
        Dim HDevice As Int=pi4b.RunMethod("initializeDevice", Array(device))
        Return HDevice
    End Sub
 
    Sub InitSPI(chipselect As Int,address As Int,baudrate As Int)
        pi4b.RunMethod("initializeSPI", Array(chipselect, address, baudrate))
    End Sub
#End region setups

#Region I2Cdevice_without_register
    Sub ReadI2C(device As Int) As Byte'' read one byte from device
        Dim result As Byte=pi4b.RunMethod("readByte", Array(device))
        Return result
    End Sub
'
    Sub WriteI2C(device As Int, b As Byte)' write one byte to device
        pi4b.RunMethod("writeByte", Array(device,b))
    End Sub                        '

    Sub ReadBytesI2C(device As Int,Length As Int) As Byte()'' Read multiple bytes from device
        Dim result() As Byte=pi4b.RunMethod("readBytes", Array(device,Length))
        Return result
    End Sub

    Sub WriteBytesI2C(device As Int, bytes() As Byte)' Write multiple bytes to device
        pi4b.RunMethod("writeBytes", Array(device,bytes))
    End Sub                        '
#End Region I2Cdevice_without_register

#Region I2Cdevice_with_register
    Sub ReadRegisterI2C(device As Int,register As Int) As Byte 'Read one byte from register
        Dim result As Byte=pi4b.RunMethod("readRegister", Array(device,register))
        Return result
    End Sub

    Sub WriteRegisterI2C(device As Int,register As Int, b As Byte)' write one byte to register
        pi4b.RunMethod("writeRegister", Array(device,register,b))
    End Sub                  

    Sub ReadRegistersI2C(device As Int,register As Int,length As Int) As Byte() 'Read multiple bytes from register
        Dim result(length) As Byte
        result=pi4b.RunMethod("readRegisters", Array(device,register,length))
        Return result
    End Sub

    Sub WriteRegistersI2C(device As Int,register As Int, bytes() As Byte)' write multiple bytes to registers
        pi4b.RunMethod("writeRegisters", Array(device,register,bytes))
    End Sub                        '
#End Region I2Cdevice_with_register


#Region GPIO
    Sub initOutput(pin As Int)
         pi4b.RunMethod("setupOutputPin", Array(pin))
    End Sub

    Sub initInput(pin As Int,PullUp As Boolean)
        Dim PullResistance As JavaObject
        PullResistance.InitializeStatic("com.pi4j.io.gpio.digital.PullResistance")
        If PullUp Then
            pi4b.RunMethod("setupInputPinWithListener", Array(pin, PullResistance.GetField("PULL_UP")))
        Else
            pi4b.RunMethod("setupInputPinWithListener", Array(pin, PullResistance.GetField("PULL_DOWN")))
        End If
    End Sub
 
    Sub WritePin(pin As Int,value As Boolean)
        pi4b.RunMethod("writeOutputPin", Array(pin,value))
    End Sub

    Sub readInputPin(pin As Int) As Boolean
           Dim state As Boolean = pi4b.RunMethod("readInputPin", Array(pin))
        Return state
    End Sub
    Sub readOutputPin(pin As Int) As Boolean
           Dim state As Boolean = pi4b.RunMethod("readOutputPin", Array(pin))
        Return state
    End Sub
  
    Public Sub onpin_statechanged (changedPin As Int, state As String)
        Select Case state
        Case "HIGH"
            CallSub3(Main,"PinState",changedPin,True)
        Case "LOW"
            CallSub3(Main,"PinState",changedPin,False)
        End Select
    End Sub
#End Region GPIO

#Region SPI
    Sub writeSPI(data() As Byte)
        pi4b.RunMethod("writeSPI", Array(data))
    End Sub
 
    Sub readSPI(length As Int) As String
        Dim response() As Byte = pi4b.RunMethod("readSPI", Array(length))
        Return (BytesToString(response, 0, response.Length, "UTF8"))
    End Sub
#End Region SPI
 
Sub ClosePI4
    Try
        pi4b.RunMethod("close", Null)
    Catch
        Log("err close bus")
    End Try
End Sub

I am attaching the jar. The dependencies are those in the example, but you must pay attention to the fact that they must be those that correspond to versions 2.1.X of PI4J.

I hope it can be useful to someone.
 

Attachments

  • JPI4J2b.jar
    38.7 KB · Views: 83
Last edited:

MbedAndroid

Well-Known Member
Licensed User
Longtime User
Good work. I was trying your example
sorry to ask: but
B4X:
  Dim pi4 As PI4wrapper
?
i got now JPi4J2.jar installed + JPi4J2b.jar. But got the message PI4wrapper is unknown?
i'm missing something?
 

Jaume Guillem

Member
Licensed User
Longtime User
It is the name of the class. If you call it something else, just call it by your name. I have corrected the example.

JPi4J2.jar is not required
 

MbedAndroid

Well-Known Member
Licensed User
Longtime User
it wont run on a pi5. Also with the standard pi4j2 lib i'm getting this error Pi Init failed
pi@raspberrypi:~ $ sudo jdk11/bin/java -jar testgpio.jar
Hello world!!!
Feb 16, 2025 8:57:41 AM com.pi4j.Pi4J newAutoContext
INFO: New auto context
Feb 16, 2025 8:57:41 AM com.pi4j.Pi4J newContextBuilder
INFO: New context builder
Feb 16, 2025 8:57:41 AM com.pi4j.platform.impl.DefaultRuntimePlatforms add
INFO: adding platform to managed platform map [id=raspberrypi; name=RaspberryPi Platform; priority=5; class=com.pi4j.plugin.raspberrypi.platform.RaspberryPiPlatform]
Pi4J inicialized
Library version=V1.2 JGuillem 2025
Feb 16, 2025 8:57:41 AM com.pi4j.library.pigpio.impl.PiGpioBase validateResult
WARNING: PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed
java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy5.create(Unknown Source)
at com.pi4j.context.Context.create(Context.java:317)
at com.pi4j.internal.IOCreator.create(IOCreator.java:58)
at com.pi4j.internal.IOCreator.create(IOCreator.java:96)
at JPI4J2b.setupOutputPin(JPI4J2b.java:173)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at b4j.example.pi4wrapper._initoutput(pi4wrapper.java:90)
at b4j.example.main._start(main.java:80)
at b4j.example.main._appstart(main.java:45)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at b4j.example.main.main(main.java:28)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.pi4j.provider.impl.ProviderProxyHandler.invoke(ProviderProxyHandler.java:100)
... 20 more
Caused by: com.pi4j.library.pigpio.PiGpioException: PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed
at com.pi4j.library.pigpio.impl.PiGpioBase.validateResult(PiGpioBase.java:263)
at com.pi4j.library.pigpio.impl.PiGpioBase.validateResult(PiGpioBase.java:249)
at com.pi4j.library.pigpio.impl.PiGpioNativeImpl.gpioInitialise(PiGpioNativeImpl.java:95)
at com.pi4j.library.pigpio.PiGpio.initialize(PiGpio.java:146)
at com.pi4j.plugin.pigpio.provider.gpio.digital.PiGpioDigitalOutputProviderImpl.create(PiGpioDigitalOutputProviderImpl.java:60)
at com.pi4j.plugin.pigpio.provider.gpio.digital.PiGpioDigitalOutputProviderImpl.create(PiGpioDigitalOutputProviderImpl.java:41)
... 25 more
Feb 16, 2025 8:57:41 AM com.pi4j.library.pigpio.impl.PiGpioBase validateResult
WARNING: PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed
java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy5.create(Unknown Source)
at com.pi4j.context.Context.create(Context.java:317)
at com.pi4j.internal.IOCreator.create(IOCreator.java:58)
at com.pi4j.internal.IOCreator.create(IOCreator.java:96)
at JPI4J2b.setupOutputPin(JPI4J2b.java:173)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at b4j.example.pi4wrapper._initoutput(pi4wrapper.java:90)
at b4j.example.main._start(main.java:82)
at b4j.example.main._appstart(main.java:45)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at b4j.example.main.main(main.java:28)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.pi4j.provider.impl.ProviderProxyHandler.invoke(ProviderProxyHandler.java:100)
... 20 more
Caused by: com.pi4j.library.pigpio.PiGpioException: PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed
at com.pi4j.library.pigpio.impl.PiGpioBase.validateResult(PiGpioBase.java:263)
at com.pi4j.library.pigpio.impl.PiGpioBase.validateResult(PiGpioBase.java:249)
at com.pi4j.library.pigpio.impl.PiGpioNativeImpl.gpioInitialise(PiGpioNativeImpl.java:95)
at com.pi4j.library.pigpio.PiGpio.initialize(PiGpio.java:146)
at com.pi4j.plugin.pigpio.provider.gpio.digital.PiGpioDigitalOutputProviderImpl.create(PiGpioDigitalOutputProviderImpl.java:60)
at com.pi4j.plugin.pigpio.provider.gpio.digital.PiGpioDigitalOutputProviderImpl.create(PiGpioDigitalOutputProviderImpl.java:41)
... 25 more
Feb 16, 2025 8:57:41 AM com.pi4j.library.pigpio.impl.PiGpioBase validateResult
WARNING: PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed
pi4wrapper._initinput (java line: 79)
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at b4j.example.pi4wrapper._initinput(pi4wrapper.java:79)
at b4j.example.main._start(main.java:84)
at b4j.example.main._appstart(main.java:45)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at b4j.example.main.main(main.java:28)
Caused by: java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy8.create(Unknown Source)
at com.pi4j.context.Context.create(Context.java:317)
at com.pi4j.internal.IOCreator.create(IOCreator.java:58)
at com.pi4j.internal.IOCreator.create(IOCreator.java:106)
at JPI4J2b.setupInputPinWithListener(JPI4J2b.java:203)
... 15 more
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.pi4j.provider.impl.ProviderProxyHandler.invoke(ProviderProxyHandler.java:100)
... 20 more
Caused by: com.pi4j.library.pigpio.PiGpioException: PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed
at com.pi4j.library.pigpio.impl.PiGpioBase.validateResult(PiGpioBase.java:263)
at com.pi4j.library.pigpio.impl.PiGpioBase.validateResult(PiGpioBase.java:249)
at com.pi4j.library.pigpio.impl.PiGpioNativeImpl.gpioInitialise(PiGpioNativeImpl.java:95)
at com.pi4j.library.pigpio.PiGpio.initialize(PiGpio.java:146)
at com.pi4j.plugin.pigpio.provider.gpio.digital.PiGpioDigitalInputProviderImpl.create(PiGpioDigitalInputProviderImpl.java:60)
at com.pi4j.plugin.pigpio.provider.gpio.digital.PiGpioDigitalInputProviderImpl.create(PiGpioDigitalInputProviderImpl.java:41)
... 25 more

seems that a new lib is needed for the pi5?
 
Last edited:

Jaume Guillem

Member
Licensed User
Longtime User
I haven't tried it on a Raspberry 5. When I buy one I'll try it, and if it doesn't work, I'll write a new library, but with the Raspberry 4 it works perfectly, GPIOs, I2C and SPI, which is what I needed since not everything worked on the standart RPI4J2.
 

MbedAndroid

Well-Known Member
Licensed User
Longtime User
I haven't tried it on a Raspberry 5. When I buy one I'll try it, and if it doesn't work, I'll write a new library, but with the Raspberry 4 it works perfectly, GPIOs, I2C and SPI, which is what I needed since not everything worked on the standart RPI4J2.
 
Top