AXDL345_I2C java problems

Our team has been trying to solve an issue with our accelerometer in Java. We have been able to get it to work on LabView and on an Arduino, but we are having problems on getting it to work in Java, while using an 8-slot CRIO. We think the issue might be an older CRIO that is not compatible with the I2C support on the latest Java libraries, but we can’t test it on the newer CRIO because it is currently sealed in our bag. Do you know of any support sites for this Java library, or have any information about the compatibility with the older CRIO?

What kind of issues are you having? I was able to get that accelerometer working earlier in the season on our test bed (which is an 8-slot cRIO) without a problem.

We are not able to read values from the accelerometer although we are able to do so on the arduino as well as through the labview sample code.

Are you getting nonsensical values? Are you getting some sort of exception? I don’t really know what problem you’re having.

As a reference, we initialized the accelerometer like this:

ADXL345_I2C _accelerometer = new ADXL345_I2C(1,ADXL345_I2C.DataFormat_Range.k2G);

and read from it like this:

double yAccel = _accelerometer.getAcceleration(ADXL345_I2C.Axes.kY);

We pretty much have the same code as you have posted, I currently do not have access to it at the moment so I cant post it. But our main problem is that when we do output the axes values it returns a 0 which we are assuming is nothing being returned at all. We stuck a probe into it just to see if it was getting data and it was sending the right address I presume “0x3A” as well as NACK’s and are confused as to why.

thanks for trying to help us

One difference is we didn’t try k2G when we initialized it. We tried k4G and k16G, but neither of those worked for us. Any pointers to docs on what those values mean?

Here’s the datasheet. The k2G, k4G etc. tell the accelerometer what value should be counted as 1 (k1G being normal gravitational acceleration, k2G being twice that, etc.).

It is still not working

Here is the code

package edu.wpi.first.wpilibj.templates;

import edu.wpi.first.wpilibj.ADXL345_I2C;
import edu.wpi.first.wpilibj.DriverStationLCD;
import edu.wpi.first.wpilibj.SimpleRobot;
import edu.wpi.first.wpilibj.Timer;
import java.util.Date;

public class RobotTemplate extends SimpleRobot {

ADXL345_I2C accelerometer;

public RobotTemplate()
{
    DriverStationLCD.getInstance().println(DriverStationLCD.Line.kUser2, 1, "Initializing...");
    DriverStationLCD.getInstance().updateLCD();
    // erase the line before the next time it gets called
    DriverStationLCD.getInstance().println(DriverStationLCD.Line.kUser2, 1, "               ");

}

/**
 * This function is called once each time the robot enters autonomous mode.
 */
public void autonomous() {

    Timer.delay(0.05);
}

/**
 * This function is called once each time the robot enters operator control.
 */
public void operatorControl() {
    
    accelerometer = new ADXL345_I2C(1, ADXL345_I2C.DataFormat_Range.k2G);

// I2C i2c = accelerometer.getI2C();
// if (i2c.addressOnly()) {
// DriverStationLCD.getInstance().println(DriverStationLCD.Line.kUser3, 1, “No Data”);
// DriverStationLCD.getInstance().println(DriverStationLCD.Line.kUser4, 1, “”);
// }

    DriverStationLCD lcd = DriverStationLCD.getInstance();

// lcd.println(DriverStationLCD.Line.kUser1, 1, (new Date()).toString());
// lcd.println(DriverStationLCD.Line.kUser2, 1, “Starting operator control”);
// lcd.updateLCD();

    //this.getWatchdog().setEnabled(false);
    while(true) {

        double x = accelerometer.getAcceleration(ADXL345_I2C.Axes.kX);
        double y = accelerometer.getAcceleration(ADXL345_I2C.Axes.kY);
        double z = accelerometer.getAcceleration(ADXL345_I2C.Axes.kZ);
    
        lcd.println(DriverStationLCD.Line.kUser1, 1, (new Date()).toString());
        lcd.println(DriverStationLCD.Line.kUser2, 1, "X: " + x);
        lcd.println(DriverStationLCD.Line.kUser3, 1, "Y: " + y);
        lcd.println(DriverStationLCD.Line.kUser4, 1, "Z: " + z);
        lcd.updateLCD();

        Timer.delay(0.05);
    }
}

}

My recommendation is that you call SetCompatibilityMode(true); on the I2C object.

-Joe

Thanks setting Compatitbilitymode(true) solved our problems and we are now getting back values. We had to go into the wpilibj source and change the ADXL_345 class file and recompile it

Joe,

Could you explain exactly what SetCompatabilityMode does? That corrected a sporatic communication issue I had with an Arduino as well and I would like to understand why. The documentation is, shall we say, sketchy.

Thanks,
Mike

Hi Mike,

The Digital I/O from the 9403 module is registered… meaning it takes several clock cycles in the FPGA for a digital write to be read back in. When using I2C over an interface like this, that means that the checking for clock skewing is expensive time-wise. As a result, the I2C implementation in the FPGA attempts to optimize this by only checking for clock skewing in “typical” parts of the waveform. Of course in the I2C spec, devices are allowed to skew the clock almost anywhere. The compatibility mode checks for clock skewing everywhere required by the spec and is thus “compatible” with that spec. The result is that your I2C transfer speed is slower (if I recall transactions take approx 60% longer), but you can talk to any I2C device, not just “typical sensors”.

I hope this clears up any gaps in the documentation (are you talking about WPILibJ doxygen?).

Cheers,
-Joe

Thanks Joe! That description really helps a lot, both in understanding why SetCompatabilityMode works and why it was set up the way it was. As for the documentation, I’m assuming it was the WPILibJ, but as I don’t have the team laptop, I’m not positive. I just remember it saying something like the funtion “enables compatibility mode”.

Thanks,
Mike