1 Reply Latest reply on Oct 30, 2018 9:21 PM by 2833902

    Transactional versus CombinedMessage

    2833902

      Hi,

       

      I am trying to understand the semantic differences (if any) between using a Transactional Device and a *CombinedMessage (on the I2C or SPI bus).

       

      The reason I ask is because I am trying to interact with a sensor (the MPU6050 accelerometer/gyroscope/thermometer sensor) which stores measurements in two 1-byte registers (one of which is the MSB and the other the LSB). Those registers are updated at whatever sampling rate has been configured in the sensor and each value can be built by concatenating the two bytes yielding a twos-complement number (effectively a short in the Java world).

       

      Now, the catch is this: As mentioned, the sensor will keep updating those registers at the sampling rate and it becomes the app's responsibility to ensure that that both reads from both registers come from the same sampling instant so that we don't get into a situation where register A's value is from sampling instant #1 and register B's from instant #2. The datasheet suggests two ways of achieving that..you can either keep checking an "interrupt" pin and read the values when that's turned on or you must read both registers whilst the serial bus is busy (i.e. if this is the I2C bus, both reads happen between the "start" and "stop" sequences). So effectively, the bus acts as a lock whose "busy-ness" prevents the sensor from updating the registers.

       

      If I understood correctly from reading the documentation two ways of implementing that is by using either a Transactional Device or a I2CCombinedMessage (MPU6050 only supports I2C access). The former is not an option on the RasPi platform which I am using, as the following code (mpu6050 is a I2CDevice instance):

       

      if (mpu6050 instanceof Transactional) {

               System.out.println("Device transactional");

      } else {

               System.out.println("Device not transactional");

      }

       

      prints: "Device not transactional"

       

      I can implement that using the CombinedMessage approach but I was wondering..is there a semantic difference between the two approaches? i.e. if a Device supports the Transactional interface why would one choose one over the other?

       

      Any input?

       

      Thanks

        • 1. Re: Transactional versus CombinedMessage
          2833902

          To partially answer myself on this, one difference I suppose,  is that with the Transactional way only one device can be used whereas with the I2CCombinedMessage multiple devices can be used..

           

          In any case if this is of any interest to anyone, here are some of my findings after experimenting  for a bit with this sensor:

           

          As you will can read on the datasheet, the sampling rate can be configured by tweaking the SMPRT_DIV register slightly (assuming the DLPF is disabled (DLPF_CFG = 0 or 7)) or by enabling the DLPF filter in DLPF_CFG.

          Let's assume we just tweak SMPRT_DIV for now...if the default value (0) is used then that will result in a sampling rate of 8KHz. Don't even think of specifying that rate and enabling interrupts for each sampling event hoping you will read every single one of them...the runtime dies almost instantly with the following error (note how two queues are alternating when buffering events):

           

          [CRITICAL] [EVENTS] iso=1:**event queue 2 full, dropping event

          [CRITICAL] [EVENTS] iso=2:**event queue 1 full, dropping event

           

          (Also, a kworker process on the Ras Pi seems to be keeping itself rather busy..)

           

          By the way, you may see that error message on the NetBeans console but then again you may not if it the process dies too fast...the most surefire way to see that is by ams-install-ing and ams-run-ing the app manually..

           

          So, what sampling rate does work then? By experimenting a bit I found that 1KHz won't crash the runtime..however, depending on what you do with that sampling event it may or may not crash the application..

           

          According to the datasheet, every time a sampling event is generated, depending on the value of bit 5 of the INT_PIN_CFG register the sensor will emit a pulse of 50 microseconds on the INT pin to manifest the event (value 0)...I'm not entirely sure, but my guess is that this is way too fast for the Ras Pi and the Java runtime to pick up..however, some events do get picked-up (perhaps when the INT pin is high when the Ras Pie's own driver happens to sample the pin..?) so if you register a listener that simply keeps an event count you should be able to see a number > 0 after a while..a far more pragmatic option however, is to set bit 5 of the INT_PIN_CFG to "high" which means that the INT pin will be held high until the interrupt is cleared..(exactly how interrupts are cleared is controlled by pin 4 in the same register, please see datasheet for more info on this).

           

          So, assuming we hold the INT pin "high" until the interrupt is cleared, will that work? Afraid, not.. Trying to read some register value without introducing a small delay results in the following exception:

           

          Caused by: java.io.IOException: Driver reported error

           

          And by the way, because we're now using interrupts (and manually clearing them), we can safely read the measurement registers "serially" i.e. the bus doesn't have to be kept busy to get values from the same sampling instance (please, see initial post).

           

          The only way to prevent the above exception from happening is by introducing a small delay between successive register reads in a listener (which in turn will of course increase the overall frequency of sampling events). That doesn't mean it won't happen at all though...just that it won't happen instantly..

           

          In case this is of any interest this is some sample code that shows one way of  accessing this sensor https://github.com/j-mbd/short-and-quick/tree/master/src/jmbd/i2c/mpu6050

           

          (Tested on Raspberry Pi 2, Model B, running the 8.3 SDK)