0

I am trying to run java code on a Raspberry Pi model 3, downloaded from a PC eclipse development environment to access a 9DoF device on the I2C bus using the pi4j library. I get the following error:

java -classpath .:classes:/opt/pi4j/lib/'*' -jar /home/pi
/artifacts/RPITank-1.0-SNAPSHOT.jar Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: com/pi4j/io/i2c/I2CFa
ctory$UnsupportedBusNumberException at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) at java.lang.Class.privateGetMethodRecursive(Class.java:3048) at java.lang.Class.getMethod0(Class.java:3018) at java.lang.Class.getMethod(Class.java:1784) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544 ) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526) Caused by: java.lang.ClassNotFoundException: com.pi4j.io.i2c.I2CFactory$Unsuppor
tedBusNumberException at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 7 more

This is the code

package main;

import java.io.IOException;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CFactory;

import devices.I2C.Pi4jI2CDevice;
import devices.sensorImplementations.MPU9250.MPU9250;

public class MPU9250Test {

    public static void main(String[] args)
    {
        I2CBus bus = null;
        System.out.println("Attempt to get Bus 1");
        try {
            final GpioController gpio = GpioFactory.getInstance();
            bus = I2CFactory.getInstance(I2CBus.BUS_1); 
            System.out.println("Got Bus, create devices");
            MPU9250 mpu9250 = new MPU9250(
                    new Pi4jI2CDevice(bus.getDevice(0x68)), // MPU9250 I2C device
                    new Pi4jI2CDevice(bus.getDevice(0x0C)), // ak8963 I2C 
                    100,                                    // sample rate
                    100);                                   // sample size
            Thread sensor = new Thread(mpu9250);
            sensor.start();

            Thread.sleep(10000);

            sensor.interrupt();

            for(int i = mpu9250.getAccelerometerReadingCount() -1; i>0; i--)
            {
                System.out.print("G: " + mpu9250.getRotationalAcceleration(i).toString());
                System.out.print(" A: " + mpu9250.getAcceleration(i).toString());
                System.out.println(" M: " + mpu9250.getGaussianData(i).toString());
            }
        } catch (I2CFactory.UnsupportedBusNumberException | InterruptedException | IOException e) {
            e.printStackTrace();
        }
    }

}

I have checked that the device is visible on bus 1 using I2Cdetect -y 1, this shows a device at address 0x68 and 0x76.

I don't know if this is a problem with the execution environment or the code, any help would be welcome.

Further experimentation shows removing the exception handler isn't an option this is required at compile time. The exception class is described here http://pi4j.com/apidocs/com/pi4j/io/i2c/I2CFactory.UnsupportedBusNumberException.html

yglodt
  • 13,807
  • 14
  • 91
  • 127
gjwo
  • 175
  • 13
  • Caused by: java.lang.ClassNotFoundException: com.pi4j.io.i2c.I2CFactory$Unsuppor tedBusNumberException - Check you have that class in your classpath – gile Oct 27 '16 at 14:42
  • java -classpath .:classes:/opt/pi4j/lib/'*' -jar /home/pi this includes the pi4j libraries – gjwo Oct 27 '16 at 17:18
  • Both the Eclipse project .pom file and the RPi have been updated to use pi4j 1.2-SNAPSHOT, this had no effect on the result. – gjwo Oct 28 '16 at 08:26
  • All GPIO controller & GPIO factory lines commented out as they are not required, no change to result. The code would appear to be failing before the first println, i.e. during imports. – gjwo Oct 28 '16 at 08:32

1 Answers1

2

The issue was that the project jar when transferred to the Raspberry Pi was not picking up its runtime links to the pi4j software preinstalled on the RPi the problem was solved via an issue on github here thanks to natdan.

The changes made to the project pom.xml were as follows:

Add the run time dependency to the dependencies

<dependencies>
<dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-core</artifactId>
    <version>1.2-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-native</artifactId>
    <version>1.2-SNAPSHOT</version>
    <classifier>raspberrypi-dynamic</classifier>
    <type>so</type>
</dependency>

After further experimentation it turned out that this dependency was not required after all, so ignore the section above.

The class path was then added to the maven jar plugin configuration as a manifest entry:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.0.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <!--<classpathPrefix>${pi.pi4j.Directory}/</classpathPrefix>-->
                        <mainClass>${pi.main.class}</mainClass>
                    </manifest>
                    <manifestEntries>
                        <!-- Add the pi4j in runtime. -->
                        <Class-Path>${pi.pi4j.Directory}/pi4j-core.jar</Class-Path>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>

finally the classpath was removed from the java command in the antrun section

                            <!-- run the JAR file on the Raspberry Pi -->
                            <sshexec host="${pi.host}" port="${pi.port}" username="${pi.user}"
                                password="${pi.password}" trust="true" failonerror="false"
                                verbose="true"
                                command="java -jar ${pi.deployDirectory}/${project.build.finalName}.jar" />
gjwo
  • 175
  • 13