Measure DC Voltage ...
 
Notifications
Clear all

Measure DC Voltage and Current with Arduino

Page 2 / 2

Will
 Will
(@will)
Noble Member
Joined: 7 months ago
Posts: 1084
 

@holder3651 

According to ...

https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/

"the maximum reading rate is about 10,000 times a second".


ReplyQuote
Holder3651
(@holder3651)
Active Member
Joined: 1 month ago
Posts: 7
 

@will,

Thanks for the response.  I now have a working voltage recorder and LCD display based on the Hall-effect sensor.

I'm now trying to create a current data logger based on an ACS712 bought from Amazon - WayInTop-US.  The code works well but I have very odd results suggesting the device should have VCC connected to a much lower voltage than the Arduino nominal 5V or my 4020 reference voltage regulator chip.

The issue is that the A/D pin that's reading the ACS712 sensor gives a value that's too high. 

Has anyone else found similar issues with that brand?

The ACS712 device from WayInTop seems to be almost identical to the one Will used in his tutorial except the circuit components and pins are 'handed'. 

Oddly, the Amazon information indicates connecting VCC to 3.3V / 5V. I thought connecting VCC to the Reference 4.098V would be great. But, with nothing connected to the sensed terminals, the sketch shoes about 0.6A.  Connecting to the Arduino's 5V, the sketch shows 7.5A. In both, I changed to code to match the VCC voltage supplied. 

I have the centre signal pin going to A2 because A0 is in use for the hardware, and A1 is the voltage feather sensor.

I can see the A/D readings because I changed the code to summate the pin values over a series of readings, then divide by the number of readings, before calculating the apparent voltage. Then, I wrote out all of the data used in the calculations and the results.  All made sense, except the A/D readings. 

With 5V supplied

Serial.print(resADC,6); Serial.print(", ");
Serial.print(zeroPoint,4); Serial.print(", ");
Serial.print(scale_factor,4); Serial.print(", ");
Serial.print(VADC,4); Serial.print(", ");
Serial.print(Vout,4); Serial.print(", ");
Serial.print(Vout-zeroPoint,4); Serial.print(", ");
Serial.print(Current,4); Serial.println();
Gives:
0.004883, 2.5000, 0.0660, 613.0000, 2.9932, 0.4932, 7.4722
 

ReplyQuote
Inst-Tech
(@inst-tech)
Eminent Member
Joined: 2 months ago
Posts: 46
 

@holder3651 ,

Hi, just now looking at the results of your print out, and a couple of things come to mind...

First, I have a couple of questions:, have you measured your circuit with a multi meter on amp scale to see what is actually the current you are using.. I see by your ACS712 scaling that you are using a 30A module.  second, did you change the analogReference() command in you code to tell the Arduino that your using an external reference..this will make a big difference in how the ADC converts the counts to voltage.. example: the resolution of a 5 v reference is 0.004828125 mV/count, but for a 4.096 V external reference it is 0.004 mV/count. for more information on the analogReference() , see https://www.arduino.cc/en/Reference.AnalogReference

It will be more helpful if you can provide a copy of your code as well, as we are just guessing at what might be the problem.

hope this helps, good luck,

Regards,

   LouisR

 

LouisR


ReplyQuote
Holder3651
(@holder3651)
Active Member
Joined: 1 month ago
Posts: 7
 

@inst-tech 

I've set up the board using the 4020 reference connected to VCC.  And, changed the code as I believe I should. 

Rather than take multiple readings and average, with the risk of getting the wrong divider count, I disabled that and took one reading.  The results using the same print out code shown earlier were:

0.004000, 2.0480, 0.0660, 521.0000, 2.0840, 0.0360, 0.5455
0.004000, 2.0480, 0.0660, 522.0000, 2.0880, 0.0400, 0.6061
0.004000, 2.0480, 0.0660, 521.0000, 2.0840, 0.0360, 0.5455
0.004000, 2.0480, 0.0660, 523.0000, 2.0920, 0.0440, 0.6667
0.004000, 2.0480, 0.0660, 523.0000, 2.0920, 0.0440, 0.6667

0.004 is right for a 4.096 V refer and 1024 divisions, 2.046 is VRef/2, and 0.066 is correct for the 30A board. But the 521 to 523 count is off. The rest follows from the count and input values.

I've attached the diagnostic code that gave these results. 

WRT reference voltage use, the code includes:

const double vRef = 4.096;  // for use in the calculations
analogReference(EXTERNAL);
/*
Current Data Logger to SD Card and LCD Display
*/

#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

#define ECHO_TO_SERIAL 1  // Control whether data echoed to serial monitor for debugging
#define WRITE_TO_SD 0 // Control whether data is written to SD Card during degugging

// the digital pins that connect to the LEDs
//#define redLEDpin 2
//#define greenLEDpin 3

// The LCD shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

// These #defines make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7

RTC_PCF8523 RTC; // define the Real Time Clock object

// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;

// the logging file
File myFile;

// The voltage breakout board uses pin A1
// Define analog input
#define ANALOG_AIN_PIN A2

// Variables for measured voltage and calculated current on ACS712
double Vout = 0;
double VADC = 0;
double Current = 0;

// Constants for Scale Factor
// Use one that matches your version of ACS712
 
//const double scale_factor = 0.185; // 5A
//const double scale_factor = 0.1; // 20A
const double scale_factor = 0.066; // 30A
 
// Constants for A/D converter resolution
// Arduino has 10-bit ADC, so 1024 possible values
// Reference voltage is 5V if not using AREF external reference
// Zero point is half of Reference Voltage

const double vRef = 4.096;
const double resConvert = 1024;
double resADC = vRef/resConvert;
double zeroPoint = vRef/2;

// Timer for current measurements
unsigned long startMillis;
unsigned long currentMillis;
unsigned long elapsedMillis;

void error(char *str)
{
  Serial.print("error: ");
  Serial.println(str);
  
  // red LED indicates error
  //digitalWrite(redLEDpin, HIGH);

  while(1);
}

void setup(void) {

  Serial.begin(9600);

  // Debugging LCD output
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);

  // Use external voltage reference
  analogReference(EXTERNAL);
  
  // Setup Serial Monitor
  
  // use debugging LEDs
  //pinMode(redLEDpin, OUTPUT);
  //pinMode(greenLEDpin, OUTPUT);
  
  // Setup SD Card
   #if WRITE_TO_SD
   while (!Serial) {
    ; // Wait for serial port to connect
   }

   Serial.print("Initializing SD Card ...");

   if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    while(1);
   }
   Serial.println("initialization done.");

   // Open the file. Note that only one file can be open at a time.
   myFile = SD.open("Output.txt", FILE_WRITE);

   // if the file opened OK, write to it:
   if (myFile) {
    Serial.print("Writing test to file.");
    myFile.println("Current recording at short intervals");
    // Close the file
    myFile.close();
    Serial.println("Done");
   } else {
    // if the file didn't open, print an error
    Serial.println("error opening file");
   }
#endif

  // connect to RTC
  Wire.begin();  
  if (!RTC.begin()) {
  #if ECHO_TO_SERIAL
    Serial.println("RTC failed");
  #endif  //ECHO_TO_SERIAL
  #if WRITE_TO_SD    
    myFile.println("RTC failed");
  #endif
  }
  
  #if ECHO_TO_SERIAL
  Serial.println("millisecs, Amp");
  #endif //ECHO_TO_SERIAL
  #if WRITE_TO_SD 
  myFile = SD.open("Output.txt", FILE_WRITE);
  Serial.println("millisecs, Amps");
   // Close the file
  myFile.close();
  #endif

  // Start timer
 startMillis = millis();  //initial start time
}

void loop(void) {
  
//Measure current at about 1s intervals using ACS712  
//Vout is read 10 Times for precision of current calculation
  // Reset Vout
  Vout = 0;
  VADC = 0;

  //for(int i = 0; i < 10; i++) {
    VADC = (VADC + analogRead(ANALOG_AIN_PIN));   
    delay(1);
  //}
  
  // Get average of i-readings for Vout in mv
  Vout = VADC * resADC / 1;
  
  // Convert Vout into Current using Scale Factor
  Current = (Vout - zeroPoint)/scale_factor;                   
 
  // fetch the time
 currentMillis = millis();  //get the current "time" (actually the number of ms elapsed)
 elapsedMillis = currentMillis - startMillis;
 
  // Print to the LCD
  lcd.setBacklight(WHITE);
  lcd.setCursor(1,0);
  lcd.print("Volts = "); lcd.print(Vout-zeroPoint, 4); lcd.println("     ");
  lcd.setCursor(1,1);
  lcd.print("Current = "); lcd.print(Current, 4); lcd.println("     ");

  // Print Vout and Current                   
 #if ECHO_TO_SERIAL 
  Serial.print(resADC,6); Serial.print(",  ");
  Serial.print(zeroPoint,4); Serial.print(",  ");
  Serial.print(scale_factor,4); Serial.print(",  ");
  Serial.print(VADC,4); Serial.print(",  ");
  Serial.print(Vout,4); Serial.print(",  ");
  Serial.print(Vout-zeroPoint,4); Serial.print(",  ");
  Serial.print(Current,4); Serial.println();
  //Serial.print(elapsedMillis);
  //Serial.print(" ms ,Vout = ");           
  //Serial.print(Vout,2); 
  //Serial.print(" Volts");                            
  //Serial.print("\t Current = ");                  
  //Serial.print(Current,2);
  //Serial.println(" Amps");  
  //Serial.println();                           
 #endif

#if WRITE_TO_SD 
  myFile = SD.open("Output.txt", FILE_WRITE);
  myFile.print(elapsedMillis); 
  myFile.print(" ms, Vout = ");
  myFile.print(Vout, 2); 
  myFile.print(" Volts"); 
  myFile.print("\t Current = ");
  myFile.print(Current, 2);
  myFile.println(" Amps");
   // Close the file
  myFile.close();
#endif

// Short delay
  delay(950);  
//}
}

 


Inst-Tech liked
ReplyQuote
Holder3651
(@holder3651)
Active Member
Joined: 1 month ago
Posts: 7
 

Physically, the VCC on ACS712 board is connected to the 4020 board 4.096V output pin and to the Uno VRef pin. 


ReplyQuote
Inst-Tech
(@inst-tech)
Eminent Member
Joined: 2 months ago
Posts: 46
 

@holder3651 

See attached document for how to wire up an external voltage reference

also note the following:

Arduino megaAVR Boards (Uno WiFi Rev2)

  • DEFAULT: a built-in 0.55V reference

  • INTERNAL: a built-in 0.55V reference

  • VDD: Vdd of the ATmega4809. 5V on the Uno WiFi Rev2

  • INTERNAL0V55: a built-in 0.55V reference

  • INTERNAL1V1: a built-in 1.1V reference

  • INTERNAL1V5: a built-in 1.5V reference

  • INTERNAL2V5: a built-in 2.5V reference

  • INTERNAL4V3: a built-in 4.3V reference

  • EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference

 example: analogReference(EXTERNAL)

Notes and Warnings

After changing the analog reference, the first few readings from analogRead() may not be accurate.

Don’t use anything less than 0V or more than 5V for external reference voltage on the AREF pin! If you’re using an external reference on the AREF pin, you must set the analog reference to EXTERNAL before calling analogRead(). Otherwise, you will short together the active reference voltage (internally generated) and the AREF pin, possibly damaging the microcontroller on your Arduino board.

Alternatively, you can connect the external reference voltage to the AREF pin through a 5K resistor, allowing you to switch between external and internal reference voltages. Note that the resistor will alter the voltage that gets used as the reference because there is an internal 32K resistor on the AREF pin. The two act as a voltage divider, so, for example, 2.5V applied through the resistor will yield 2.5 * 32 / (32 + 5) = ~2.2V at the AREF pin.

regards,

LouisR

 

LouisR


ReplyQuote
Inst-Tech
(@inst-tech)
Eminent Member
Joined: 2 months ago
Posts: 46
 

@holder3651 

Question: How do you know the count is off.. have you measured the current in the circuit with a multi-meter in (current mode)? The math and the formulas look ok, so unless you have a floating ground, I can see no reason why this shouldn't work.. Check your grounding from the ACS712 to the Arduino to make sure you don't have a bad connection or a broken wire.. check this with an ohm meter to rule that out.. those tiny wires are easy to break!  good luck,

Regards,

LouisR

LouisR


ReplyQuote
Holder3651
(@holder3651)
Active Member
Joined: 1 month ago
Posts: 7
 

I’ll check the soldering tomorrow. 

Your last but one response showed the connections for the voltage sensor but my problem is with the ACS712 current sensor.  Apart from checking everything is soldered well, my doubts lie with how the ACS712 VCC pin should be connected.  I connected it to the 4020 board’s 4.096V pin that is already connected to the Arduino ARef pin. But now I’m wondering if that’s correct. 

Note, the same Adafruit data logger board that I used to successfully set up 25V voltage and 4020 reference boards, was modified by adding the ACS712. The signals from each sensor board were taken to different pins, A1 and A2, but there are interconnections because both are on the same data logger and share grounds and +ve.  

For a build with only the ACS712 and the 4020 voltage reference, it isn’t clear to me how they should be wired.  Without the 4020, the wiring would be as your tutorial, i.e. VCC to Arduino 5V, Signal to A2 or similar and -Ve to Arduino GND.  But with the 4020 added to Arduino ARef, should the ACS712 wiring change so VCC connects elsewhere? 

At the root of this is perhaps my lack of understanding of how the Arduino A/D system works without and with an external VRef. My understanding is that the ACS712 Hall-effect current sensor works by splitting the voltage between GND and VCC pins so that a portion related to current goes to the Signal pin with the A/D converter generates a digital code. 


Inst-Tech liked
ReplyQuote
Inst-Tech
(@inst-tech)
Eminent Member
Joined: 2 months ago
Posts: 46
 

@holder3651 

I think your problem lies in the connection to the 4020 ref board. It is for reference ONLY.. no other connections to it as it has no capability to source any current.. The ACS712 VCC is connected to the Arduino +5v on the board, See attached file below. The reference board 4020 only affect the reference voltage used by the ADC mux., not the 5v buss that the ACS712 is using for power.. With the external reference board you get a little more resolution for the ADC , ~ 4 mV, (0.004) as opposed to the internal reference of 5v +/- 50 mV (at 1% tolerance) of 4.883 mV ( 0.004883). this will, in affect the accuracy of your counts in the ADC mux. But I digress.. I digital & analog inputs are subject to wild variations when their inputs are not connected, or grounding issues are present..Your on the right track.. just stick with it, and I'm sure you'll fix the problem..BTW,The code for your project is impressive..I'm not new to programming, but I'm just learning C++ after 30+ years of using MS VBA, and other industrial OOP like PLC (Programmatical Load Controller) and DCS (Distributed Control Systems) to program  industrial control systems.. At 75, I'm still learning, lol

Good luck, and keep me advised.. I'll probably be hitting you up on tips on programming.. it's a steep curve for ol' timers like me...hehehe

Regards,

LouisR

ACS712 connection to Arduino

 

 

LouisR


ReplyQuote
Holder3651
(@holder3651)
Active Member
Joined: 1 month ago
Posts: 7
 

I've took the ACS712 off the same data logger board as the 30V voltage sensor and LM4040 reference voltage card, and now have 'sensible' zero results from the ACS712. That is the readings with no current is close enough to zero that it is within the 512 +/- 2 bits accuracy limit that might be expected of the A/D converter.  I have to get another LM4040 reference voltage card so see if that makes any difference. 

Using a multimeter to check the Arduino nominal 5V to GND, I found the voltage was actually a bit lower than 5V.  That lead me to change the code to more replicate the voltage.  And, then to lower it a bit more.  Surprisingly, the specified vRef didn't really alter the measured zero with no external current.

In western Canada, I'm at the end of a long supply line for less common Adafruit parts, so it might be a while before I get another LM4040 reference voltage card.  The shipping cost is much more than the item, too. So, it might be a while before I test the setup with an LM4040 added. 

My next step is to measure check values from the ACS712 with a know current as you suggested. 

To summarise, it seems there was some odd interaction between the two measurement cards or the ACS712 and the LM4040 aren't compatible, that led to the patently incorrect readings. 


Inst-Tech liked
ReplyQuote
Inst-Tech
(@inst-tech)
Eminent Member
Joined: 2 months ago
Posts: 46
 

Good job!..Indeed, I did some  measurement checking my self on the LM4020, and the Arduino Vcc +5V pin & Vref pin with external circuit loading, and unloading:  In the attached file are  are some of the results that I found. In conclusion, The results show that using the Arduino +5v pin to power anything over a few mA will pull the 5V down.. So I recommend using external power supply to power your circuits that are being connected to the Arduino, inputs and outputs.. making sure you tie the negative of the supply to the Arduino gnd connection to prevent ground loops, which can severely impact your readings.

See attached word doc for results of test:

kind regards,

LouisR

 

LouisR


ReplyQuote
Holder3651
(@holder3651)
Active Member
Joined: 1 month ago
Posts: 7
 

You are most helpful to do that work. I’ll have to wait a bit for parts. And, find a way to rig up a separate PS.  Unlike you, I don’t have a bench power supply.   

I’m now looking at the Adafruit ADS1115 and ADS1015, which offer much greater precision in the analogue - digital conversion, albeit at a fair loss of sampling speed. 

I’ll likely go silent for a while as I deal with other matters and supply chains.


Inst-Tech liked
ReplyQuote
Inst-Tech
(@inst-tech)
Eminent Member
Joined: 2 months ago
Posts: 46
 

Good luck to you @Holder3651... let us know how it turns out..

Kind regards,

LouisR

LouisR


ReplyQuote
Page 2 / 2