@cabinfo.eu/veml6030
Version:
A package to communicate with VEML chipset through I2C
649 lines (539 loc) • 21 kB
JavaScript
'use strict';
class VEML6030 {
static ALS_SETTING_REGISTER = 0x00;
static ALS_WH_REGISTER = 0x01;
static ALS_WL_REGISTER = 0x02;
static ALS_POWER_SAVE_REGISTER = 0x03;
static ALS_READ_REGISTER = 0x04;
static WHITE_READ_REGISTER = 0x05;
static ALS_INT_REGISTER = 0x06;
static READ_BASE_RESOLUTION = 0.0036;
constructor(options) {
const i2c = require('i2c-bus');
this.debug = (options && options.hasOwnProperty('debug')) ? options.debug : false;
this.VEML6030_ADDR = (options && options.hasOwnProperty('i2cAddress')) ? options.i2cAddress : 0x48;
this.gain = (options && options.hasOwnProperty('gain')) ? this.setGain(options.gain) : 0x00;
this.integrationTime = (options && options.hasOwnProperty('integrationTime')) ? this.setIntegrationTime(options.integrationTime) : 0x00;
this.ALSPersistenceProtectNumber = (options && options.hasOwnProperty('ALSPersistenceProtectNumber')) ? this.setALSPersistenceProtectNumber(options.ALSPersistenceProtectNumber) : 0x00;
this.ALSInterruptEnableSetting = (options && options.hasOwnProperty('ALSInterruptEnableSetting')) ? this.setALSInterruptEnable(options.ALSInterruptEnableSetting) : 0x00;
this.ALSShutDownSetting = (options && options.hasOwnProperty('ALSShutDownSetting')) ? this.setALSShutdown(options.ALSShutDownSetting) : 0x00;
if (this.debug){
console.debug('Constructor: VEML6030_ADDR: %o', this.VEML6030_ADDR);
console.debug('Constructor: gain: %o', this.getGain(this.gain));
console.debug('Constructor: integrationTime: %o', this.getIntegrationTime(this.integrationTime));
console.debug('Constructor: ALSPersistenceProtectNumber: %o', this.ALSPersistenceProtectNumber);
console.debug('Constructor: ALSInterruptEnableSetting: %o', this.ALSInterruptEnableSetting);
console.debug('Constructor: ALSShutDownSetting: %o', this.ALSShutDownSetting);
}
this.i2cBus = i2c.openSync((options && options.hasOwnProperty('i2cBusNumber')) ? options.i2cBusNumber : 1);
} // eo constructor
init() {
return new Promise((resolve, reject) => {
this.writeConfiguration()
.then(() => {
resolve();
})
.catch( error => reject(error));
});
} // eo init method
calculateLuxLevel(rawValue){
let integrationFactor;
let gainFactor;
switch(this.gain){
case 0x01 : {
gainFactor = 1;
break;
}
case 0x00 : {
gainFactor = 2;
break;
}
case 0x03 : {
gainFactor = 8;
break;
}
case 0x02 : {
gainFactor = 16;
break;
}
}
switch(this.integrationTime){
case 0x03 : {
integrationFactor = 1;
break;
}
case 0x02 : {
integrationFactor = 2;
break;
}
case 0x01 : {
integrationFactor = 4;
break;
}
case 0x00 : {
integrationFactor = 8;
break;
}
case 0x08 : {
integrationFactor = 16;
break;
}
case 0x0c : {
integrationFactor = 32;
break;
}
}
return rawValue * VEML6030.READ_BASE_RESOLUTION * gainFactor * integrationFactor;
} // eo calculateLuxLevel method
applyCorrectionFormula(rawValue){
return (6.0135e-13 * (rawValue ** 4)) - (9.3924e-09 * (rawValue ** 3)) + (8.1488e-05 * (rawValue ** 2)) + (1.0023e-00 * rawValue);
} // eo applyCorrectionFormula method
setGain(gain){
switch(gain){
case 0.125 : {
this.gain = 0x02;
break;
}
case 0.25 : {
this.gain = 0x03;
break;
}
case 1.0 : {
this.gain = 0x00;
break;
}
case 2.0 : {
this.gain = 0x01;
break;
}
default : {
this.gain = 0x00;
}
}
return this.gain;
} // eo setGain method
getGain(){
switch(this.gain){
case 0x03 : {
return 0.25;
}
case 0x02 : {
return 0.125;
}
case 0x01 : {
return 2.0;
}
case 0x00 : {
return 1.0;
}
}
} // eo getGain method
setIntegrationTime(integrationTime){
switch(integrationTime){
case 25 : {
this.integrationTime = 0x0c;
break;
}
case 50 : {
this.integrationTime = 0x08;
break;
}
case 100 : {
this.integrationTime = 0x00;
break;
}
case 200 : {
this.integrationTime = 0x01;
break;
}
case 400 : {
this.integrationTime = 0x02;
break;
}
case 800 : {
this.integrationTime = 0x03;
break;
}
default : {
this.integrationTime = 0x00;
}
}
return this.integrationTime;
} // eo setIntegrationTime method
getIntegrationTime(){
switch(this.integrationTime){
case 0x03 : {
return 800;
}
case 0x02 : {
return 400;
}
case 0x01 : {
return 200;
}
case 0x00 : {
return 100;
}
case 0x08 : {
return 50;
}
case 0x0c : {
return 25;
}
}
} // eo getIntegrationTime method
setALSPersistenceProtectNumber(protectNumber){
switch(protectNumber){
case 1 : {
this.ALSPersistenceProtectNumber = 0x00;
break;
}
case 2 : {
this.ALSPersistenceProtectNumber = 0x01;
break;
}
case 4 : {
this.ALSPersistenceProtectNumber = 0x02;
break;
}
case 8 : {
this.ALSPersistenceProtectNumber = 0x03;
break;
}
default : {
this.ALSPersistenceProtectNumber = 0x00;
}
}
return this.ALSPersistenceProtectNumber;
} // eo setALSPersistenceProtectNumber method
setALSInterruptEnable(protectNumber){
switch(protectNumber){
case false : {
this.ALSInterruptEnableSetting = 0x00;
break;
}
case true : {
this.ALSInterruptEnableSetting = 0x01;
break;
}
default : {
this.ALSInterruptEnableSetting = 0x00;
}
}
return this.ALSInterruptEnableSetting;
} // eo setALSPersistenceProtectNumber method
setALSShutdown(protectNumber){
switch(protectNumber){
case false : {
this.ALSShutDownSetting = 0x00;
break;
}
case true : {
this.ALSShutDownSetting = 0x01;
break;
}
default : {
this.ALSShutDownSetting = 0x00;
}
}
return this.ALSShutDownSetting;
} // eo setALSShutdown method
writeConfiguration(){
return new Promise((resolve, reject) => {
let command = (this.gain << 11) + (this.integrationTime << 6) + (this.ALSPersistenceProtectNumber << 4) + (this.ALSInterruptEnableSetting << 1) + (this.ALSShutDownSetting << 0);
if (this.debug){
console.log('Configuration: %o', command.toString(2));
}
this.i2cBus.writeWord(this.VEML6030_ADDR, VEML6030.ALS_SETTING_REGISTER, command, (error) => {
if (error) {
return reject(error);
}
else {
if(this.debug){
console.debug('writeConfiguration: configuration saved');
}
return resolve(true);
}
});
});
} // eo writeConfiguration method
async writeConfigurationSync() {
let command = (this.gain << 11) + (this.integrationTime << 6) + (this.ALSPersistenceProtectNumber << 4) + (this.ALSInterruptEnableSetting << 1) + (this.ALSShutDownSetting << 0);
if (this.debug){
console.log('Configuration: %o', command.toString(2));
}
this.i2cBus.writeWordSync(this.VEML6030_ADDR, VEML6030.ALS_SETTING_REGISTER, command);
if(this.debug){
console.debug('writeConfigurationSync: configuration saved');
}
} // eo writeConfigurationSync method
readSensorData(autoCalibrate = false) {
return new Promise((resolve, reject) => {
if (! autoCalibrate){
// No auto calibrate, make a simple measure.
this.i2cBus.readWord(this.VEML6030_ADDR, VEML6030.ALS_READ_REGISTER, (error, readValue) => {
if(error) {
return reject(error);
}
let rawLuxValue = this.calculateLuxLevel(readValue);
let luxValue = rawLuxValue;
let useCorrectionFormula = false;
if (readValue > 100){
luxValue = this.applyCorrectionFormula(rawLuxValue);
useCorrectionFormula = true;
}
let overflow = this.checkForOverflow(luxValue);
return resolve({
rawValue : readValue,
rawLuxValue: rawLuxValue,
luxValue : luxValue,
useCorrectionFormula: useCorrectionFormula,
gain : this.getGain(this.gain),
integrationTime : this.getIntegrationTime(this.integrationTime),
autocalibrate: false,
retry: 1,
overflow: overflow
});
});
}
else {
// Auto calibrate.
let readValue = 0;
let timeoutCount = 25;
let count = 0;
let hasValue = false;
// Set initial gain and integration time.
this.gain = this.setGain(0.125);
this.integrationTime = this.setIntegrationTime(100);
this.writeConfigurationSync();
while (! hasValue){
// Check if we should go to timeout.
if (count == timeoutCount){
hasValue = true;
return reject("Reading timeout");
}
// read value from I2C
readValue = this.i2cBus.readWordSync(this.VEML6030_ADDR, VEML6030.ALS_READ_REGISTER);
// Check if readed value is lower than 100.
if (readValue <= 100) {
// Readed value is lower than 100, increase resolution and make measure again.
if (this.debug){
console.debug('readValue: %o', readValue);
}
this.increaseResolution();
this.writeConfigurationSync();
}
else {
// Readed value is greater than 100, check if > 10 000.
if (readValue > 10000){
// Decrease resolution.
this.decreaseResolution();
this.writeConfigurationSync();
}
else {
// readValue i > 100 and < 10000, reading is ok.
hasValue = true;
}
}
count++;
}
let rawLuxValue = this.calculateLuxLevel(readValue);
let luxValue = rawLuxValue;
let useCorrectionFormula = false;
if (readValue > 100){
luxValue = this.applyCorrectionFormula(rawLuxValue);
useCorrectionFormula = true;
}
let overflow = this.checkForOverflow(luxValue);
return resolve({
rawValue : readValue,
rawLuxValue: rawLuxValue,
luxValue : luxValue,
useCorrectionFormula: useCorrectionFormula,
gain : this.getGain(this.gain),
integrationTime : this.getIntegrationTime(this.integrationTime),
autocalibrate: true,
retry: count,
overflow: overflow
});
}
});
} // eo readSensorData method
checkForOverflow(readValue){
let isOverflow = false;
if ( this.gain == 0x01 && this.integrationTime == 0x03 && readValue >= 236){
isOverflow = true;
}
if ( this.gain == 0x01 && this.integrationTime == 0x02 && readValue >= 472){
isOverflow = true;
}
if ( this.gain == 0x01 && this.integrationTime == 0x01 && readValue >= 944){
isOverflow = true;
}
if ( this.gain == 0x01 && this.integrationTime == 0x00 && readValue >= 1887){
isOverflow = true;
}
if ( this.gain == 0x01 && this.integrationTime == 0x08 && readValue >= 3775){
isOverflow = true;
}
if ( this.gain == 0x01 && this.integrationTime == 0x0c && readValue >= 7550){
isOverflow = true;
}
if ( this.gain == 0x00 && this.integrationTime == 0x03 && readValue >= 472){
isOverflow = true;
}
if ( this.gain == 0x00 && this.integrationTime == 0x02 && readValue >= 944){
isOverflow = true;
}
if ( this.gain == 0x00 && this.integrationTime == 0x01 && readValue >= 1887){
isOverflow = true;
}
if ( this.gain == 0x00 && this.integrationTime == 0x00 && readValue >= 3775){
isOverflow = true;
}
if ( this.gain == 0x00 && this.integrationTime == 0x08 && readValue >= 7550){
isOverflow = true;
}
if ( this.gain == 0x00 && this.integrationTime == 0x0c && readValue >= 15099){
isOverflow = true;
}
if ( this.gain == 0x03 && this.integrationTime == 0x03 && readValue >= 1887){
isOverflow = true;
}
if ( this.gain == 0x03 && this.integrationTime == 0x02 && readValue >= 3775){
isOverflow = true;
}
if ( this.gain == 0x03 && this.integrationTime == 0x01 && readValue >= 7550){
isOverflow = true;
}
if ( this.gain == 0x03 && this.integrationTime == 0x00 && readValue >= 15099){
isOverflow = true;
}
if ( this.gain == 0x03 && this.integrationTime == 0x08 && readValue >= 30199){
isOverflow = true;
}
if ( this.gain == 0x03 && this.integrationTime == 0x0c && readValue >= 60398){
isOverflow = true;
}
if ( this.gain == 0x02 && this.integrationTime == 0x03 && readValue >= 3775){
isOverflow = true;
}
if ( this.gain == 0x02 && this.integrationTime == 0x02 && readValue >= 7550){
isOverflow = true;
}
if ( this.gain == 0x02 && this.integrationTime == 0x01 && readValue >= 15099){
isOverflow = true;
}
if ( this.gain == 0x02 && this.integrationTime == 0x00 && readValue >= 30199){
isOverflow = true;
}
if ( this.gain == 0x02 && this.integrationTime == 0x08 && readValue >= 60398){
isOverflow = true;
}
if ( this.gain == 0x02 && this.integrationTime == 0x0c && readValue >= 120796){
isOverflow = true;
}
return isOverflow;
}
increaseResolution(){
let changed = false;
if (this.debug){
console.debug('increaseResolution (before): this.gain: %o', this.gain);
console.debug('increaseResolution (before): this.integrationTime: %o', this.integrationTime);
}
if (this.gain == 0x02 && ! changed){
// gain = 0.125 set to 0.25
this.setGain(0.25);
changed = true;
}
if (this.gain == 0x03 && ! changed){
// gain = 0.25 set to 1.0
this.setGain(1.0);
changed = true;
}
if (this.gain == 0x00 && ! changed){
// gain = 1.0 set to 2.0
this.setGain(2.0);
changed = true;
}
if (this.gain == 0x01 && ! changed){
// Maximum gain, set Integration time
if (this.integrationTime == 0x0c && ! changed){
// Integration time = 25 ms set to 50 ms
this.setIntegrationTime(50);
changed = true;
}
if (this.integrationTime == 0x08 && ! changed){
// Integration time = 50 ms set to 100 ms
this.setIntegrationTime(100);
changed = true;
}
if (this.integrationTime == 0x00 && ! changed){
// Integration time = 100 ms set to 200 ms
this.setIntegrationTime(200);
changed = true;
}
if (this.integrationTime == 0x01 && ! changed){
// Integration time = 200 ms set to 400 ms
this.setIntegrationTime(400);
changed = true;
}
if (this.integrationTime == 0x02 && ! changed){
// Integration time = 400 ms set to 800 ms
this.setIntegrationTime(800);
// changed = true;
}
}
if (this.debug){
console.debug('increaseResolution (after): this.gain: %o', this.gain);
console.debug('increaseResolution (after): this.integrationTime: %o', this.integrationTime);
}
} // eo increaseResolution method
decreaseResolution(){
let changed = false;
if (this.integrationTime == 0x03 && ! changed){
// Integration time = 800 ms set to 400 ms
this.setIntegrationTime(400);
changed = true;
}
if (this.integrationTime == 0x02 && ! changed){
// Integration time = 400 ms set to 200 ms
this.setIntegrationTime(200);
changed = true;
}
if (this.integrationTime == 0x01 && ! changed){
// Integration time = 200 ms set to 100 ms
this.setIntegrationTime(100);
changed = true;
}
if (this.integrationTime == 0x00 && ! changed){
// Integration time = 100 ms set to 50 ms
this.setIntegrationTime(50);
changed = true;
}
if (this.integrationTime == 0x08 && ! changed){
// Integration time = 50 ms set to 25 ms
this.setIntegrationTime(25);
changed = true;
}
if (this.integrationTime == 0x0c && ! changed){
// Minimum Integration time (25 ms), decrease gain
if (this.gain == 0x01 && ! changed){
// gain = 2.0 set to 1.0
this.setGain(1.0);
changed = true;
}
if (this.gain == 0x00 && ! changed){
// gain = 1.0 set to 0.25
this.setGain(0.25);
changed = true;
}
if (this.gain == 0x03 && ! changed){
// gain = 0.25 set to 0.125
this.setGain(0.125);
// changed = true;
}
}
} // eo decreaseResolution method
} // eo VEML6030 class
module.exports = VEML6030;