Starting the Gate Sensor Code

This article is part of a series about a project I am working on. Taken out of context it may be a little random, so make sure you check out the original article about how I am going to build my own gate sensor.

I spent an hour or so yesterday evening working on code which will execute on the Puck.js itself.

// based level of magnetic fields 
let base = Puck.mag();

// advertise value for open/closed gate + batter precentage
let advertise = gate => {
       0x180A : [gate], 0x180F : [Puck.getBatteryPercentage()]
    },{interval: 100});

// set a good base for the magnetic field 
// check if value over threshold then pass value to advertise 
let onMag = level => {
  level.x -= base.x;
  level.y -= base.y;
  level.z -= base.z;
  let magLevel = Math.sqrt(level.x*level.x + level.y*level.y + level.z*level.z);
  magLevel > 3000 ? advertise(02) : advertise(01);
Puck.on('mag', onMag);

The magnetic field sensor returns 3 values – coordinates of X, Y & Z which allow me to pinpoint the location a magnetic field is coming from. The 3 values are not really needed for a simple gate sensor. All that is needed is the strength of the magnetic field, such as a single integer, which will give an indication of how close the magnet is. This can be achieved with some basic trigonometry –  I multiply each of the 3 values by themselves, then add them together & take the square root of that sum. This will give me a nice number to work with.

The math needs one further step. Magnetic fields are everywhere so the sensor is picking up background fields without a magnet being close to it. A baseline, or zero reading, needs to be set without the magnet being near the sensor. To do this I am getting an initial single reading of the 3 values when the code is uploaded to the Puck.js which I am then subtracting from the sensor reading before the basic trigonometry mentioned above is executed. This gives a good baseline, but I need to remember to get a new single baseline reading once the Puck.js is in its final location as the background magnetic fields may differ from where it is located now, on my desk.

Now I have a good number to work with which shows me the strength of the magnetic field. For the rest of this article, I will refer that variable as magLevel. When magLevel is larger the field is stronger, so the magnet is closer. When magLevel is smaller the field is weaker, so the magnet is further away. Whilst testing on my desk I have seen that magLevel falls below 3000 with no magnet near it and above 3000 with the magnet next to it. By using a simple if statement it is now possible to tell if the magnet is close or not, which is the basic way of telling if the gate is open or closed. Simple.

So now the Puck.js knows if the gate is open or closed I have to get that data to the Raspberry Pi so it can then trigger the push notification. To achieve this I have decided to make the Puck.js advertise (using NRF.setAdvertising) the information. A simple 01 or 02 is advertised based on the outcome of the above mentioned if statement. I have also included the battery level of the Puck.js in the advertised date so I can extend the functionality to also include a push notification when the battery is running low.

From my research so far I think this is the most battery efficient method. The code has been executing on the Puck.js all night and the battery level has not dropped.

Security wise anyone can pick up the Bluetooth Advertising, but they could also just look to see if the gate is open or closed so I don’t see that as a major security concern.

Next Steps

I need to write the Node.js side of the system which will run on the Raspbery Pi.

I also want to make the security on the Puck.js a little better, not in terms of the Bluetooth Advertising but protect it so no one can connect to it without a password.


Check back soon for my next article on the project.