UNPKG

5.39 kBJavaScriptView Raw
1var Board = require("./board");
2var Fn = require("./fn");
3var Emitter = require("events").EventEmitter;
4var util = require("util");
5
6var Controllers = {
7 MPL3115A2: {
8 requirements: {
9 value: {
10 options: {
11 elevation: {
12 throws: false,
13 message: "Missing `elevation` option. Without a specified base `elevation`, the altitude measurement will be inaccurate. Use the meters value shown on whatismyelevation.com",
14 typeof: "number",
15 }
16 }
17 }
18 },
19 initialize: {
20 value: function(opts, dataHandler) {
21 var Multi = require("./imu");
22 var driver = Multi.Drivers.get(this.board, "MPL3115A2", opts);
23 driver.on("data", function(data) {
24 dataHandler(data.altitude);
25 });
26 }
27 },
28 toMeters: {
29 value: function(raw) {
30
31 // Table 2, Note 3
32 // "Smallest bit change in register represents minimum value change in
33 // Pascals or meters. Typical resolution to signify change in altitudeis 0.3 m"
34 return Fn.toFixed(raw, 1);
35 }
36 }
37 },
38 MS5611: {
39 initialize: {
40 value: function(opts, dataHandler) {
41 var Multi = require("./imu");
42 var driver = Multi.Drivers.get(this.board, "MS5611", opts);
43 driver.on("data", function(data) {
44 dataHandler(data.altitude);
45 });
46 }
47 },
48 toMeters: {
49 value: function(raw) {
50 // Datasheet available at http://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=MS5611-01BA03&DocType=Data+Sheet&DocLang=English
51 //
52 // From page 1
53 // "This barometric pressure sensor is optimized for
54 // altimeters and variometers with an altitude resolution of 10 cm."
55 return Fn.toFixed(raw, 2);
56 }
57 }
58 },
59
60 BMP180: {
61 initialize: {
62 value: function(opts, dataHandler) {
63 var Multi = require("./imu");
64 var driver = Multi.Drivers.get(this.board, "BMP180", opts);
65 driver.on("data", function(data) {
66 dataHandler(data.altitude);
67 });
68 }
69 },
70 toMeters: {
71 value: function(raw) {
72 // Page 6, Table 1
73 // Resolution of output data 0.01hPa
74 //
75 // From paragraph 3.6, page 16 1hPa=8.43m
76 // resolution ~= 0.08m
77 return Fn.toFixed(raw, 2);
78 }
79 }
80 },
81
82 BMP280: {
83 initialize: {
84 value: function(opts, dataHandler) {
85 var Multi = require("./imu");
86 var driver = Multi.Drivers.get(this.board, "BMP280", opts);
87 driver.on("data", function(data) {
88 dataHandler(data.altitude);
89 });
90 }
91 },
92 toMeters: {
93 value: function(raw) {
94 // Page 8, Table 2
95 // Resolution of output data in ultra high resolution mode 0.0016hPa
96 // 1hPa=8.43m
97 // resolution ~= 0.013m
98 return Fn.toFixed(raw, 3);
99 }
100 }
101 },
102 BME280: {
103 initialize: {
104 value: function(opts, dataHandler) {
105 var Multi = require("./imu");
106 var driver = Multi.Drivers.get(this.board, "BME280", opts);
107 driver.on("data", function(data) {
108 dataHandler(data.altitude);
109 });
110 }
111 },
112 toMeters: {
113 value: function(raw) {
114 // Page 10, Table 3
115 // Resolution of pressure output data 0.18Pa
116 // 1hPa=8.43m
117 // 100Pa=8.43m
118 // resolution ~= 0.015m
119 return Fn.toFixed(raw, 3);
120 }
121 }
122 },
123
124};
125
126Controllers["BMP085"] = Controllers["BMP-085"] = Controllers.BMP180;
127
128var priv = new Map();
129
130function Altimeter(opts) {
131 if (!(this instanceof Altimeter)) {
132 return new Altimeter(opts);
133 }
134
135 var controller = null;
136 var freq;
137 var last = null;
138 var raw = null;
139 var state = {};
140
141 Board.Component.call(
142 this, opts = Board.Options(opts)
143 );
144
145 freq = opts.freq || 25;
146
147
148 if (opts.controller && typeof opts.controller === "string") {
149 controller = Controllers[opts.controller.toUpperCase()];
150 } else {
151 controller = opts.controller;
152 }
153
154 if (controller == null) {
155 throw new Error("Altimeter expects a valid controller");
156 }
157
158 priv.set(this, state);
159
160 Board.Controller.call(this, controller, opts);
161
162 if (!this.toMeters) {
163 this.toMeters = opts.toMeters || function(x) {
164 return x;
165 };
166 }
167
168 var descriptors = {
169 meters: {
170 get: function() {
171 return this.toMeters(raw);
172 }
173 },
174 feet: {
175 get: function() {
176 return Fn.toFixed(this.meters * 3.28084, 2);
177 }
178 }
179 };
180 // Convenience aliases
181 descriptors.m = descriptors.meters;
182 descriptors.ft = descriptors.feet;
183
184 Object.defineProperties(this, descriptors);
185
186
187 /* istanbul ignore else */
188 if (typeof this.initialize === "function") {
189 this.initialize(opts, function(data) {
190 raw = data;
191 });
192 }
193
194 setInterval(function() {
195 if (raw == null) {
196 return;
197 }
198
199 var data = {};
200 data.m = data.meters = this.meters;
201 data.ft = data.feet = this.feet;
202
203 this.emit("data", data);
204
205 /* istanbul ignore else */
206 if (this.meters !== last) {
207 last = this.meters;
208 this.emit("change", data);
209 }
210 }.bind(this), freq);
211}
212
213util.inherits(Altimeter, Emitter);
214
215/* istanbul ignore else */
216if (!!process.env.IS_TEST_MODE) {
217 Altimeter.Controllers = Controllers;
218 Altimeter.purge = function() {
219 priv.clear();
220 };
221}
222
223
224module.exports = Altimeter;