• I actually just added this to the Espruino App loader as well: https://espruino.github.io/EspruinoApps/#puckrotate

    You can get the code by clicking the GitHub icon but the code has some power saving built in too which will really increase the battery life.

    1) In both examples, the gyro z-axis data is added to itself, then divided by a constant (64,000 or 128,000). Could you help me understand where you got those numbers from?

    Honestly, I started out calculating it based on 2000dps, 26 samples per second, and 360 degrees but then I just rotated the Puck by 360 degrees looked at the value I got, and divided by that - so it's almost certainly not exactly right.

    2) The second example uses a.mag and a.ang... I don't see these referenced in the API docs. Is 'mag' using the magnetometer? If so, what for? Where do I find more info about these two properties?

    They're created in line 10/11. Just added to the acceleration object because then I could see what they were by looking at lastAccel in the console.

    • mag is the size of the acceleration (squared). If the Puck isn't moving it should be the same as gravity (8192*8192 because of the scaling)
    • ang is the angle based on X and Y

    3) The math in the second example gets over my head. Any insight into that would be great (but don't feel obligated if there is not a simple way to explain it.)

    Yes, sorry - it was a quick hack so I didn't document it too well...

    // work out the rotation from the gyro - this line is all you need
    // if you don't care alignment with gravity
    d -= r.gyro.z/128000;
    
      var a = r.acc;
    // work out the magnitude of acceleration squared 
      a.mag = a.x*a.x + a.y*a.y + a.z*a.z;
    // work out the angle (as a value between 0 and 1)
      a.ang = Math.atan2(a.y,a.x)/(2*Math.PI);
    // if magnitude is more or less than gravity we assume we've moved
      if (a.mag < 66000000 || a.mag > 71000000) {
        timeStationary = 0;
      } else {
    // otherwise we start incrementing a counter
        if (timeStationary<100) timeStationary++;
    // when we've been stationary for 100 samples (~4 seconds)
    // start re-adjusting the value based on gravity
        else {
    // work out the nearest rotation value that matches with the rotation
    // we're getting based on gravity. 
    // a.ang is the fractional amount of rotation (-0.5 .. 0.5)
    // Math.round(d) is the nearest whole rotation
          var nearest = Math.round(d)+a.ang;
    // then we do a simple average (we don't set the value right away)
          d = d*0.8 + nearest*0.2;
        }
      }
    
About

Avatar for Gordon @Gordon started