3

I have a Micro:Bit. It has an accelerometer, so I'm able to measure acceleration on x,y,z axis.

The idea is to wear it on the arm and send over bluetooth when it detects some movement on the arm.

So, I would like to check the acceleration and generate an event if it passes some kind of threshold, but I don't know how to do this.

This would be something like this:

void onAwake (int x, int y, int z){
    snprintf(buffer, sizeof(buffer), "%i/%i/%i",x,y,z);
    uart->send(ManagedString(buffer));
}

int main() {
    while (1) {
      x = uBit.accelerometer.getX();
      y = uBit.accelerometer.getY();
      z = uBit.accelerometer.getZ();

      // Check if device is getting moved

      if (accel > 1) onAwake(x,y,z); // Some kind of threshold

      sleep(200);
    }
}
Lechucico
  • 1,914
  • 7
  • 27
  • 60
  • You don't say why your example doesn't work. Is it the computation of `accel` that you need? Well, it's a vector so you just have to store it's value and in every loop iteration compare it to it's "*new*" value, and update the "*new*" value for the next iteration, repeat. Also, this code would not compile. – Iharob Al Asimi Mar 01 '18 at 19:30
  • It is working, but I don't know how to calculate that acceleration that I need. – Lechucico Mar 01 '18 at 19:31
  • You want the magnitude of the acceleration? `sqrt(x * x + y * y + z * z)`, i.e. The Pythagoras theoreme (*not exactly, but equivalent*). – Iharob Al Asimi Mar 01 '18 at 19:31
  • And once I got the acceleration, how I could know if the device is moving or not? – Lechucico Mar 01 '18 at 19:33
  • 1
    If it is accelerating, it is moving. Hm, perhaps being shaken. – Weather Vane Mar 01 '18 at 19:33
  • 1
    @WeatherVane Not necessarily ... – Iharob Al Asimi Mar 01 '18 at 19:34
  • 1
    Right now, the device is on my table and it has x=0 y=0, and z=-1000. So it is "accelerating" because of gravity but it's not moving! – Lechucico Mar 01 '18 at 19:34
  • @WeatherVane If you throw a ball upwards when it reaches it's maximum height it's velocity is exactly 0 but it's acceleration is *g* (or *-g*, depening on your choice of axes to represent it). You can say, that if an object is accelerating it will move, but not that it's moving. – Iharob Al Asimi Mar 01 '18 at 19:38
  • @IharobAlAsimi an accelerometer detects change in motion, not force? – Weather Vane Mar 01 '18 at 19:40
  • @WeatherVane I think it detects change in motion, but then you should have said that if the accelerometer reports an acceleration it's moving, right? – Iharob Al Asimi Mar 01 '18 at 19:41
  • 1
    acceleration is the rate of change of velocity. To determine a rate, you'll need to introduce some kind of history to have at least 2 data points for comparison. As you've noted, simply reading the accelerometer values at a snapshot in time won't tell you about velocity... but it is indeed accelerating at the snapshot in time of your example. – yano Mar 01 '18 at 19:42
  • @IharobAlAsimi yet OP says it is sitting on his table but has z acceleration. – Weather Vane Mar 01 '18 at 19:42
  • Interesting ... I didn't read that. Then acceleration is not enough to determine whether or not there is movement, because if it's sitting on the table and there is a *z* acceleration, then it's speed would be increasing in the *z* direction, but it's *sitting* on the table. Note that it's not measuring force anyway because it would then sense the force of the table too and the acceleration would be 0. – Iharob Al Asimi Mar 01 '18 at 19:45
  • 1
    yes, that's how I understand it. It's sitting on the table with downward acceleration, but not moving, because the table is exerting an equal but opposite force (mass * acceleration) upwards, the net force on the object is zero, thus it's not moving. However, the accelerometer itself is still accelerating at -_g_. This is why your phone screen tilts from portrait to landscape when you turn it, but only when its accelerometer can sense that change in acceleration due to gravity. Hmm, maybe this question should get migrated to the physics exchange ;) – yano Mar 01 '18 at 19:50
  • @yano good point. When I rotate my phone there is no vertical acceleration, so the device is detecting a force: not an acceleration. OP if `z` is `-1000` you should be able to calibrate ;) – Weather Vane Mar 01 '18 at 19:54
  • And in terms of screen orientation, your phone is only looking for acceleration on the _y_ (I guess?) axis,, you can spin your phone all day long flat on a table and it's screen orientation won't change. I think it's safe to say that the motion of an object depends on the net-sum of all the forces acting on it, but I'm not a physicist. – yano Mar 01 '18 at 19:58
  • 1
    @yano No, and that's the problem. Note that you don't need to say "*net-force sum*", just *net-force* because it implies a sum. An object moves even when no force acts on it, but when a force acts then it's velocity changes. Note also, that velocity is a vector, so it's not enough to say that it's speed changes, because sometimes it doesn't change even though the object is accelerating, when it rotates for instance. – Iharob Al Asimi Mar 01 '18 at 20:01
  • @IharobAlAsimi I did change that wording.. but yeah you're right. An object can be moving with no forces acting on it (thinking of an object drifting through space),. but It must be moving because of a previous force, at least. Shoot, I haven't had to think about this stuff in at least 12 years, now I'm confused. – yano Mar 01 '18 at 20:04
  • 1
    @yano Don't worry. I am a physicist, so for me there is no need to *think about this stuff*, I was trained 5 years to do so. But if you want to read this quickly and understand all of it, then google about how Gallileo came to the conclusion that force was not a requirement for movement, contrary to what Aristotle thought, and how Newton summarized that fact in a *law*. – Iharob Al Asimi Mar 01 '18 at 20:10

2 Answers2

1

If the magnitude of acceleration doesn't change the device could be moving anyway, so you would need to store all 3 values and compare.

Something like this

void onAwake (int x, int y, int z){
    snprintf(buffer, sizeof(buffer), "%i/%i/%i", x, y, z);
    uart->send(ManagedString(buffer));
}

int main() {

    int x;
    int y;
    int z;

    while (1) {
       int nx = uBit.accelerometer.getX();
       int ny = uBit.accelerometer.getY();
       int nz = uBit.accelerometer.getZ();

       // Check if device is getting moved

       if ((x != nx) || (y != ny) || (z != nz))
           onAwake(x, y, z); // Some kind of threshold
       sleep(200);
    }
}
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • But this code will activate onAwake every time a variable (x, y, z) changes. I don't want that, since a jolt is not a movement and that would activate the code. I need some kind of comparison that will allow me to establish a minimum acceleration threshold. – Lechucico Mar 01 '18 at 19:38
  • But you seem confused. You should then store the speed somewhere and that would be in fact a much better indicator of movement. You know how speed changes because you know the acceleration. One question, isn't there a mechanism built into the device to detect changes in acceleration? Note that the comparison is not as relevant as the data that you can accumulate to compare with. – Iharob Al Asimi Mar 01 '18 at 19:40
  • Yes, this device has an event that awakes when acceleration changes, but it needs a big acceleration... I need that it awakes with low accelerations, that's why i'm doing this. – Lechucico Mar 01 '18 at 19:41
  • @Lechucico Perhaps you can check the device's manual and programming guide to see if you can change it's sensibility. – Iharob Al Asimi Mar 01 '18 at 19:43
  • If the sensibility is too low, then I'am afraid there's nothing you can do about it. Because there's a lack of information. You can always try to extrapolate it. But that goes way out of the scope of answer questions on SO. Feel free to send more info to my email iharob@gmail.com and we can collaborate if you like. – Iharob Al Asimi Mar 01 '18 at 19:49
  • I need something like that: https://stackoverflow.com/questions/14574879/how-to-detect-movement-of-an-android-device But I don't get what is that delta and mAccel – Lechucico Mar 01 '18 at 19:51
  • 1
    @Lechucico Read the comments on the accepted answer. – Iharob Al Asimi Mar 01 '18 at 19:54
  • But I don't get it. Because sqrt(x^2+y^2+z^2) will always give me a huge value because z is always near 1000. So this always get activated – Lechucico Mar 01 '18 at 19:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/166056/discussion-between-iharob-al-asimi-and-lechucico). – Iharob Al Asimi Mar 01 '18 at 20:02
0

I've finally solved it with adding a threshold:

MicroBit uBit;

char buffer[20];
int x, nx, y, ny, z, nz;
int threshold = 100;

void onAwake (int x, int y, int z){
    snprintf(buffer, sizeof(buffer), "%i/%i/%i", x, y, z);
    uart->send(ManagedString(buffer));
}

int main() {

    uBit.init();

    x = uBit.accelerometer.getX();
    y = uBit.accelerometer.getY();
    z = uBit.accelerometer.getZ();

    while (1) {
       nx = uBit.accelerometer.getX();
       ny = uBit.accelerometer.getY();
       nz = uBit.accelerometer.getZ();

       if ((x != nx && abs(x-nx)>threshold) || (y != ny && abs(y-ny)>threshold) || (z != nz && abs(z-nz)>threshold)) {
            onAwake(x,y,z);
       }  
       x = nx; y = ny; z = nz;
       sleep(200);
    }
Lechucico
  • 1,914
  • 7
  • 27
  • 60