/
LIS2DH12.js
155 lines (144 loc) · 5 KB
/
LIS2DH12.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* Copyright (c) 2017 Gordon Williams, Pur3 Ltd. See the file LICENSE for copying permission. */
var C = {
WHO_AM_I:0x0F,
CTRL_REG1:0x20,
CTRL_REG2:0x21,
CTRL_REG3:0x22,
CTRL_REG4:0x23,
STATUS_REG:0x27,
OUT_X_L:0x28,
I_AM_MASK:0x33,
// CTRL_REG1
ODR_MASK_1HZ:0x10, /*HR / Normal / Low Power */
ODR_MASK_10HZ:0x20, /*HR / Normal / Low Power */
ODR_MASK_25HZ:0x30, /*HR / Normal / Low Power */
ODR_MASK_50HZ:0x40, /*HR / Normal / Low Power */
ODR_MASK_100HZ:0x50, /*HR / Normal / Low Power */
ODR_MASK_200HZ:0x60, /*HR / Normal / Low Power */
ODR_MASK_400HZ:0x70, /*HR / Normal / Low Power */
ODR_MASK_1620HZ:0x80, /* Low Power Mode only */
ODR_MASK_HIGH_RES:0x90, /* in HR+Normal: 1344Hz, in Low Power 5376Hz */
LPEN_MASK:0x08,
XYZ_EN_MASK:0x07,
// CTRL_REG4
HR_MASK:0x08,
SCALE2G:0, /**< Scale Selection */
SCALE4G:1,
SCALE8G:2,
SCALE16G:3
};
/* Initialise LIS2DH12 - called automatically from connectSPI/connectI2C.
options = {
callback : function, // function to call when data is ready
};
*/
function LIS2DH12(r,w, options) {
this.r = r; // read from a register
this.w = w; // write to a register
this.options = options||{};
this.callback = this.options.callback;
if (this.r(C.WHO_AM_I, 1)[0] != C.I_AM_MASK)
throw "LIS2DH12 WHO_AM_I check failed";
this.g_scale = C.SCALE2G;
this.mode = "powerdown";
this.interval = undefined;
}
/** Set the power state of the accelerometer.
Either :
"normal" - 100Hz
"low" - 1Hz
"fast" - 1000Hz
"highres" - 1000Hz
"powerdown" - Off */
LIS2DH12.prototype.setPowerMode = function (mode) {
var ctrl1RegVal = C.XYZ_EN_MASK; // Enable all axis
var ctrl4RegVal = this.g_scale<<4; // Set Scale
var time_ms = 0;
switch(mode) {
case "normal":
ctrl1RegVal |= C.ODR_MASK_100HZ;
this.g_mgpb = 4 << this.g_scale; // 4 bits per mg at normal power/2g, adjust by scaling
time_ms = 10;
break;
case "low":
ctrl1RegVal |= (C.ODR_MASK_1HZ); //Power consumption is same for low-power and normal mode at 1 Hz
this.g_mgpb = 4 << this.g_scale; // 4 bits per mg at normal power/2g, adjust by scaling
time_ms = 1000;
break;
case "fast":
ctrl1RegVal |= (C.ODR_MASK_1620HZ | C.LPEN_MASK);
this.g_mgpb = 16 << this.g_scale; // 16 bits per mg at low power/2g, adjust by scaling
time_ms = 1;
break;
case "highres":
ctrl1RegVal |= C.ODR_MASK_HIGH_RES;
ctrl4RegVal |= C.HR_MASK;
this.g_mgpb = 1 << this.g_scale; // 1 bits per mg at high power/2g, adjust by scaling
time_ms = 1;
break;
case "powerdown":
ctrl1RegVal = 0;
time_ms = 0;
break;
default:
throw "Unknown power mode "+JSON.stringify(mode);
}
this.w(C.CTRL_REG1, ctrl1RegVal);
this.w(C.CTRL_REG4, ctrl4RegVal);
/* save power mode to check in get functions if power is enabled */
this.mode = mode;
// set up timer
if (this.interval) clearInterval(this.interval);
this.interval = undefined;
if (time_ms && this.callback) {
this.interval = setInterval(function(acc) {
acc.callback(acc.getXYZ());
}, time_ms, this);
}
};
/* Get the last read accelerometer readings as
an object with {x,y,z,new} elements. new is false if the data hasn't changed since the last read */
LIS2DH12.prototype.getXYZ = function() {
var d = new DataView(new Uint8Array(this.r(C.STATUS_REG, 7)).buffer);
var scale = 1 / (16 << (this.g_scale)) * 1000 / 1024;
return {
x: d.getInt16(1,true)*scale,
y: d.getInt16(3,true)*scale,
z: d.getInt16(5,true)*scale,
new : (d.getUint8(0)&8)!=0
};
};
/* Call the callback with an accelerometer reading {x,y,z}. If the accelerometer is powered off,
power it on, take a reading, and power it off again */
LIS2DH12.prototype.readXYZ = function(callback) {
var isOff = this.mode=="powerdown";
var c = this.callback;
this.callback = function(xyz) {
if (isOff) this.setPowerMode("powerdown");
this.callback = c;
callback(xyz);
};
if (isOff) this.setPowerMode("normal");
};
/* Initialise the LIS2DH12 module with the given SPI interface and CS pins.
See 'LIS2DH12' above for options */
exports.connectSPI = function(spi,cs,options) {
if ("function"==typeof options)
throw new Error("Use require(LIS2DH12).connectSPI(..., {callback:function() { ... }} instead");
return new LIS2DH12(function(reg,len) { // read
return spi.send([reg|0xC0,new Uint8Array(len)], cs).slice(1);
}, function(reg,data) { // write
return spi.write(reg, data, cs);
},options);
};
/* Initialise the LIS2DH12 module with the given I2C interface (and optional address with connectI2C(i2c,{addr:...}) )
See 'LIS2DH12' above for more options */
exports.connectI2C = function(i2c,options) {
var addr = (options&&options.addr)||0x19;
return new LIS2DH12(function(reg,len) { // read
i2c.writeTo(addr,reg|128);
return i2c.readFrom(addr,len);
}, function(reg,data) { // write
i2c.writeTo(addr,reg,data);
},options);
};