Pedometer count issue and question

Posted on
  • Edit: see here http://forum.espruino.com/conversations/­345754/

    Hi,

    I am using the pedometer widget.
    The step count is always much too high, it counts simple arm movement as steps. Is the calculation done in the widget or in the firmware? Or do the steps come from the watch?

    In the current state it is not of much use, unfortunately.

    Thanks
    Christian

  • The step counting is done in firmware, based on whether the total acceleration goes above/below 1G. This is what most devices seem to do.

    You can however set the threshold with http://www.espruino.com/Reference#l_Bang­le_setOptions stepCounterThresholdLow/High so you could tweak it to your needs

  • Where would I set this option, or all other options, if necessary?
    Directly in the code of the app/widget?

    Would it make sense to include an options page in the settings (or create a new app for setting this options)? Or do they get lost after closing the app?

    I would volunteer to start developing such a thing, if it makes sense.

  • To start with, you can connect the Espruino WebIDE to your Bangle JS and update settings from the IDE and see which value works for you...

    You could add a incrementer/decrementer feature in Settings app too.

    I am currently waiting to map the movements it records for non-walk vs. walk, then will filter out non-walk movements in my custom app. The 'Step' event at default settings is a good filter for the firehose of data provided by the 'accel' event :-).

  • How do you set the options for pedometer?
    Somehow like that, but how do I put it together?

    Bangle.setOptions({wakeOnTwist:false,ste­pCounterThresholdLow:X,stepCounterThresh­oldHigh:Y})
    X=sqr(8192-80)
    Y=sqr(8192+80)
    
  • Yes, but just define the variables before you use them :)

    function setStepSensitivity(s) {
      function sqr(x) { return x*x; }
      var X=sqr(8192-s);
      var Y=sqr(8192+s);
      Bangle.setOptions({stepCounterThresholdL­ow:X,stepCounterThresholdHigh:Y});
    }
    Bangle.on('step',x=>print("Step"));
    
    // run this and it'll become much less sensitive
    // setStepSensitivity(400)
    
  • Yes, that works. Thank you for posting this easy to use testing script.
    I think there is a general problem with counting steps.

    There is more to it than just measuring acceleration.
    With acceleration only you have it counting steps, but then it also counts wrist movement. So doing the dishes awards me hundreds of steps.
    Lowering the sensitivity too much will lead to steps not counted.

    Probably existing smartwatches measure this in a much more complex way.

  • Probably existing smartwatches measure this in a much more complex way.

    Feel free to look into it...

    If you find something better then we can look at implementing it in Bangle.js firmware, but nothing stops you doing in JavaScript yourself. In fact doing it in JS would allow you to compare the results from both algorithms.

    At least from my digging, acceleration magnitude seems to be the standard way of doing it. You can add a filter on to drop individual 'steps' and to only count once someone has taken a few steps in sequence...

  • No disrespect :)
    I probably did not do as much research as you.

    Maybe filtering would do the trick.

  • @Gordon
    I extended the pedometer widget and it is going through tests now.
    You have to reach 10 steps in a given time (eg 10 seconds) to make the steps count.

    Advantages:

    • This should filter out arm movement.
    • You can display an "active" attribute to show if you are currently in active mode or not
    • The "active" attribute could be used to message you to get some movemment if some time has passed without movemnet

    Disadvantage:

    • The steps are only added in increments, eg 10
    • Widget needs timers, no idea how that affects battery life.

    Currently i am fiddling around with the amount of steps needed and with the time frame to get best results. It looks promising.

  • Great!

    Widget needs timers, no idea how that affects battery life.

    It depends on how often your timers are set. If it's once a second or less you're super unlikely to notice any issues with battery life at all.

  • Thats good. We are talking about several seconds here.

  • Hi there!
    I've also been experimenting with pedometer accuracy and would like to share my results.
    I'm using several parameters - currently just as constants in the JS code:

    // Max step duration (ms)
    const cMaxTime = 1200;
    // Min step duration (ms)
    const cMinTime = 240;
    // Max difference between consecutive steps (%)
    const cMaxDiff = 50;
    // Min number of consecutive steps
    const cMinSteps = 5;
    // Step sensitivity as per http://forum.espruino.com/comments/15186­837/
    const cSensitivity = 400;
    

    The trouble I'm running into is that getTime() seems to have a resolution of 80ms, which gives me trouble with really quick steps. When two steps are only 200ms apart, the jitter will often exceed the 50% set in cMaxDiff. Since I'm not a terriffic runner, that is not a problem for me, but for some it might be.

    Maybe you would like to look into my code and use the best from both our attempts.

    Thanks a lot!


    1 Attachment

  • PS: That's what makes this project so cool. If you buy an Apple Watch and the software sucks, it just sucks. If you buy a Bangle.js and the software sucks, you can go ahead and improve it.

  • Sun 2020.04.05

    post #14 'The trouble I'm running into is that getTime() seems to have a resolution of 80ms'

    Hi @Rudi, just ran some tests fetching the getTime() value from within an interval. From 100msec, 10msec, 1msec it can be seen that the call returns a value extremely close to that which is expected, even with a small interpreter execution duration.

    dur = 100
      time at [ 1 ]  85118.3  9614868164  diff: 0.0  9997558593
      time at [ 2 ]  85118.4  9612426757  diff: 0.1  0003662109
      time at [ 3 ]  85118.5  9616088867  diff: 0.1  0000610351
    
    dur = 10
      time at [ 1 ]  84861.25  775146484  diff: 0.00  997924804
      time at [ 2 ]  84861.26  773071289  diff: 0.01  004028320
      time at [ 3 ]  84861.27  777099609  diff: 0.00  994873046
    
    dur = 1
      time at [ 1 ]  84824.128  57055664  diff: 0.000  9765625
      time at [ 2 ]  84824.129  54711914  diff: 0.000  94604492
      time at [ 3 ]  84824.130  49316406  diff: 0.000  9765625
    

    raw data with visual spacing remeoved

    dur = 100
      time at [ 1 ]  85118.39614868164  diff: 0.09997558593
      time at [ 2 ]  85118.49612426757  diff: 0.10003662109
      time at [ 3 ]  85118.59616088867  diff: 0.10000610351
    
    dur = 10
      time at [ 1 ]  84861.25775146484  diff: 0.00997924804
      time at [ 2 ]  84861.26773071289  diff: 0.01004028320
      time at [ 3 ]  84861.27777099609  diff: 0.00994873046
    
    dur = 1
      time at [ 1 ]  84824.12857055664  diff: 0.0009765625
      time at [ 2 ]  84824.12954711914  diff: 0.00094604492
      time at [ 3 ]  84824.13049316406  diff: 0.0009765625
    



    Checked the source for acceleration thresholds?

    https://github.com/espruino/Espruino/blo­b/master/libs/banglejs/jswrap_bangle.c#L­90
    https://github.com/espruino/Espruino/blo­b/master/libs/banglejs/jswrap_bangle.c#L­366



    It's more likely to be the print() statements scattered throughout.

  • I can't find a fault in my code. Could it be that Bangle.on('step') fires only at multiples of 80ms?
    ...
    If I may answer my own question: Bangle.setPollInterval will improve resolution. I think the polling interval should be less or equal one-third of the minimum step duration. If the parameters were set in a menu, the polling interval could be adjusted accordingly.

  • This looks really cool.

    Could it be that Bangle.on('step') fires only at multiples of 80ms?

    yep: as you noted above, it's based on accelerometer data, which my default is polled at ~12Hz. Higher polling rates will mean higher battery usage though...

    If 12Hz by itself is enough to detect fast steps then maybe you could consider doing something like checking cMaxDiff and difference in absolute time, and then if the difference was more than 50% but less than 80ms you still count it?

  • My solution is working pretty well, but I still have to do some tests of settings.
    Currently I have:

    10 steps in 15 seconds needed to get steps counted.
    This counts steps on a walk ok, but still does count too many steps from just arm movement.

    I will try 20 steps in 20 seconds today.

  • Wed 2020.04.08

    post #19 'still does count too many steps from just arm movement'

    Would taking a GPS position and verifiying has 'actually moved' from last reading help eliminate accelerometer movement attributed to arm waving?

  • GPS would help of course. But that would need a GPS fix.
    Annoying to get this for each walk and impossible indoors.

    I was thinking to check forward movement of the body, but that will get too complicated for me very soon.

    I am satisfied with what I got now, I just have to find the right settings for me.

    Currently I am testing:

    • 20 steps in 20 seconds
    • Active resets every 30 seconds.

    But I will never be able to filter out false steps when doing a lot of arm movement.
    But honestly, all arm-worn pedometers do count those.
    I just did not want to have 3000 steps just standing at my desk working.

About

Pedometer count issue and question

Posted by Avatar for Purple-Tentacle @Purple-Tentacle

Actions