ADS1115 ACS712 Sketch timing

Hi All,

I'm trying to make a high-precision digital multimeter and watt-meter. (Going for 100uA and 1~2mV resolution.)

I am using the ACS712ELCTR-05B-T for current measurement, and the Adafruit ADS1115 16-bit ADC to read the voltage and current values.
My test board is an Uno R3 @ 16MHz (when built I will transfer to a 5v 16MHz Pro Mini).

My problems are twofold:

  1. The output from the ACS712 is massively unstable.
  2. My code for reading the values is too slow!

I'm mainly after help with point 2 here - I'm pretty sure the instability will be solved with a replacement 712, or better grounding when I make it off the breadboard.

Here's my code (so far):

#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include <LiquidCrystal_I2C.h>

 Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
 #define ADS1115_REG_CONFIG_DR_860SPS;
 
 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
 
 int i;
 float avVolt = 0;
 float avAmp = 0;
 float lastVolt = 0;
 float lastAmp = 0;
 float numLoops = 50.00;
 long previousMillis = 0;
 
void setup(void)
{
  Serial.begin(115200);
  Serial.println("Hello!");
  
  lcd.begin(20,4);
  lcd.backlight();
  lcd.setCursor(1,0);
  lcd.print("Digital Multimeter");
  lcd.setCursor(7,1);
  lcd.print("V1.0.0");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1,0);
  lcd.print("V = ");
  lcd.setCursor(1,1);
  lcd.print("A = ");
  lcd.setCursor(1,3);
  lcd.print("Loop Millis = ");
  
  Serial.println("Getting differential reading from AIN0 (P) and AIN1 (N)");
  Serial.println("ADC Range: +/- 4.096V (1 bit = 0.125mV)");
  
  // The ADC input range (or gain) can be changed via the following
  // functions, but be careful never to exceed VDD +0.3V max, or to
  // exceed the upper and lower limits if you adjust the input range!
  // Setting these values incorrectly may destroy your ADC!
  //                                                                ADS1015  ADS1115
  //                                                                -------  -------
  // ads.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
     ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
  // ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1 bit = 1mV      0.0625mV
  // ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
  // ads.setGain(GAIN_EIGHT);      // 8x gain   +/- 0.512V  1 bit = 0.25mV   0.015625mV
  // ads.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV
  
  ads.begin();
}

void loop(void)
{  
  unsigned long currentMillis = millis();
  
  for (i = 0; i < numLoops; i++) {
  
  int16_t Vresults;
  int16_t Aresults;
  
  Vresults = ads.readADC_Differential_0_1();  
  Aresults = ads.readADC_Differential_2_3();
  
  avVolt = lastVolt + Vresults;
  avAmp = lastAmp + Aresults;
  
  lastVolt = avVolt;
  lastAmp = avAmp;
  //Serial.print(i);
  //Serial.print(" ");
  
  //delay(1);
  
  }
  
  float Vmultiplier = 0.000125F; /* ADS1115  @ +/- 4.096V gain_1 (16-bit results) */
  float Amultiplier = 0.000125F * (1 / 0.185);
 
  float Vval = ((avVolt * Vmultiplier) / numLoops);
  float Aval = ((avAmp * Amultiplier) / numLoops) - (2.5339 * (1 / 0.185));
  
  //Serial.println();
  //Serial.print("V = ");
  //Serial.println(Vval, 3);
  //Serial.print("I = ");
  //Serial.println(Aval, 4);
  
  lcd.setCursor(5,0);
  lcd.print(Vval, 3);
  lcd.setCursor(5,1);
  lcd.print(Aval, 4);
  
  lastVolt = 0;
  lastAmp = 0;
  avVolt = 0;
  avAmp = 0;
  //delay(1);
  
  previousMillis = millis() - currentMillis;
  
  lcd.setCursor(15,3);
  lcd.print(previousMillis);
  //Serial.print("Previous Millis = ");
  //Serial.println(previousMillis);
}

The ADS1115 should be able to take 860 samples / second. I know I'm doing maths in the smoothing loop, but it's hardly rocket science!

At numLoops = 50, the LCD updates at 915 millis. If I remove the LCD, it still only updates at 904 millis.
At numLoops = 100, the LCD updates at 1815 millis, and 1804 millis with serial.

This leads me to believe its the "ads.readADC_Differential_x_x()" commands which are taking all the time.

Far from 860SPS, I'm only achieving ~55SPS!!

My ultimate aim (obviously there are more calculations to be added later when Watts, Wh and Ah are being calculated) is for a 3-4Hz LCD update, with 100+ samples being averaged.

Can anyone point me to why this is running so slowly?!

Thank you,
Tom.

 #define ADS1115_REG_CONFIG_DR_860SPS;

#define statements rarely end with ;. Why does yours?

Can anyone point me to why this is running so slowly?!

I seriously doubt that the commented out code is the problem. So, why did you post it? Get rid of commented out code before posting.

ACS712 is not in any way high precision - you need a calibrated 4-terminal shunt
resistor to measure current accurately.