How to implement a LowPass Filter for the accelerometer?

Hi, 
I'm trying to implement a low pass filter for all 3 axis of the accelerometer.  For the moment I'm just trying to do it for the z-axis, however with very little success. Here is the Builder sequence I use:

           DataProcessorController=(DataProcessor)this.MwController.getModuleController(Module.DATA_PROCESSOR);
            DataProcessorController.removeAllFilters();
            DataProcessorController.addFilter(LoggingTrigger.ACCELEROMETER_Z_AXIS, new FilterConfigBuilder.LowPassBuilder()
                    .withSampleSize((byte)10)
                    .withInputSize((byte)2)
                    .withOutputSize((byte)2)
                    .build());

However when I look at the data it seems to be just noise. I could'n find an example. What are the correct parameters for the LowPassBuilder?

Comments

  • What version of the firmware are you running?  I believe the DataProcessor and LowPass filter were added in v0.8.6.

    Those parameters look fine to me.  Do you have any recorded values that we can take a look at?
  • edited December 2014
    I'm using firmware v.0.86.

    After some more testing it actually seems that the filter might work ok but that there was a problem with the data readout. 

    This is what I did in the read out callback:

    public void receivedFilterOutput(byte filterId, byte[] data) {
            short z_= (short)(ByteBuffer.wrap(data, 0, 2).order(ByteOrder.LITTLE_ENDIAN).getShort());

      byte[] config= samplingConfig.getBytes();
            float z= BytesInterpreter.bytesToGs(config, z_);
           ...
    }

    To make it work I had to add this transformation to  z_ before transforming it to a float:
     z_=z_>0?(short)(-z_+Short.MAX_VALUE):(short)(-z_-Short.MAX_VALUE);

    What is the correct way to interpret the output data from the filter? Am I doing something wrong in the interpretation of the output data or is this a bug? I would like to chain the low pass filter with other filters but now I'm not sure if I can trust the output of the low pass filter to be correct. The above read out works fine for a math filter for example without the sign transformation. 


  • ... 

    I chained a Math filter multiplying the output of the lowpass filter with 2 and this also fixes the problem. Meaning that I don't need the sign transformation to get meaningful data.  

    PS. Does not work if I just multiply by 1. 
  • edited December 2014
    Hrm...looks like the low pass filter does not handle signed inputs, which some of the other filters do (comparator, math, rms).  Let me confirm this with the firmware dev.
  • As mentioned earlier I would like to apply the lowpass filter to the three axis of the accelerometer simultaneously to than pass it to the RMS filter. Now I did realise however that the input size for the low pass filter  is limited to 4 bytes. Is it at all possible to pass the three axis simultaneously to a low pass filter? 

    My idea was to define  an accelerometer Trigger:

    ACCELEROMETER {
            @Override public Register register() { return Accelerometer.Register.DATA_VALUE; }
            @Override public byte offset() { return 0; }
            @Override public byte length() { return 6; }
        };

    and than use this for adding the filter:
        
    dataProcessorController.addFilter(LoggingTrigger.ACCELEROMETER, new FilterConfigBuilder.LowPassBuilder()
                        .withSampleSize((byte)32)
                        .withInputSize((byte)6)
                        .withOutputSize((byte)6)
                        .build());

    However given that the .withInputSize is limited to [1, 4] this does not work I suppose.
    Is there another way?
  • Would the RMS filter be something that you can use instead?
  • What I'm trying to do here is accumulating low frequency movements with the following chain:

    LowPassFilter (Accelerometer) > get rid of high frequency movements
    RMS > get amount of instantaneous low frequency movement
    Accumulate > get accumulated low frequency movement
    TimeDelay > notify or store on device (10 min)

    It's essential to have the low pass filter before the RMS so the high frequency oscillations cancel out. 

    At the moment I'm doing it on the raw accelerometer data on the phone. This is working fine. Would however be nice to be phone independent. I was considering doing separate chains for each accelerometer axis. Form what I understand from the API this should be possible. However I suppose I'm getting close to the computational capacity of the sensors processor. Besides the updated frequency, I'm not sure how to handle the high numbers I get from the accumulator filter with just two bytes. Any suggestions are welcomed.




  • Mm, unfortunately I don't think we can do what you want solely on the firmware at this time.  I'll ping the firmware dev again about enhancements to the low pass filter, possibly making it more like the RMS filter, in its ability to perform a computation on an array of inputs.

    The accelerometer does have a high pass filter mode that we use in the MetaTracker app (http://projects.mbientlab.com/metatracker-ios-app-turns-your-metawear-into-a-fitness-tracker/).  It may not be exactly what you are looking for but might be of some use to you.
This discussion has been closed.