You are reading a single comment by @fanoush and its replies. Click here to read the full conversation.
  • Yes, that Hackaday link is basically all the info I have on the Q3 at the moment, and you can build Espruino (although I'm not doing automatic builds at the moment). Basically what we're missing is the heart rate sensor right now (since I have to reverse engineer it all). I'm hoping to get them in the shop 'soon' - hopefully within the next month - but they're still very much beta as I have to decide exactly what to do about making existing apps compatible (the screen/buttons are different).

    GPS is a pain though - it doesn't seem to be quite as good as the Bangle's, and as you say it's a completely different command set too.

    Is there a way to simulate this in javascript first,

    Yes - it's not a very difficult algorithm (there is no machine learning), so this is probably what I should have actually done at the start. Try:

    // values for debug plotting
    var lastAccel = 120;      // BLUE
    var lastAccelFilt = 120;  // YELLOW
    var lastThresh = 120;     // RED
    
    var filter_taps = new Int8Array([ -2, 4, 4, 1, -1, 0, 2, -3, -12, -13, 2, 24, 29, 6, -25, -33, -13, 10, 11, -1, 3, 29, 41, 4, -62, -89, -34, 62, 110, 62, -34, -89, -62, 4, 41, 29, 3, -1, 11, 10, -13, -33, -25, 6, 29, 24, 2, -13, -12, -3, 2, 0, -1, 1, 4, 4, -2 ]);
    var history = new Int8Array(filter_taps.length);
    const stepCounterThresholdMin = 1500;
    const stepCounterAvr = 1;
    
    /// Theshold in filtered acceleration for detecting a step
    var stepCounterThreshold = stepCounterThresholdMin;
    /// has filtered acceleration passed stepCounterThresholdLow?
    var stepWasLow = false;
    
    function onAccel(a) {
      // scale to fit and clip
      var v = ((a.mag-1)*8192)>>5;
      // save
      history.set(new Int8Array(history.buffer,1));
      history[history.length-1] = E.clip(v, -128, 127);
      // do filtering
      var accFiltered = E.convolve(filter_taps, history, 0) >> 2;
    
      /*
      // Simple average-based threshold
      if (stepCounterAvr) {
        var a = accFiltered;
        if (a<0) a=-a;
        stepCounterThreshold = (stepCounterThreshold*(32-stepCounterAvr) + a*stepCounterAvr) >> 5;
        if (stepCounterThreshold < stepCounterThresholdMin)
          stepCounterThreshold = stepCounterThresholdMin;
      }*/
      
      // Set threshold based on the 'middle' history item - the one making the big spikes.
      // Try and scale it appropriately
      var a = history[32] * 55; 
      if (a<0) a=-a;
      if (a > stepCounterThreshold) 
        stepCounterThreshold = a;//(stepCounterThreshold+a) >> 1;
      stepCounterThreshold -= 48;
      if (stepCounterThreshold < stepCounterThresholdMin)
        stepCounterThreshold = stepCounterThresholdMin;  
      
      // check for steps
      var hadStep = false;
      if (accFiltered < -stepCounterThreshold) 
        stepWasLow = true;
      else if ((accFiltered > stepCounterThreshold) && stepWasLow) {
        stepWasLow = false;
        hadStep = true;
      }
    
      // output data
      g.scroll(0,1);
      var n;
      
      if (accFiltered < -stepCounterThreshold)
        g.setColor("#0ff").fillRect(0,0,8,0);
      if (accFiltered > stepCounterThreshold)
        g.setColor("#0ff").fillRect(232,0,240,0);
      
      n = 120+v;
      g.setColor("#00f").fillRect(lastAccel,0,n,0);
      lastAccel = n;
      n = 120+(accFiltered>>6);
      g.setColor("#ff0").fillRect(lastAccelFilt,0,n,0);
      lastAccelFilt = n;
      n = 120+(stepCounterThreshold>>6);
      g.setColor("#f00").fillRect(lastThresh,0,n,0);
      lastThresh = n;
    
      if (hadStep) {
        g.setColor(-1).drawString("STEP",60,0);
      }
    }
    Bangle.on('accel',onAccel);
    Bangle.setLCDTimeout(0);
    
    

    On the graph that's displayed, blue is the actual accelerometer data, yellow is the filtered data, and red is the threshold.

    The issue is really the filter...

    • It's good in that repeated inputs within the frequency range get amplified, so are easy to detect
    • However a single big acceleration input will 'ring' - it generates oscillations in the desired frequency.

    So if using the filter actually turns out to be a good idea, we basically need a way of only passing through steps when the filter is producing values that are all the same (ish) amplitude, and not passing through the outliers.

  • I'm hoping to get them in the shop 'soon' - hopefully within the next month - but they're still very much beta

    Even the HW was beta, looks like newer ones that some guys received later have small hole and pressure sensor works much better with that. Without hole the pressure inside just goes up with the temperature and does not reflect air pressure very much.

About

Avatar for fanoush @fanoush started