Voltmeter M5Stack (ADS1115) interface
-
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.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login