Announcement

Collapse
No announcement yet.

How to detect if i2cDeviceSync's readTimeStamped and write functions fail?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to detect if i2cDeviceSync's readTimeStamped and write functions fail?

    While working on communication to an I2C device via the i2cDeviceSync class, it's not clear from the documentation how the calling code can know if the call to readTimeStamped() [if reading data] or write() [if writing data] methods succeeded or not. The goal is to be able to reliably detect cases where the i2c device has become disconnected.

    At this point, it appears if the data values returned from readTimeStamped() are all zeros, this indicates a failure. That's not exactly deterministic, is there another way to deterministically detect that an error occured?

    And what about write()? If the i2c device doesn't exist when the write occurs, how would the calling code deterministically detect this?

  • #2
    Your observations are valid. At the moment, I don't think there's any way for the caller to deterministically detect failure. I do agree that such functionality would be good though. I'll pass this along to the SDK devs.

    Comment


    • #3
      Thanks! I have a few more notes that might be helpful.

      After reviewing the 2019 Skystone sources for the i2cSynchDevice, there does appear to be a HardwareDeviceHealth mechanism, but after review it it appears it is not fully integrated. I found code that would set it's value to UNHEALTHY, but the code that calls this function for cases like this passes in a null object reference for the object that would be updated - and I could not find any code that ever restored the HealthStatus back to the state of being HEALTHY, which one would expect when communication occurred successfully again. Perhaps there's something I've missed, but I don't think that implementation sufficient for determining communication failure.

      Comment


      • #4
        The status is restored to healthy on the next successful operation (notice the call to setHealthyIfArmed):

        Code:
        // Return real data if we've got it
        if (result.data.length == creg)
        {
            readStatusQueryPlaceholder.reset();
            readHistory.addToHistoryQueue(result);
            setHealthyIfArmed();
            return result;
        }
        But yeah, the current way it works is less than ideal. The problem really is that I2C is quite different from e.g. USB: there's no enumeration. The only way to know if a device is "there" would be to continually ping it, which would be bad for many reasons. Having a return code, out param, or checked exception to indicate success/failure for the operation would be good.

        Comment


        • #5
          > setHealtyIfArmed();

          Thanks, I missed that part. However see below, there's still a problem I believe.

          > But yeah, the current way it works is less than ideal.

          I'm thinking the health state can never be set during an I2C transaction to UNHEALTHY, because the code in i2cDeviceSyncImpl.java (in the robotcore library) for the method public TimestampedData readTimeStamped(int ireg, int creg) invokes:

          TimestampedI2cData.makeFakeData(null, getI2cAddress(), ireg, creg);

          The "null" in this invocation is supposed to be a HardwareDeviceHealth object. But because it's null, TimesampedI2cData's makeFakeData() method can't update the status to UNHEALTHY in the first place.

          Comment


          • #6
            Originally posted by slibert2017 View Post
            > setHealtyIfArmed();

            Thanks, I missed that part. However see below, there's still a problem I believe.

            > But yeah, the current way it works is less than ideal.

            I'm thinking the health state can never be set during an I2C transaction to UNHEALTHY, because the code in i2cDeviceSyncImpl.java (in the robotcore library) for the method public TimestampedData readTimeStamped(int ireg, int creg) invokes:

            TimestampedI2cData.makeFakeData(null, getI2cAddress(), ireg, creg);

            The "null" in this invocation is supposed to be a HardwareDeviceHealth object. But because it's null, TimesampedI2cData's makeFakeData() method can't update the status to UNHEALTHY in the first place.
            You're looking at the Modern Robotics CDIM code, not the ExH code. Take a look at LynxI2cDeviceSynch.


            Code:
            return readStatusQueryPlaceholder.log(TimestampedI2cData.makeFakeData(deviceHavingProblems, i2cAddr, ireg, creg));

            Comment


            • #7
              > Take a look at LynxI2cDeviceSynch.

              Ah, thanks. So it's implemented for Lynx, which I understand is the only option for next season.

              So it seems like the deterministic way is to mark the device's HardwareDeviceHealth to "HEALTHY" (if it's not already), execute readTimeStamped. If it's not UNHEALTHY, then no exceptional conditions were detected during the read. I think that should work, let me know if I'm missing something obvious.

              Comment


              • #8
                Originally posted by slibert2017 View Post
                > Take a look at LynxI2cDeviceSynch.

                Ah, thanks. So it's implemented for Lynx, which I understand is the only option for next season.

                So it seems like the deterministic way is to mark the device's HardwareDeviceHealth to "HEALTHY" (if it's not already), execute readTimeStamped. If it's not UNHEALTHY, then no exceptional conditions were detected during the read. I think that should work, let me know if I'm missing something obvious.
                I think that would work. Again, I'll see if a better way can be integrated into a future SDK release

                Comment

                Working...
                X