Suggestion for program

Posted on
  • I plan on creating a notice to inform me when my son feeds the dogs.
    I am going to Velcro the Puck in the round screw in lid to the dog food bucket.
    When he turns the lid to open it up, the accelerometer will sense movement and send out a message (battery level).

    My Ras Pi will be listening for that message and when it receives it, it will send a message to my Azure IOT Hub. ( can handle the raspberry pi code)

    I wonder if you could help me on the how I might go about programming the Puck to send a message when the accelerometer senses movement?

    Is it possible with the graphical designer?

    Thank you for any coding you can help me with so this doesn't take me a month to figure out.

  • Sun 2018.08.05

    Hello @Terrence7

    Does this excellent video tutorial provide the insight you seek?

    Door Controlled Light with Puck.js
    http://www.espruino.com/Puck.js+Door+Lig­ht


    See 'Tutorials' (sixth heading down page) listed on Puck page documentation
    http://www.espruino.com/Puck.js


    other forum posts that might provide some insight

    Just search 'magnetometer' forum page upper right


    How can I get the rotation change by Magnet xyz value ?

    Using a 3-Axis Magnetometer as a compass

    Is the Magnetometer a MAX3110 or a MAG3110?

    Datasheet MAG3110



    EDIT

    Is it possible with the graphical designer?

    Puck.js Bluetooth with the Graphical Editor

    Where I am having trouble is the BLE part of the equation

    About Bluetooth LE (BLE)

  • Robin, thank you for those links. I will start reading and watching them.

    I can figure out how to take a reading on the mag or accelerometer.

    Where I am having trouble is the BLE part of the equation. I just want to send a signal, do I have to do advertising and or GATT services, or can I just send a signal without all of the BLE ceremony?

  • @Terrence7, when reading movements from accelerometer, you modify the puck's advertisement, and go back to normal advertisement a while later. Periodically, on another puck or on Pi you check who 'is out there' by scanning for advertisements and filter the one you are interested in. You always keep the last one for comparison with the present one to determine when the movement started respectively has stopped. The change - either begin or ended - you publish to the IoT Azure Hub. Whether you can do all in graphical editor - blockly - or or not, I don't know. But doing it in JS may even be simpler.

  • @allObjects Thanks for you helpful comments.

    Any thought on this comment?

    Where I am having trouble is the BLE part of the equation. I just want to send a signal, do I have to do advertising and or GATT services, or can I just send a signal without all of the BLE ceremony?

  • Advertising is the way puck sends simplest signal. With suggested approach you do not even enter bidirectional communication.

    Take a look at Advertising.

    In the example there, puck changes advertisement every button press: a value is incremented and this value is advertised.

    On the receiving - or interested - side, a scan for devices is issued, which will pick-up the advertisement. That's all there is.

  • As @allObjects says, Advertising is what you want. It's only in one direction so it's not guaranteed that you'll receive every advertising packet. What I usually say is to transmit a number all the time, and to then just increment that number when something happens. It's then easy to detect on your IoT hub.

    This might help you out quite a bit as it uses sending a button press as an example: BLE Advertising with Node.js/Python/C#/Android

    I should add that Puck.js doesn't have an accelerometer - it's a magnetometer (effectively a 3D compass). It's still pretty easy to use it to detect movement though as any rotation would change the compass reading.

    There's a post here: http://forum.espruino.com/conversations/­301185/

    But basically you want some code like:

    var avr = Puck.mag();
    var magDiff;
    var hadMoved = false;
    var moveCounter = 0;
    Puck.on('mag', function(xyz) {
      // work out difference in field
      var dx = xyz.x-avr.x;
      var dy = xyz.y-avr.y;
      var dz = xyz.z-avr.z;
      magDiff = Math.sqrt(dx*dx+dy*dy+dz*dz);
      // update average
      avr.x += dx/2;
      avr.y += dy/2;
      avr.z += dz/2;  
      var moved = magDiff > 50;
      if (moved && !hadMoved) {
        moveCounter++;
        NRF.setAdvertising({},{manufacturer: 0x0590, manufacturerData:[moveCounter]});
      }
       hadMoved = moved;
    });
    // Turn magnetometer on
    Puck.magOn();
    

    But I'm afraid at the moment that's not something that you could do with the graphical editor - it'd have to be JS.

  • @allObjects, @Gordon Thank you for your great responses.

    I have settled on using the light sensor, as the puck will be inside the tub, and will get flooded with light when he opens the lid.

    Problem is distance. Gordon, how far should I expect a puck to Rpi to be able to communicate?

    What I usually say is to transmit a number all the time, and to then just increment that number when something happens.

    Isn't that going to burn up the battery? I would like to get a couple of months battery out of a once a day event advert.

  • Gordon, how far should I expect a Puck to Rpi to be able to communicate?

    In my house I manage around 10M including two floors and a brick wall pretty reliably. You can get more in free air, but it's the brick walls that really impact the transmission.

    Isn't that going to burn up the battery? I would like to get a couple of months battery out of a once a day event advert.

    Surprisingly not that much. The Puck has to keep broadcasting so it can be connected to - so you're not adding more power usage over what it's doing already.

    If you leave it as-is you should get at least 6 months out of it. You might want to increase the transmit power with NRF.setTxPower(4) but maybe just decrease the advertising interval - make it 1000ms instead of the default 375ms and you'll instantly bump the battery life up a load.

    While you can use NRF.sleep() and NRF.wake() to start/stop advertising, personally I'd just lower the advertising interval - it's easier, and you can always also do stuff like advertising battery level so you can keep an eye on it.

    It might be worth doing digitalRead(LED1) before you check the light level too. The LED is used for light sensing, and if it was an output then Puck.js has to wait for 50ms for it to discharge/charge each reading - which adds quite a lot of power usage :)

  • Here is my proposed code, do you have any suggestions?

    1. So in this code, LED1 is not an output, so I shouldn't have to do a read correct?

    2. The only reason you suggested bumping power with setTxPower(4) is just to give me some more distance correct?

    Thank you.

    function sendAdvert() {
      if(Puck.light() > 0.50){
        NRF.setAdvertising({0x180F : Puck.getBatteryPercentage()});
      }
      else{
       NRF.setAdvertising({0xFFFF:"0"});
      }
    }
    
    NRF.setTxPower(4);
    setInterval(sendAdvert, 1500);
    
    
  • I'd do NRF.setAdvertising({0xFFFF:[0]}); rather than sending an actual string, and NRF.setAdvertising({0x180F : [Puck.getBatteryPercentage()]}); as is done in the examples - your way might work, but providing the array is more explicit about what you want to send (one byte, not a string of characters).

    But yes, that'd work fine - although I'd still recommend that you use the counter method if you want to be sure you don't miss things happening.

    So in this code, LED1 is not an output, so I shouldn't have to do a read correct?

    I think it is an output by default - just stick digitalRead(LED1) right at the end of your code and you'll be sorted.

    The only reason you suggested bumping power with setTxPower(4) is just to give me some more distance correct?

    Correct, yes.

  • although I'd still recommend that you use the counter method if you want to be sure you don't miss things happening.

    My IOT hub will be a rpi3. I plan on capturing the battery reading when the lid has been opened, and thus will only be one hit a day. In my else statement I send a 0, though you are recommending a count.

    I don't plan on doing anything with the count, but I am interested in your suggestion, please tell me more about how this will help. (a bit slow here :) )

    Here is the current state of my code:

    function sendAdvert() {
      if(Puck.light() > 0.50){
        NRF.setAdvertising({0x180F : [Puck.getBatteryPercentage()]});
      }
      else{
       NRF.setAdvertising({0xFFFF:[0]});
      }
    }
    
    setInterval(sendAdvert, 1500);
    digitalRead(LED1);
    NRF.setTxPower(4);
    
    
  • ...you can keep/use the count to detect that the advertisement has changed... because I think you want to advertise over a certain period of time...

  • Advertising only sends data in one direction so it's not guaranteed that you'll receive every advertising packet that is sent. What I usually say is to transmit a number all the time, and to then just increment that number when something happens. It's then easy to detect on your IoT hub even if you miss a few packets.

    capturing the battery reading when the lid has been opened, and thus will only be one hit a day

    I think you think that setAdvertising will only send one packet of data? That's not actually the case. It sets the data that Espruino will advertise, but that advertisement is sent several times a second from then on out.

    This might help a bit: http://www.espruino.com/About+Bluetooth+­LE

    So the code above will work great, but you'll keep receiving advertising packets on your Pi 3 all the time. Actually sending advertising data doesn't actually use that much power though - your device will still last for months on a battery.

  • Yes, I was under the impression it would send it just when I ask it to.

    1. So my if else statement just changes What is being advertised, not When it will be advertised.

    2. My setInterval call determines the Frequency of the broadcast.

    3. If I know it takes my son 3 minutes to get all of the dog food out and put it in bowls, then can't I set the interval to 60 seconds? (you mentioned not staying connected if it was too infrequent).

    I have read over that page, all good info, but being new the concepts take a bit to sink in. Q & A really helps.

    Thank you for your clarifications.

  • So my if else statement just changes What is being advertised, not When it will be advertised.

    correct, yes...

    My setInterval call determines the Frequency of the broadcast.

    Not really - that's just how often it calls your if statement, which doesn't affect the advertising speed.

    The actual advertising interval is an argument to setAdvertising: http://www.espruino.com/Reference#l_NRF_­setAdvertising

    For instance NRF.setAdvertising({0xFFFF:[0]},{interva­l:500});

    If I know it takes my son 3 minutes to get all of the dog food out and put it in bowls, then can't I set the interval to 60 seconds?

    Yes and no. Yes, I'd say set setInterval(sendAdvert, 60000); - so your 'if' statement gets called every minute. That'll be great for battery life.

    In terms of advertising, I'd set that to 10 seconds absolute maximum. Honestly once you get past once every few seconds you're making pretty small improvements to battery life. It's still going to last a year or so.

    I should add that Advertising sends data on 3 frequency bands, each in turn. However a lot of bluetooth radios only listen for advertising on one channel at once - so they'll only get every third transmission even if there is no interference at all. It really pays to make sure you send a few more packets than you absolutely need, especially as the cost is so low.

  • Gordon, thanks for your incredible support. I am now looking at BLE coding on RPI to pick up the adverts. I hope you might help me in that area once I get over there.

    .net / asp.net / sql server etc dev. This \IOT js dev is a new area for me and its taking a bit to get my head around it.

  • For the RPi stuff, check out: http://www.espruino.com/Puck.js+Advertis­ing

    Either the Node.js or Python code should work pretty well for you. It deals mainly with getting manufacturer data rather than service data, but you could swap the Puck over to advertise that pretty easily or you could modify the code on the Pi - once you have something that gets advertisements from that link, tweaking it to read the service data field rather than the manufacturer one is nice and easy

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

Suggestion for program

Posted by Avatar for Terrence7 @Terrence7

Actions