forked from espruino/EspruinoDocs
/
VL6180X.js
197 lines (167 loc) · 9.76 KB
/
VL6180X.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/* Copyright (c) 2020 Salvatore Castelbuono. See the file LICENSE for copying permission. */
var C = {
VL6180X_DEFAULT_I2C_ADDR: 0x29,
VL6180X_REG_I2C_ADDR: 0x0212,
VL6180X_REG_IDENTIFICATION_MODEL_ID: 0x000, // Device model identification number
VL6180X_REG_SYSTEM_INTERRUPT_CONFIG: 0x014, // Interrupt configuration
VL6180X_REG_SYSTEM_INTERRUPT_CLEAR: 0x015, // Interrupt clear bits
VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET: 0x016, // Fresh out of reset bit
VL6180X_REG_SYSRANGE_START: 0x018, // Trigger Ranging
VL6180X_REG_SYSALS_START: 0x038, // Trigger Lux Reading
VL6180X_REG_SYSALS_ANALOGUE_GAIN: 0x03F, // Lux reading gain
VL6180X_REG_SYSALS_INTEGRATION_PERIOD_HI: 0x040, // Integration period for ALS mode, high byte
VL6180X_REG_SYSALS_INTEGRATION_PERIOD_LO: 0x041, // Integration period for ALS mode, low byte
VL6180X_REG_RESULT_RANGE_STATUS: 0x04d, // Specific error codes
VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO: 0x04f, // Interrupt status
VL6180X_REG_RESULT_ALS_VAL: 0x050, // Light reading value
VL6180X_REG_RESULT_RANGE_VAL: 0x062, // Ranging reading value
//Lux gain - not needed
VL6180X_ALS_GAIN_1: 0x06, // 1x gain
VL6180X_ALS_GAIN_1_25: 0x05, // 1.25x gain
VL6180X_ALS_GAIN_1_67: 0x04, // 1.67x gain
VL6180X_ALS_GAIN_2_5: 0x03, // 2.5x gain
VL6180X_ALS_GAIN_5: 0x02, // 5x gain
VL6180X_ALS_GAIN_10: 0x01, // 10x gain
VL6180X_ALS_GAIN_20: 0x00, // 20x gain
VL6180X_ALS_GAIN_40: 0x07, // 40x gain
VL6180X_ERROR_NONE: 0, // Success!
VL6180X_ERROR_SYSERR_1: 1, // System error
VL6180X_ERROR_SYSERR_5: 5, // System error
VL6180X_ERROR_ECEFAIL: 6, // Early convergence estimate fail
VL6180X_ERROR_NOCONVERGE: 7, // No target detected
VL6180X_ERROR_RANGEIGNORE: 8, // Ignore threshold check failed
VL6180X_ERROR_SNR: 11, // Ambient conditions too high
VL6180X_ERROR_RAWUFLOW: 12, // Raw range algo underflow
VL6180X_ERROR_RAWOFLOW: 13, // Raw range algo overflow
VL6180X_ERROR_RANGEUFLOW: 14, // Raw range algo underflow
VL6180X_ERROR_RANGEOFLOW: 15 // Raw range algo overflow
};
function VL6180X(i2c, options) {
this.options = options||{};
this.i2c = i2c;
this.ad = C.VL6180X_DEFAULT_I2C_ADDR;
if (this.options.address) { // Change I2C address, if specified in options
this.ad = this.options.address;
this.write8(C.VL6180X_REG_I2C_ADDR, this.ad);
}
if (this.read8(C.VL6180X_REG_IDENTIFICATION_MODEL_ID) != 0xB4){
console.log(this.read8(C.VL6180X_REG_IDENTIFICATION_MODEL_ID));
}
if (this.read8(C.VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET) == 0x01){
console.log("Load settings...");
this.loadSettings();
}
this.write8(C.VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00);
}
//Read and Write 1 byte (8 bit) values
VL6180X.prototype.read8 = function(reg) {
this.i2c.writeTo(this.ad, reg >> 8, reg & 0xff);
var data = this.i2c.readFrom(this.ad, 0x01);
return data[0];
};
VL6180X.prototype.write8 = function(reg, value) {
this.i2c.writeTo(this.ad, reg >> 8, reg & 0xff, value);
};
//Read and Write 2 byte (16 bit) values
VL6180X.prototype.read16 = function(reg) {
this.i2c.writeTo(this.ad, reg >> 8, reg & 0xff);
var data = this.i2c.readFrom(this.ad, 0x02);
return (data[0] << 8) | data[1];
};
VL6180X.prototype.write16 = function(reg, value) {
this.i2c.writeTo(this.ad, reg >> 8, reg & 0xff, value >> 8, value & 0xff);
};
//Load settings function
VL6180X.prototype.loadSettings = function() {
// private settings from APPENDIX 1 - Setup Guide
this.write8(0x0207, 0x01);
this.write8(0x0208, 0x01);
this.write8(0x0096, 0x00);
this.write8(0x0097, 0xfd);
this.write8(0x00e3, 0x01);
this.write8(0x00e4, 0x03);
this.write8(0x00e5, 0x02);
this.write8(0x00e6, 0x01);
this.write8(0x00e7, 0x03);
this.write8(0x00f5, 0x02);
this.write8(0x00d9, 0x05);
this.write8(0x00db, 0xce);
this.write8(0x00dc, 0x03);
this.write8(0x00dd, 0xf8);
this.write8(0x009f, 0x00);
this.write8(0x00a3, 0x3c);
this.write8(0x00b7, 0x00);
this.write8(0x00bb, 0x3c);
this.write8(0x00b2, 0x09);
this.write8(0x00ca, 0x09);
this.write8(0x0198, 0x01);
this.write8(0x01b0, 0x17);
this.write8(0x01ad, 0x00);
this.write8(0x00ff, 0x05);
this.write8(0x0100, 0x05);
this.write8(0x0199, 0x05);
this.write8(0x01a6, 0x1b);
this.write8(0x01ac, 0x3e);
this.write8(0x01a7, 0x1f);
this.write8(0x0030, 0x00);
//Recommended : Public registers - See data sheet for more detail
this.write8(0x0011, 0x10); // Enables polling for ‘New Sample ready’ when measurement completes
this.write8(0x010a, 0x30); // Set the averaging sample period(compromise between lower noise and increased execution time)
this.write8(0x003f, 0x46); // Sets the light and dark gain (upper nibble). Dark gain should not be changed.
this.write8(0x0031, 0xFF); // sets the # of range measurements after which auto calibration of system is performed
this.write8(0x0041, 0x63); // Set ALS integration time to 100ms
this.write8(0x002e, 0x01); // perform a single temperature calibration // of the ranging sensor
//Optional: Public registers - See data sheet for more detail
this.write8(0x001b, 0x09); // Set default ranging inter-measurement period to 100ms
this.write8(0x003e, 0x31); // Set default ALS inter-measurement period to 500ms
this.write8(0x0014, 0x24); // Configures interrupt on ‘New Sample Ready threshold event’
};
// Read range function - expects callback with two (2) args:
// - err: error code of module: 32 not ready for | 64 not completed measurement
// - val: range in mm if module err == 0 else device error code (see Table 12)
VL6180X.prototype.readRange = function(cb){
var rc = this._readRangeRC.bind(this); // ready check as funct w/ obj context
rc(5,10,rc,cb); // 5 tries, each retry 10ms (rcTimeoutTime) deferred
};
VL6180X.prototype._readRangeRC = function(triesLeft,rcTimeoutTime,rc,cb){
// ready check for measurement - and start measurement
var s = this.read8(C.VL6180X_REG_RESULT_RANGE_STATUS);
if(s & 0x01){ // ready for measurement
this.write8(C.VL6180X_REG_SYSRANGE_START, 0x01); // start measurement
var cc = this._readRangeCC.bind(this); // check completion as f w/ obj ctx
cc(6,12,cc,cb); // 6 tries, each retry 12ms (ccTimeoutTime) deferred
}
else{ // not ready yet for measurement
if(--triesLeft>0){ // retry ready check delayed/deferred
setTimeout(rc,rcTimeoutTime,triesLeft,rcTimeoutTime,rc,cb); // retry
}
else{
cb(32,s); // err in module = 32 / 0x20: not ready within...
} // ...tries-1 x rcTimeoutTime, device err code in val;
} // alternative: cb(32|s); combined err and undefined for val
};
VL6180X.prototype._readRangeCC = function(triesLeft,ccTimeoutTime,cc,cb) {
// completion check for measurement - and read measurement and clear interrupt
var s = this.read8(C.VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO);
if(s & 0x04){ // completed measurement
var range = this.read8(C.VL6180X_REG_RESULT_RANGE_VAL); // read range in mm
this.write8(C.VL6180X_REG_SYSTEM_INTERRUPT_CLEAR, 0x07); // clear interrupt
cb(0,range); // module and device err = 0, measured range in val
}
else{ // not completed measurement yet
if (--triesLeft>0){ // retry completion check delayed/deferred
setTimeout(cc,ccTimeoutTime,triesLeft,ccTimeoutTime,cc,cb); // retry
}
else{
cb(64,s); // err in module = 64 / 0x40: not completed within...
} // ...tries-1 x ccTimeoutTime, device err code in val;
} // alternative: cb(64|s); combined err and undefined for val
};
//Range status function
VL6180X.prototype.readRangeStatus = function() {
var status = this.read8(C.VL6180X_REG_RESULT_RANGE_STATUS) >> 4
return status;
};
exports.connect = function(i2c, options) {
return new VL6180X(i2c, options);
};