Compass Offset Help

Hi.

I have a digital compass value that is showing 15 degrees as north. This offset value is consistent after every calibration. the Compass range is 0 - 360.
Can any help me with some basic code that will offset this value to 0 degrees. I'm familiar with magnetic declination and the calibration takes this value into consideration. I have searched for nodes that can offset or ZERO a value but nothing obviously available.
The value returned (msg.payload) is in json format {"heading":45}

Thank you

A simple function can do this...

image

[{"id":"49c22b709472f98b","type":"function","z":"f9687f620c582b41","name":"calibrate","func":"const offset = -15;\nconst original = msg.payload.heading;\nlet calibrated = original + offset;\nif (calibrated < 0) calibrated = 360 + calibrated;\nif (calibrated > 360) calibrated = calibrated - 360;\nmsg.payload.calibrated = calibrated;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1560,"y":1280,"wires":[["627cbd8f80ae18d3"]]},{"id":"95f3866760b7a46f","type":"inject","z":"f9687f620c582b41","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"heading\": 5}","payloadType":"json","x":1350,"y":1280,"wires":[["49c22b709472f98b"]]},{"id":"2388318e5db274cc","type":"inject","z":"f9687f620c582b41","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"heading\": 30}","payloadType":"json","x":1360,"y":1320,"wires":[["49c22b709472f98b"]]},{"id":"7c316fca509f5a1f","type":"inject","z":"f9687f620c582b41","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"heading\": 350}","payloadType":"json","x":1360,"y":1360,"wires":[["49c22b709472f98b"]]},{"id":"627cbd8f80ae18d3","type":"debug","z":"f9687f620c582b41","name":"","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"info","statusType":"auto","x":1750,"y":1280,"wires":[]}]

Use CTRL+I to import this demo flow ↑

This should be a relatively simple function node, something like:


let heading = ((360 + (msg.payload.heading -15)) % 360)
msg.payload.heading = heading
return msg

That is the fastest response i have ever know. Let me check these examples guys.
Than you :slight_smile:

You might also want to look into why the compass is showing an error of 15 degrees. Since it's not variation or deviation there must be something else off, possibly the sensor not mounted correctly in whatever housing it's in.

Might be worth contacting the manufacturer to find out if this is normal behaviour or if there's something wrong with your one.

So i think the issue is my very bad coding.

I'm sending an array from a magnetometer
[247,231,336]

X = 247
y = 231
z = 336

Im trying to get compass heading from X,Y using the following.

var X = msg.payload[0];
var Y = msg.payload[1];
function calcAngleDegrees(X,Y)
{
return Math.atan2(X,Y) * 180 / Math.PI;
}
msg.payload = (calcAngleDegrees(X,Y));
return msg.

The behavior is not a 360 degrees. Splitting the 360 into 3 segments of the pie segment being 33.3%
2 segments start at 0 then go to 60. then the last segment is 89 and doesn't change.

Any pointers on the code i'm using?

This is the code from honeywell
Direction

(y>0) = 90 - [arcTAN(x/y)]*180/Ď€Direction
(y<0) = 270 - [arcTAN(x/y)]*180/Ď€Direction
(y=0, x<0) = 180.0Direction
(y=0, x>0) = 0.0

I'm not sure how to write this in NodeRED.

Cheers guys.

Hi, can you please surround any code or values with backticks (use the code format button)

Maybe this works -

const x = msg.payload[0];
const y = msg.payload[1];
let ang = 0.0;

if (y > 0) ang = 90 - Math.atan(x / y) * 180 / Math.PI;
if (y < 0) ang = 270 - Math.atan(x / y) * 180 / Math.PI;
if (y == 0 && x < 0) ang = 180.0;
if (y == 0 && x > 0) ang = 0.0;

msg.payload = ang;
return msg;

I will do Steve, thanks. Let me try this.

Assuming that works then I think it would be a little more efficient as

if (y > 0) ang = 90 - Math.atan(x / y) * 180 / Math.PI;
else if (y < 0) ang = 270 - Math.atan(x / y) * 180 / Math.PI;
else if (y == 0 && x < 0) ang = 180.0;

The last line isn't needed as ang has been initialised to 0 at the start.

1 Like

True (I simply did a direct conversation so the op could see the relationship)

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.