Location tracking

Posted on
of 2
/ 2
  • I'm looking for a solution to tracking people as they move around in a space and I'm wondering if attaching some Pucks to the people will give me something workable.

    I'm guessing I can use some form of triangulation based on signal strength if I set up some Pucks around the space as well?

    Has anyone had any experience doing this sort of thing? @Gordon know anybody that has achieved this, or if it is even possible given the capabilities of the Puck?

    I'd need to be able to differentiate between two people standing within a couple of feet of each other.

  • Yes, it's definitely possible... So you want to track people and send it back to some central place?

    There would be a few ways of doing it (for instance Pucks could look at the signal strength of other Pucks that are within range), but personally I'd:

    • Give everyone you want to track a Puck
    • Put a few Raspberry Pi Zero W devices around that'll report back all the signal strengths of Pucks they see, and can use that for triangulation

    Or, another method is:

    • Put some Pucks around as beacons, and have them advertise an X/Y coordinate
    • On each Puck a user has, use NRF.setScan and then keep track of all the currently found 'beacon' Pucks. You can then work out a rough distance from the signal strength and can keep a weighted average of the XY coordinates. Then you can do whatever you want with that on the Puck itself (maybe just advertising the position the Puck believes the person is in).

    Personally I'd say the first option might be the more sensible - it gives you a bunch of data, and the Pi Zero Ws are ridiculously cheap.

  • I think I like both approaches. Problem with RPZ-W's is, everywhere that sells them is one per customer and I need at least 3 for triangulation!

    Good to know its plausible.

    Are you still on 2 day shipping on Tindie? I'm gonna need a few Puck's ASAP. I want to order direct but if somewhere else ships faster it'll have to be them.

  • Just emailed, but I usually send out in the afternoon of monday wednesday friday. To anyone else reading this, if there's a reason you need it urgently then get in touch - most times I can send out sooner if it's needed.

  • @Gordon btw, what is the rough maximum ranges (rx, tx) of the bluetooth module in Puck?

  • I don't know separate ranges for RX and TX - it'll depend a lot on what's on the other end. Raytac say 'over 80m in open space' for the module in Puck.js, which seems pessimistic given what others are claiming they're getting with the same chip and cheaper aerials.

    Only thing to watch out for are obstructions - I don't know the figures, but a brick wall has a huge effect, and even a human body can drop the signal strength so you can't expect super accurate triangulation. It'll be the same for any other 2.4ghz radio systems though, and the more receivers/beacons you have in known positions the better it'll be.

  • Well I'm not trying to track through walls or anything, just in a very large space. 1500m2. However thats 30m x 50m.

    Now my brain gets confused because geometry was never a strong suit (oh yes I'm looking forward to the triangulation maths), because in theory that means a single puck (with 50m range) could cover the entire space? Or am I mad?

  • Yes, I think that'd be fine - however the more static base stations (either transmitters or receivers) you have the better, because then you can average the data you get...

    Personally I'd start simple - manually work out how the RSSI reading corresponds to distance by taking some readings... then you just need to work out the position from the distances, which could require some googling :)

    If you can't find anything then let me know - I have an idea about how you can do it, but it's almost certainly not the best way!

  • @Gordon Hmm. I'm using

    NRF.findDevices(function(devices) {
    }, 1000);

    but I'm barely getting 10 meters range, let alone 80!

    Flashed firmware to both devices, did NRF.setTxPower(4) on both devices.... just not getting any sort of range.

    Any ideas?

  • I guess you're still connected by Bluetooth?

    It could be because when you're connected by bluetooth it's sending and receiving packets to your PC every (i think) 20ms or so, which could very likely overlap with the advertising packets that it is trying to receive (and that appear only every 300ms or so).

    You could try something like:

    var found = [];
    setWatch(function() {
      NRF.findDevices(function(devices) {
        found = devices;
      }, 4000);
    }, BTN, { edge:"rising",debounce:50,repeat:true });

    and you could upload, press the button, then connect again after the 5 seconds and see what was in 'found'?

  • Hi @Gordon, gave that a try, still getting 10 meters at best, outside in open space. I changed the code to this so I didn't need to reconnect each time, it just flashes an LED if it sees another Puck

    setWatch(function() {
      NRF.findDevices(function(devices) {
        devices.forEach(function (device) {
          if (device.name && device.name.indexOf('Puck.js') >= 0) {
      }, 4000);
    }, BTN, { edge:"rising",debounce:50,repeat:true });

    Any further ideas?

  • Not at the moment... I'll take a look at this on Monday - it's possible that the softdevice is stripping out anything with a signal strength that's too low I guess. Presumably you can see the Puck from much further away with a phone?

  • Yes I backed up about as far as I could get and the phone sees the Puck, although it takes a few scans sometimes. 30m at least.

  • @Gordon more interesting behaviour. I have the following code running:

    function getDevices() {
      NRF.findDevices(function(foundDevices) {
        foundDevices.forEach(function (device) {
          if (device.name && device.name.indexOf('Puck.js') >= 0) {
            const data = device.data.toString();
              name: device.name,
              rssi: device.rssi,
              data: data,
      }, 250);
    setInterval(getDevices, 2000);

    This can run fine for ages, but sometimes I get the edge case where the LED remains on (so NRF.findDevices is never returning), which requires me to reset the device as it is no longer discoverable via the IDE.

    Equally, if I am connected to the device via the IDE and then disconnect, about 25% of the time the device gets stuck, either with the LED on or off.

    Any idea what might be going on?

  • @Gordon this seems to get worse the more beacons I have online. With 1 beacon the problem barely ever happens, with 3 its every few seconds.

    Just wondering if https://www.espruino.com/Reference#t_l_N­RF_setAdvertising calls some code on the NRF and the 'interval' setting is then sufficiently randomised by the NRF? i.e if I set interval to 100, the actual intervals are +- 10ms of 100? Or do I need to be including the randomness required for the advertisements to not conflict?


  • I don't understand the RSSI readings I get on the Pucks... I get a better signal from a Puck 2 meters away than the one 1 meter away...

    I'm the grey splodge, the blue Puck is 2 meters away, the red puck is 1 meter away, yet the blue puck gives me consistently better RSSI readings. I know there should be some variance but this seems way out of whack.

    1 Attachment

    • Screen Shot 2017-07-23 at 11.09.58.png
  • Did you ever solve the 'crash' issue? There should be enough randomness in the output times to work I think. You could try without the Bluetooth.println in case that's causing issues - but it shouldn't be.

    I'd have said that 250ms for findDevices could be a bit short. You could also try using NRF.setScan - which leaves scanning on all the time, and calls you back whenever an advertising packet is received.

    With the signal strength, it's odd that it's that bad. Does the red one have setTxPower(4) as well? Could your body be in the way of the signal at all? The aerials don't radiate and receive as well in all directions, so if the angle of the red Puck happened to be in a 'dead spot' it could cause problems.

    If you take a look at Page 25 of http://www.raytac.com/download/MDBT42/MD­BT42Q%20spec-Version%20C.pdf you'll see the radiation pattern of the module. Annoyingly the more expensive ceramic antenna version (which we're using) has a far more uneven emission pattern than the cheap one. It looks to me like as long as the aerial side of the Puck is facing out into the room you should be ok.

  • I swapped over to setScan but I still get crashes fairly frequently.

    That is...one hell of a radiation pattern. Which side of the Puck is which? I've ended up trying to make sure I orient them all the same so that the bluetooth module is at the top, facing out into the room.

  • I know. I'm quite surprised about that to be honest - I expected the ceramic antenna to be better than the printed one. You do get much better signal strength I guess.

    I know as much about that as you do, but my guess is that Z is vertical, X is in the direction of the writing on the module, and Y is in line with the antenna (as you'd expect that to be pretty symmetrical).

    So you get less signal if you're at the button-end of the Puck, since the metal shield blocks it quite a lot.

    I'll see if I can reproduce some kind of crash here when using setScan - and you're on the 1v93 firmware?

  • Yes, first thing I did was flash them

  • Would you be ok posting up your setScan code? I've just been doing this:

    var n = 0;
    NRF.setScan(function(d) {
      if (d.id=="f3:ec:65:44:85:db random") {
    var hist = [];
    setInterval(function() {
      while (hist.length>20) hist.shift();
    }, 5000);

    With around 15 advertising packets/second received, and it still seems stable. When connected the amount of advertising packets received drops from 15 down to 8/9 though - so having a connection open means it misses quite a lot.

  • Simplified version is:

    var devices = {};
    NRF.setScan(function(device) {
        if (device.name && device.name.indexOf(‘Puck.js’) >= 0) {
          const data = device.data.toString().substr(-1);
          if (!devices[device.name]) {
            devices[device.name] = {
              name: device.name,
              rssi: device.rssi,
              data: data,
          const oldDevice = devices[device.name];
          if (device.rssi !== oldDevice.rssi) {
            devices[device.name].rssi = device.rssi;

    Is that receiving advertising packets from a single Puck or having many advertising at the same time?

  • I have 5 Pucks advertising at the same time, with one set to advertise every 50ms.

    When I upload that code, the console just gets spammed with JSON from the advertising and it's hard to do anything, which is kind of what you'd expect. Realistically the RSSI values move around a bit so almost every advertising packet is different and it ends up printing data faster than it can output it over Bluetooth.

    However, if I remove the Bluetooth.println(JSON.stringify(device)­); and just type devices to look at the active devices then it looks like it's working pretty well. It's been going a few minutes now but I'll leave it longer just to make sure.

  • Yeah its not that its hard to do anything, its that it seems to lock up the Puck entirely (as in eventually the println stops being run)

  • It's still working without the println. It seems very stable...

    But yes, if I add the Bluetooth.println it prints a solid wall of text and starts locking up after a while. Even this does it:

    NRF.setScan(function(device) {

    but if I throttle it down enough, it doesn't do it:

    var n=0;
    NRF.setScan(function(device) {
      if (n&15) return;

    When printing fast and connected by serial, I seem to be able to get out of memory errors as well - which will be due to all the advertising packets queuing up in memory and not being handled fast enough.

    Honestly, I'm not sure there's much I can do. Bluetooth LE can only transmit data so fast. If you're printing data faster than it can be output, something has to give.

    I'll file a bug for the subsequent crash and will try and sort that out - but even if that's fixed, your code isn't going to work with the print statements in it like that.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Location tracking

Posted by Avatar for dave_irvine @dave_irvine