You are reading a single comment by @Eric and its replies. Click here to read the full conversation.
  • All what you say makes sense Gordon following on from my recent tests.

    I may help to make it clear what I am attempting and how I am progressing so far.

    The project is to set a range of Puck's to broadcast primarily motion detection but also temperature, light level, magnetometer, voltage readings and battery condition. The target uses are:

    a) Motion detection to turn lights on and off and act as intrusion detection.

    b) Pool water level detection and temperature using a floating magnet in the pool skimmer and a waterproof remote temperature IC. (Currently working using a Photon device and a solar panel / battery circuit)

    c) Soil moisture detection to trigger irrigation and monitor soil moisture over time.

    All of this was to be monitored, recorded and acted on using an externally situated Pi3 running node-red. Trigger actions are handled with a combination of IFTTT event handlers and notifications, and data logging using an SQL database.

    I must say that I am very happy with what has been achieved so far and most of the elements are working very well, but I feel it's not fully optimised yet.

    Initially I experimented with code that you posted to set up advertising a simple value:

    setInterval(function() {
      NRF.setAdvertising({
        0x1809 : [Math.round(E.getTemperature())]
      });
    }, 30000);
    

    It's clear now that this will set broadcasting up continuously the temperature reading, and update it every 30 seconds. All very good.

    I modified the code to send a second parameter to see if it was possible to send multiple sensors in the same broadcast command. For example:

    setInterval(function() {
      NRF.setAdvertising({
        0x1809 : [Math.round(E.getTemperature())],
        0x2a00 : [Math.floor((Math.random() * 10) + 1)]
      });
    }, 30000);
    

    Setting up a /ble/advertise/fd:f9:15:7f:43:07/# MQTT listener showed both values correctly and were also filterable using /0X809 and /0x2a00 in the filter.

    Adding a third or fourth value also worked until I more data to the array like a string of characters to represent the mag array, or just a random "Hello world" string. This broke the advertisement and threw an error in the Puck console. I believe it was a ble size error.

    Removing some of the data lines or shortening the strings sent fixed the error and all was good once more.

    To get around the problem, I divided the messaging up into multiple advertisements delayed by 5 seconds using setTimeout() functions. All these were wrapped in a 60 second setInterval() function to refresh the data readings.

    One other important discovery was that if you want to advertise an important event, you must stop other events from being advertised, or at least being refreshed, otherwise the event may be lost. This was the case for a motion detect event. To handle this I recorded state of the motion detector to suppress broadcasting of other data.

    Motion detection was also set up to be broadcast on a state change using a setWatch() function. This was the number one priority broadcast event so had to broadcast as soon as it occurred.

    Using this method led me to believe there is an advertise period (backed up by some NRF documents). The fully working code I used is:

    //7f:9a Motion detector code
    digitalPulse(LED1,true,1000);
    pinMode(D1, 'input_pulldown');
    pinMode(D30, 'input');
    var state =0;
    var zero = Puck.mag();
    
    NRF.setTxPower(4); // Full Power advertising
    
    
    function motion(){
      digitalPulse(LED3,true,100);
      advertise(1);
    }
    
    function reset(){
      digitalPulse(LED2,true,100);
      advertise(0);
    }
    
    function advertise(pinState){
      state = pinState;
      NRF.setAdvertising({
              0x2a00 : [state]
          });
      
    }
    
    setWatch(motion, D1, {repeat:true,edge:'rising',debounce:100});
    setWatch(reset, D1, {repeat:true,edge:'falling',debounce:100});
    
    setInterval(function () {
      
      
      setTimeout(function(){
        if(state === 0){
          NRF.setAdvertising({
            0x2a01 : [String(E.getTemperature())]
          });
        }
      },1);
    
        setTimeout(function(){
          var volts = analogRead(D30)*6.6;
              volts = Math.round(volts * 100) / 100;
         if(state === 0){
          NRF.setAdvertising({
            0x2a02 : [String(volts)]
          });
         }
        },5000);
    
       setTimeout(function(){
          if(state === 0){
            NRF.setAdvertising({
              0x180f : [Puck.getBatteryPercentage()]
            });
          }
        },10000);
      
      setTimeout(function(){
          if(state === 0){
            NRF.setAdvertising({
              0x2a03 : [String(NRF.getBattery())]
            });
          }
        },15000);
      
        setTimeout(function(){
          if(state === 0){
            NRF.setAdvertising({
              0x2a04 : [String(Puck.light())]
            });
          }
        },20000);
      
        setTimeout(function(){
         if(state === 0){
          NRF.setAdvertising({
            0x2a05 : [String(getMag())]
          });
         }
        },25000);
    
    
    },60000);
    
    function getMag(){
      p = Puck.mag();
      p.x -= zero.x;
      p.y -= zero.y;
      p.z -= zero.z;
      var s = Math.sqrt(p.x*p.x + p.y*p.y + p.z*p.z);
       return Math.round(s * 100 ) / 100;
    }
    

    If anyone would like to see the node-red flow and view some of the output data I have attach then to this post.

    Finally a note about the battery life. If you simply watch all events from a Puck, you see a stream of RSSI adverts with the puck name:

    9/01/2017, 11:06:3194b19651.0be4b8
    /ble/advertise/fd:f9:15:7f:43:07 : msg.payload : string [34]
    {"rssi":-99,"name":"Puck.js 4307"}
    19/01/2017, 11:06:3194b19651.0be4b8
    /ble/advertise/fd:f9:15:7f:43:07/rssi : msg.payload : string [3]
    -99

    These occur continously, so the thought of of being able to have a multiplexing array of adverts that use the same broadcast stream would be really cool. Having it all handled in the command NRF.setAdvertising({id,[payload1]},{id,[payload2]},id{id,[payload3]}, options) whoud be a simple way to set up non colliding event data as you suggested. Further options could be added to have a priority flag that ensured a motion event could be prioritised over another to be re-advertised on change.

    My current Puck battery life is holding out apart from initial uploading hundreds of times the code, but when left to advertise, appears to be steady. Temperature does effect the battery readings so you do have to watch trends over time.
    All food for thought and possibly outside the normal methods of ble data coms.


    2 Attachments

About

Avatar for Eric @Eric started