Only Y axis filtered from Accelerometer

I need to check the sensor inclination.If the inclination is over 45° i need to do samethink.
I read the accelerometer with :

    accelModule.routeData()
    .fromAxes()
    .stream("accelSub")/*.log("accelLogger")*/
    .commit()
    .onComplete(new CompletionHandler<RouteManager>() {
        @Override
        public void success(RouteManager result) {
            result.subscribe("accelSub", new RouteManager.MessageHandler() {
                @Override
                public void process(Message msg) {
                    final CartesianShort axisData = msg.getData(CartesianShort.class);
                    int inclination = (int) (axisData.y()/11.41);
                    String val = String.format("%s %d°", axisData.toString(),inclination);
                    Log.i("test", "Stream: "+val);
                }
            });

            .......
        }

    });
Ok, work fine. But i would like to filter the data under 45° because i think this limit battery usage.
I try to read acceletometer only for the Y axies,(because i read the Comparison is not possibile on all axies), with fromYAxis but the value is very different.
                   accelModule.routeData()
                           .fromYAxis()
                           .process(new Comparison(Comparison.Operation.GTE, 500))
                           .stream("accelSub")
                           /*.log("accelLogger")*/
                           .commit()
                           .onComplete(new CompletionHandler<RouteManager>() {
                               @Override
                               public void success(RouteManager result) {
                                   result.subscribe("accelSub", new RouteManager.MessageHandler() {
                                       @Override
                                       public void process(Message msg) {

                                           Bmi160SingleAxisMessage bmi160Msg= (Bmi160SingleAxisMessage) msg;
                                           Log.i("test","SingleAxisMessage Y = "+msg.getData(Float.class));

                                       }
                                   });

                                   .....
                               }
                           });
If i read CartesianShort with fromAxes the Y is beetween 0 - 1030
but if i read Bmi160SingleAxisMessage with fromYAxis the interval is 500 (correct because i Comparison it) - 49000
Same one have an explanation or same suggestions

Comments

  • edited May 2016
    It appears that the filter is returning both Y and Z axis data as opposed to only Y axis.  You can compute the Y axis value yourself from the byte data.


    result.subscribe("accelSub", new RouteManager.MessageHandler() {
        @Override
        public void process(Message msg) {
            Bmi160SingleAxisMessage bmi160Msg= (Bmi160SingleAxisMessage) msg;
            short unscaled= (short) (bmi160Msg.getData()[0] | (bmi160Msg.getData()[1] << 8));
            Log.i("test", "Y-Axis= " + (unscaled / bmi160Msg.getScale()));
        }
    });
    
  • Thanks Eric for your answer.

    I understand there is a little bug and the API return Y and Z value instead only Y.

    But in this way the (unscaled / bmi160Msg.getScale()) is often a low value.
    If i don't move the sensor, Y value are same time correct, and same time very low (under 0).
    In fromAxes this not occur. The read is more accurate.

    With fromYAxis() i cannot you the
    process(new Comparison(Comparison.Operation.GTE, 500))
    because, i imagine, the comparison is with YZ value and not only on Y axies.
    Correct ?
    But i want to limit only Y.

    I start to think it's not possible, to actual firmware version, to use fromYAxis for limit the information transmitted on BT.


  • Hrm, yes I believe your hypothesis is correct about comparing a YZ value.  What you can do to work around this is in the meantime is to attach a Maths processor that adds 0 before you compare it.

    accelCtrllr.routeData().fromYAxis()
    .process(new Maths(Maths.Operation.ADD, 0))
    .process(new Comparison(Comparison.Operation.LTE, -0.8))
    Also, the acceleration units are g, not mg; your value should be 0.5 not 500. Lastly, set the axis sampling range before you construct the data processing chain.
  • Thanks Eric, but i solution is not very good.

    I don't know if i understand well "set the axis sampling range before you construct the data processing chain".

    My source is :



    accelModule.routeData()
    .fromYAxis()
    .process(new Maths(Maths.Operation.ADD, 0))
    .process(new Comparison(Comparison.Operation.LTE, 0.5))
    .stream("accelSub")
    .commit()
    .onComplete(new CompletionHandler() {
    @Override
    public void success(RouteManager result) {

    result.subscribe("accelSub", new RouteManager.MessageHandler() {
    @Override
    public void process(Message msg) {
    try {
    Bmi160SingleAxisMessage bmi160Msg = (Bmi160SingleAxisMessage) msg;
    short unscaled = (short) (bmi160Msg.getData()[0] | (bmi160Msg.getData()[1] << 8));

    final Float yAxisData = (unscaled / bmi160Msg.getScale()) * 1000;
    int inclination = (int) (yAxisData / 11.41);
    String val = String.format("%f %d°", yAxisData, inclination);
    Log.i("test", "Stream: " + val);
    ((TextView) findViewById(R.id.textView3)).setText(val);

    }catch (Exception ex) {
    Log.e("test","Error in CompletionHandler process : ",ex);
    ex.printStackTrace();
    }
    }
    });

    accelModule.setOutputDataRate(50.f);

    accelSetup = true;
    loggingModule.startLogging();

    accelModule.enableAxisSampling();
    accelModule.start();
    }

    @Override
    public void failure(Throwable error) {
    Log.e("test", "Error committing route", error);
    accelSetup = false;
    }
    });

    In this way i received often many Y-axis zero, this not occur if i use fromAxes.

    Have you a forecast or the new firmware upgrade with the corrected fromYAxis() ?


    • What is not good about my solution?  Of course it's not ideal but this is what you have to do to temporarily work around the issue
    • There is a function called setAxisSamplingRange for the Accelerometer class.
    • You don't need the byte manipulation code using the workaround nor do you need to cast the msg object.  You can revert your code to getting the data as a float.
    • You cannot use a comparator with the entire XYZ acceleration data (fromAxes), only with the individual axis (fromXAxis).
    • It has been filed in our bug tracker but there is no timetable for addressing this issue.
  • Thank you very much, Erik,
       i remove the bit manipulation and cast the data to a float, and now all work very well.
    I update the code if same one need it in the future :
    accelModule.routeData()
    .fromYAxis()
    .process(new Maths(Maths.Operation.ADD, 0))
    .process(new Comparison(Comparison.Operation.LTE, 0.5))
    .stream("accelSub")
    .commit()
    .onComplete(new CompletionHandler<RouteManager>() {
    @Override
    public void success(RouteManager result) {

    result.subscribe("accelSub", new RouteManager.MessageHandler() {
    @Override
    public void process(Message msg) {
    try {
    Float yAxisData = msg.getData(Float.class) *1000 -40;
    int inclination = (int) (yAxisData / 10.86);
    String val = String.format("%f %d°", yAxisData, inclination);
    Log.i("test", "Stream: " + val);
    ((TextView) findViewById(R.id.textView3)).setText(val);

    }catch (Exception ex) {
    Log.e("test","Error in CompletionHandler process : ",ex);
    ex.printStackTrace();
    }
    }
    });

    accelModule.setOutputDataRate(50.f);

    accelSetup = true;
    loggingModule.startLogging();

    accelModule.enableAxisSampling();
    accelModule.start();
    }

    @Override
    public void failure(Throwable error) {
    Log.e("test", "Error committing route", error);
    accelSetup = false;
    }
    });
    Thanks for your support again.
This discussion has been closed.