Hello,
I try to interface the Voltemer based on ADS1115 in nodejs.
The only given sample is based on C++ and Arduino code, but there is no detailled documentation on which command and parameters can be sent to register, in order to get measure for each range of voltage.
I try to measure a battery voltage, like the picture here.

Here is my code. Can you give me more information ?
- which element is to read : MUX_DIFF_0_1 : (0x0000), MUX_DIFF_0_3 : (0x1000), MUX_DIFF_1_3 : (0x2000), MUX_DIFF_2_3 : (0x3000), MUX_SINGLE_0 : (0x4000), MUX_SINGLE_1 : (0x5000), MUX_SINGLE_2 : (0x6000), MUX_SINGLE_3 : (0x7000) ?
 - which mathematical operation is to do with the value read in ther register ? multiply with what, depending of what (gain ?) ?
Thank you for information. 
/* sample*/
var ADS1X15 = {};
/* Register values. Most of these aren't used
and this is hidden, so it'll get optimised out
when minified */
ADS1X15.CONFIG = {
	OS_MASK      : (0x8000),
	OS_SINGLE    : (0x8000),  // Write: Set to start a single-conversion
	OS_BUSY      : (0x0000),  // Read: Bit = 0 when conversion is in progress
	OS_NOTBUSY   : (0x8000),  // Read: Bit = 1 when device is not performing a conversion					
	MUX_MASK     : (0x7000),
	MUX_DIFF_0_1 : (0x0000),  // Differential P = AIN0, N = AIN1 (default)
	MUX_DIFF_0_3 : (0x1000),  // Differential P = AIN0, N = AIN3
	MUX_DIFF_1_3 : (0x2000),  // Differential P = AIN1, N = AIN3
	MUX_DIFF_2_3 : (0x3000),  // Differential P = AIN2, N = AIN3
	MUX_SINGLE_0 : (0x4000),  // Single-ended AIN0
	MUX_SINGLE_1 : (0x5000),  // Single-ended AIN1
	MUX_SINGLE_2 : (0x6000),  // Single-ended AIN2
	MUX_SINGLE_3 : (0x7000),  // Single-ended AIN3
							
	PGA_MASK     : (0x0E00),
	PGA_6_144V   : (0x0000),  // +/-6.144V range = Gain 2/3
	PGA_4_096V   : (0x0200),  // +/-4.096V range = Gain 1
	PGA_2_048V   : (0x0400),  // +/-2.048V range = Gain 2 (default)
	PGA_1_024V   : (0x0600),  // +/-1.024V range = Gain 4
	PGA_0_512V   : (0x0800),  // +/-0.512V range = Gain 8
	PGA_0_256V   : (0x0A00),  // +/-0.256V range = Gain 16
							
	MODE_MASK    : (0x0100),
	MODE_CONTIN  : (0x0000),  // Continuous conversion mode
	MODE_SINGLE  : (0x0100),  // Power-down single-shot mode (default)
						
	DR_MASK      : (0x00E0),  
	DR_128SPS    : (0x0000),  // 128 samples per second
	DR_250SPS    : (0x0020),  // 250 samples per second
	DR_490SPS    : (0x0040),  // 490 samples per second
	DR_920SPS    : (0x0060),  // 920 samples per second
	DR_1600SPS   : (0x0080),  // 1600 samples per second (default)
	DR_2400SPS   : (0x00A0),  // 2400 samples per second
	DR_3300SPS   : (0x00C0),  // 3300 samples per second
					 
	CMODE_MASK   : (0x0010),
	CMODE_TRAD   : (0x0000),  // Traditional comparator with hysteresis (default)
	CMODE_WINDOW : (0x0010),  // Window comparator
						
	CPOL_MASK    : (0x0008),
	CPOL_ACTVLOW : (0x0000),  // ALERT/RDY pin is low when active (default)
	CPOL_ACTVHI  : (0x0008),  // ALERT/RDY pin is high when active
					
	CLAT_MASK    : (0x0004),  // Determines if ALERT/RDY pin latches once asserted
	CLAT_NONLAT  : (0x0000),  // Non-latching comparator (default)
	CLAT_LATCH   : (0x0004),  // Latching comparator
						 
	CQUE_MASK    : (0x0003),
	CQUE_1CONV   : (0x0000),  // Assert ALERT/RDY after one conversions
	CQUE_2CONV   : (0x0001),  // Assert ALERT/RDY after two conversions
	CQUE_4CONV   : (0x0002),  // Assert ALERT/RDY after four conversions
	CQUE_NONE    : (0x0003)  	// Disable the comparator and put ALERT/RDY in high state (default)
};
/*
Voltage_measurement_range		Maximum_input_DC_voltage(V)		Minimum_resolution(mV)		Gain_factor
PAG_4096(Calibrated)				±128													7.85											0.125
2.048												64														3.93											0.0625
1.024												32														1.96											0.03125
0.512												16														0.98											0.015625
PAG_256(Calibrated)					±8														0.49											0.007813
*/
ADS1X15.GAINS = {
	6144 : 	ADS1X15.CONFIG.PGA_6_144V,  // +/-6.144V range = Gain 2/3
	4096 : 	ADS1X15.CONFIG.PGA_4_096V,  // +/-4.096V range = Gain 1
	2048 : 	ADS1X15.CONFIG.PGA_2_048V,  // +/-2.048V range = Gain 2 (default)
	1024 : 	ADS1X15.CONFIG.PGA_1_024V,  // +/-1.024V range = Gain 4
	512 : 	ADS1X15.CONFIG.PGA_0_512V,  // +/-0.512V range = Gain 8
	256 : 	ADS1X15.CONFIG.PGA_0_256V  // +/-0.256V range = Gain 16;
};
ADS1X15.VOLT_RANGE = {
	"0_8V": 256,
	"0_16V": 512,
	"0_32V": 1024,
	"0_64V": 2048,
	"0_128V": 4096
};
ADS1X15.MULTICATOR = {
	6144: 0.187500,
	4096: 0.125000,
	2048: 0.062500,
	1024: 0.031250,
	512: 0.015625,
	256: 0.007813
};
ADS1X15.COEFFICIENT = 0.015918958;
ADS1X15.DIFFS = {
	"0,1" : ADS1X15.CONFIG.MUX_DIFF_0_1, // Differential P = AIN0, N = AIN1 (default)
	"0,3" : ADS1X15.CONFIG.MUX_DIFF_0_3, // Differential P = AIN0, N = AIN3
	"1,3" : ADS1X15.CONFIG.MUX_DIFF_1_3, // Differential P = AIN1, N = AIN3
	"2,3" : ADS1X15.CONFIG.MUX_DIFF_2_3  // Differential P = AIN2, N = AIN3
};
ADS1X15.SINGLE_CHANELS = [
	ADS1X15.CONFIG.MUX_SINGLE_0,
	ADS1X15.CONFIG.MUX_SINGLE_1,
	ADS1X15.CONFIG.MUX_SINGLE_2,
	ADS1X15.CONFIG.MUX_SINGLE_3
];
ADS1X15.REG = {
	MASK : 3,
	CONVERT : 0,
	CONFIG : 1,
	LOWTHRESH : 2,
	HITHRESH : 3
};
// prototypes
if (Number.prototype.toHexa === undefined) {
	Number.prototype.toHexa = function( len) {
		return "0x" + this.toString( 16).padStart( len, '0');
	}
}
if (Buffer.prototype.toHexa === undefined) {
	Buffer.prototype.toHexa = function() {
		let str = "";
		let arr = [...this];
		arr.forEach( a => {
			str = '0x' + a.toString(16).padStart( 2, '0') + ' ' + str;
		});
		return str;
	}
}
// used internally for writing to the ADC
function writeRegister( i2c, register, value) {
	const funcName = "writeRegister";
	
	const buff = Buffer.from( [register & 3, value >> 8, value & 0xFF]);
	console.log( `${funcName}> write to ${addr.toHexa(2)}, buff: ${buff.toHexa()}...`);
	try {
		let nbBytesWritten = i2c.i2cWriteSync( addr, 3, buff);
		console.log( `${funcName}> ${nbBytesWritten} written`);
	} catch( err1) {
		console.log( `${funcName}> write FAILS > err1: ${err1}`);
	}
}
// used internally for reading from the ADC
function readRegister( i2c, register) {
	const funcName = "readRegister";
	let value = null;
	
	do {
		const buffW = Buffer.from( [register] );
		console.log( `${funcName}> write to ${addr.toHexa(2)} register: ${register.toHexa(2)}...`);
		try {
			i2c.i2cWriteSync( addr, 1, buffW);
		} catch( err1) {
			console.log( `${funcName}> write FAILS > err1: ${err1}`);
			break;
			//!!!!!
		}
		
		let buffR = Buffer.from( [ 0, 0]);
		try {
			let nbBytesRead = i2c.i2cReadSync( addr, 2, buffR);				
			value = (buffR[0] << 8) | buffR[1];
			console.log( `${funcName}> ${nbBytesRead} read, buffR: ${buffR.toHexa()}, value: ${value}`);
		} catch( err2) {
			console.log( `${funcName}> read FAILS > err2: ${err2}`);
			break;
			//!!!!!
		}
	} while( false);
	
	return value;
}
function getADC( i2c, channelSpec, callback) {
		
	let config = ADS1X15.CONFIG.CQUE_NONE    | // Disable the comparator (default val)
								ADS1X15.CONFIG.CLAT_NONLAT  | // Non-latching (default val)
								ADS1X15.CONFIG.CPOL_ACTVLOW | // Alert/Rdy active low   (default val)
								ADS1X15.CONFIG.CMODE_TRAD   | // Traditional comparator (default val)
								ADS1X15.CONFIG.DR_1600SPS   | // rate: 1600 samples per second (default)
								ADS1X15.CONFIG.MODE_SINGLE;   // Single-shot mode (default)
										
	// single ended (channelSpec is a number) or differential (channelSpec is array w/ valid channel duo)
	if ("number" == typeof channelSpec) { // Set single-ended input channel
		if ( ! ADS1X15.SINGLE_CHANELS.includes( channelSpec)) {
			throw new Error( `Invalid single-ended channelSpec ${channelSpec.toHexa()} ! use one of ADS1X15.SINGLE_CHANELS ${ADS1X15.SINGLE_CHANELS}`);
		}
		config |= channelSpec;
	} else { 
		// Set differential input channels from channelSpec
		if ( ! (channelSpec in ADS1X15.DIFFS)) {
			throw new Error( `Invalid differention channelSpec ${channelSpec} ! use one of ADS1X15.DIFFS`);
		}
		let diffChannel = ADS1X15.DIFFS[ channelSpec];
		config |= diffChannel;
	} 
	
	// Set PGA/voltage range
	config |= ADS1X15.GAINS[ gain];
	
	// Set 'start single-conversion' bit
	config |= ADS1X15.CONFIG.OS_SINGLE;
	
	// Write config register to the ADC
	writeRegister( i2c, ADS1X15.REG.CONFIG, config);
	
	// Wait for the conversion to complete
	setTimeout(function() {
		// Read the conversion results
		let d = readRegister( i2c, ADS1X15.REG.CONVERT);
		if ( d & 0x8000) {
			d -= 65535; // sign
		}
		
		let volts = parseFloat( d) * resolution;
		console.log( `d: ${d}, resolution: ${resolution}, volts: ${volts}`);
		
		callback( volts); 
	}, 8);
}
var i2cBus = null;
var DEV_I2C = 1;
var I2C_BUS = require("i2c-bus");
console.log( `VoltMeter.js > on linux > i2c-bus loaded.`);
var addr = 0x49;
var voltRange = "0_8V";
var gain = ADS1X15.VOLT_RANGE[ voltRange];
var multiplicator = ADS1X15.MULTICATOR[ gain];
var resolution = parseFloat( multiplicator / ADS1X15.COEFFICIENT);
console.log( `gain: ${gain.toHexa()}, multiplicator: ${multiplicator}, COEFFICIENT: ${ADS1X15.COEFFICIENT}, resolution: ${resolution}...`);
i2cBus = I2C_BUS.open( DEV_I2C, err1 => {
	if (err1) {
		console.log( `i2c.open FAILS > err1: ${err1}`);
	} else {
		
		setInterval( function() {
			// getADC( i2cBus, ADS1X15.CONFIG.MUX_SINGLE_0, function( value) {
			getADC( i2cBus, "0,1", function( value) {
				console.log( `${new Date().toISOString()} > mesure ${value} volts`);
			});
		}, 1000);
	}
});
Best regards.
