Current Sensor ACS714 Wandering Values

Hello everyone,

My first post & and I'm a newbie to Arduino so forgive me if I'm being a bit stupid.
I've hooked up a ACS714 (-30A to +30A), a RTC and SD card onto my MEGA (also fitted with Ethernet Shield but removing it makes no difference) but am a bit perplexed as to why, with nothing connected, the sensorValue wanders around from about 506 to 511. I was expected a little fluctuation but around 0.4A seems a lot. I have my ACS board connected to my MEGA as follows:

OUT: A0
Vcc: 5v
GND: GND

Should I be using a resistor anywhere?
Is there a reference GND I should be using?
and finally do I have my maths right for calculating the mA readings - as hunting around the internet there seems to be several ways of doing this.

Any advice gratefully received...

Here's my code:

#include <LiquidCrystal.h> //For the LCD
#include <RTClib.h>// For the RTC
#include <Wire.h> //For I2C comms
#include <SdFat.h> // Include the standard SD card library

SdFat sd; //alias for the SD library
SdFile DataFile; //alias for the datalog file
const int chipSelect = 53; //Initialise the SD card outputs on the Arduino. Mega = 53

// initialize the LCD library with the numbers of the interface pins. You can use any (but wire to those specified obviously!)
LiquidCrystal lcd(22, 23, 24, 25, 26, 27); //LCD pins RS(4), DB4(11), DB5(12), DB6(13), DB7(14)

RTC_DS1307 RTC; //Initialise the RTC

int analogInPin = A0; // Analog input pin that the carrier board OUT is connected to
int sensorValue = 0; // value read from the carrier board
int outputValue = 0; // output in milliamps
String TimeString=""; //Used to concatenate the time & date string
int lastTime = -1; //Used to set a time interval
int led = 13;//LED to show logging

void setup() {

Serial.begin(9600); // initialize serial communications at 9600 bps:
lcd.begin(20, 4);// LCD set up. Set the LCD's number of columns and rows:
Wire.begin();//set off the I2C comand
RTC.begin(); //Start the RTC
//RTC.adjust(DateTime(DATE, TIME)); //Running this sets the RTC Clock via the controller PC
pinMode(chipSelect, OUTPUT); //Set SD Chip Select pin on the Arduino as output (even if not using this function)
pinMode(led, OUTPUT);
}

void loop() {

{digitalWrite(led, LOW);} // turn the LED off by making the voltage LOW
delay(500);
DateTime now = RTC.now(); //Get the Time
int time = now.minute();

// read the analog in value:
sensorValue = analogRead(analogInPin);
// convert to milli amps
outputValue = ((long)sensorValue - 512 ) * 73.982L;
//outputValue = ((long)sensorValue - 512 ) * 234375 / 4000000;
//outputValue = ( ((long)sensorValue * 5000 / 1024) - 2500 ) * 1000 / 66;
/*
Analog read produces a value of 0-1023, equating to 0v to 5v.
With a sensitivity of 66 mV per A the optimized -30 to 30 range
would be (Vcc/2)-1.98V to (Vcc/2)+1.98V (0.52V to 4.48V).
That's something like .073982 A per step. 73,982 microamps per step.
*/

// lcd.clear();
lcd.setCursor(0,0);
lcd.print(TimeString);
lcd.setCursor(0,1);
lcd.print(sensorValue);
lcd.setCursor(0,2);
lcd.print(outputValue);

if (abs(time - lastTime) >= 1)
{
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)

//create the time string
TimeString=String(now.day(),DEC) + "/" + String(now.month(),DEC) + "/" + String(now.year(),DEC) + " "

  • String(now.hour(),DEC) + ":" + String(now.minute(),DEC) + ":" + String(now.second(),DEC);

// print the results to the serial monitor:
/*
Serial.print(TimeString);
Serial.print("Sensor Count (0-1023)= " );
Serial.print(sensorValue);
Serial.print("\t Current (ma) = ");
Serial.println(outputValue);
*/

// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library.
// change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_QUARTER_SPEED)) sd.initErrorHalt();

// open the file for write at end like the Native SD library
if (!DataFile.open("ampleak.txt", O_RDWR | O_CREAT | O_AT_END))
sd.errorHalt("ERROR opening ampleak.txt for write!");

// if the file opened okay, write to it:
Serial.println("Writing " + TimeString + "," + String(sensorValue) + + "," + String(outputValue) + " to ampleak.txt...");
lastTime = time;
DataFile.println(TimeString + "," + String(sensorValue) + "," + String(outputValue));

delay(500);

DataFile.close();// close the file to complete the write process:

}
}

I see some problems with points and commas and floating point and long and int.

Your calculation seems good.
Could you try a floating point calculation ? That is easier.

int sensorValue;
float milliAmps;

sensorValue = analogRead(analogInPin);           

Serial.print("raw sensorValue = ");
Serial.println(sensorValue);

// Convert to milli amps
// The offset of 512 has to be determined, perhaps during startup.
milliAmps = ((float) (sensorValue  - 512) * 5.0 / 1023.0 ) * 1000.0 / 66.0;

Serial.print("milliAmps = ");
Serial.println(milliAmps);

Erdin,

Many thanks, that did the trick. I still have a lot to learn about data types in this language, I'm more used to Visual Studio where things seems a little more straightforward...!

I would have replied earlier but we seem to have lost the forum for a day?

Thanks

To increase speed and precission you could replace

milliAmps = ((float) (sensorValue - 512) * 5.0 / 1023.0 ) * 1000.0 / 66.0;

by

milliAmps = (sensorValue - 512) * 0.074054326;

BUt yes you should document where that magic number comes from :wink:

These hall-effect current sensors are quite noisy - and sensitive to external magnetic fields too.

Their good points are isolation and low shunt resistance and thus low dropout voltage (basically
its a copper link in the high current circuit).

outputValue = ((long)sensorValue  - 512 ) * 73.982L;

Well this line makes no sense at all.

I concur that 0.4 A seems like a large current to be reading when there is no current there.

But this may be just an offset error in the device, which you can account for in your code,
if it is linear.

To check that your device is actually working, I suggest you figure out some way to put
a known small current through it, and see if the device detects its presence.

The other thing to do, is to check what voltage the device is outputing, when there is no current in it.
You can do this with your digital multimeter without connecting the arduino at all.

Suppose the device actually outputs 2.6 V instead of the 2.5V you are apparently expecting.

This will correspond to a count of 530 instead of 512 from the analogRead() function.

So where you calculate the current with the code

current = ( analogVal - 512 ) * scaling_factor

then just replace the 512 by 530 in the above equation, and the offset problem is solved, assuming that the
error is persistent and non-varying.