Metawear R - Tap Detection

edited October 2015 in General
I've been prototyping a project using the Metawear R and I'm running into a wall and could use a little advice.

My Metawear is kept in a ultra thin custom printed case which features a thin triangular tip at one end and what is essentially a sleeve that the Metawear fits in at the other end. The micro usb port sticks out of the open end of the case. Something like the terrible ASCII drawing below (not to scale obviously).

One of the primary functions of the device is to detect when the user taps the tip in either an upwards or downwards motion.

The accelerometer on the Metawear R will produce tap events, and there is a polarity to them which seems to correspond to a negative or positive tap direction on the z-axis. This isn't overly well documented in the SDKs but my own experimentation seems to lead me to believe this to be true. This is called polarity in the android sdk. The iOS sdk doesn't seem to report a polarity but the obj that the notification handler receives seems to contain two possible strings and the one that contains a "<c4>" happens at the same time as positive polarity events occur in the android sdk so that's what I'm using for iOS. Based on what I've seen a POSITIVE tap indicates a downward motion while a NEGATIVE tap indicates an upward motion.

This tap detection works great if you are tapping near the accelerometer. Unfortunately the accelerometer is near the end with the micro usb port and the tap polarity goes haywire the further from it that the tap occurs. The polarity of the tap events produced by the accelerometer seem almost random when striking the tip of my device. Perhaps the polarity isn't meant to be used for this purpose? 

I've attempted to write my own algorithms for tap detection which I derived from some research I discovered online but I'm having very little success. This basically boils down to looking for particular spikes on the z-axis over short periods of time. Again, the pattern on these seems inconsistent at best or I've screwed up somewhere that isn't obvious to me.

I've also tried graphing the accelerometer data while tapping the device to see if I could discern a pattern that I could then detect programatically but that hasn't worked either.

I'm running the accelerometer at 50HZ, at 8G max range with the high pass filter on and the high pass cutoff frequency set to low. Are there settings that are better for this?

I'm hoping there is a simple solution to this that I'm overlooking or someone else out there has done something similar and can point me in the right direction. If nothing else, a link to some solid research into tap detection would be delightful. My google searching has not produced many useful results.

Any help would be greatly appreciated,

  --[-]----                   <--- usb and accelerometer at this end
-|          |-
-|          |-
-|          |-
     \--/                     <--- tapping on this end


  • You can checkout the application notes provided by Free Scale regarding tap detection.  The pdf provides some explanation on how they implemented tap detection on the MMA8452Q accelerometer, which is the sensor on the MetaWear R board.

    On Android, what does the "crossedThreshold" function return when you are tapping on the tip of your device?  Its possible the tap threshold isn't even crossed at that range.  Also, what tap detection parameters are you using, if not the default settings?
  • edited October 2015
    Hi Eric, thanks for taking the time to respond.

    I'll take a look at that PDF to see if I can figure out what I'm doing wrong.

    The crossedThreshold function returns true when tapping my device. I've noticed that I receive far more tap events from my ios implementation. The android implementation seems less reliable... or that could all be in my head.

    I'm configuring and starting the accelerometer like this on android:

        mMma = mwBoard.getModule(Mma8452qAccelerometer.class);
        mMma.configureAxisSampling().enableHighPassFilter((byte) 3)
                .onComplete(new AsyncOperation.CompletionHandler<RouteManager>() {
                    public void success(RouteManager result) {
                        result.subscribe("mmTap", new RouteManager.MessageHandler() {
                            public void process(Message message) {
                                // ... 

This discussion has been closed.