Current Sensing problems

Hi,

I'm trying to read current data from an ACS712 30A Current Sensor from the voltage source that is feeding a MOSFET. I'm using Arduino's digitalWrite to turn on or off the Gate of the IRF510 depending on whether a hall effect sensor detects a magnet. I am able to measure DC current with no problem by using my fluke multimeter but I am unable to do the measurements with the sensor. The sensor basically reads zero current. I suspect is has to do because the transistor's gate is switching at a high speed and the current sensor is unable to make measurements because the transistor is not on for an appropiate time. I have attached a picture of the relevant part of the circuit. Should I be measuring RMS AC current of the square wave given that it is constantly switching or should I measure normal DC current? If the latter, what am I doing wrong? Any help is greatly appreciated. Thanks.

Capture.PNG

The IRF510 is not a logic fet, so you have to be lucky to saturate it with Arduino's 5volt logic.

You use pin13, which can be problematic because it's also used for the onboard LED.

You did not use gate resistors.

You did not include your sketch (inside code tags) and a drawing of how you have connected the ACS712.
Leo..

If the 9v in you diagram is a battery, it is also probable that you will not get much current anyway. Using a 30A sensor to measure a low current will not give good results.

Weedpharma

Wawa, you are absolutely right. I was confused about what is discussed in the following post:

http://forum.arduino.cc/index.php?topic=72000.0

Weedpharma,

I'm getting a maximum of 600mA with my meter. I've read that a low power source and or load could be an issue when using this sensor, but I still don't understand why. Could you explain this to me?

Thanks for the help. Learned a lot.

The sensitivity of the sensor is 66mV per Amp. This means the analogue reading will change by

1024 / 5 for each volt input change. IE, 205.

So the change of 66mV will give

.066 X 205 = 13.5 change in analogue value for each Amp through the sensor.

600 mA will only change the reading by about 8.

Weedpharma

I see. I still don't get what you mean by "change". Could you clarify this? Lastly, could you suggest a more sensitive current sensor breakout? Thanks for help.

You are using a 60Amp sensor (+/- 30Amp).

Arduino has a 10-bit A/D (1024 values).

The sensor can't output the full 5volt swing. More like 3.96volt (66mV x 60A).

That leaves 792 values, spread over 60Amp.
Each Amp is ~13 A/D values.
So with the right code you could read resolutions/steps of ~100mA.
Leo..

Do you mean that I don't have to replace the sensor or use one with less amps? If so, could you help me get started with the code? At least in pseudo?

A sensor made for big currents is not that accurate for small currents.
A 5Amp sensor would have been better for 600mA currents.
As said, the 30A sensor combined with an Arduino has a granularity of ~0.1Amp.
Here is some (untested) code to get you started.
It uses pre-read and smoothing.
Works on LCD shield and serial monitor.
Read the comments.
Leo..

// ACS712

int inputPin = A1; // the pin that the sensor is connected to

// calibration
float offset = 511.5; // zeroing | bi-directional sensor is 510 - 513
float span = 0.151515; // current range

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // your LCD pins could be different
const byte ledPin = 10; // backlight pin
const byte numReadings = 32; // number of readings for smoothing (max 64 for a 10-bit A/D)
int readings[numReadings]; // raw readings from the analog input
byte index = 0; // index of the current reading
unsigned int total = 0; // running total
float current; // resulting current

void setup() {
  //analogWrite(ledPin, 200); // optional dimming
  Serial.begin(9600); // ---set serial monitor to this value---
  lcd.begin(16, 2); // shield with 2x16 characters
  lcd.print("Battery Current"); // info text
  lcd.setCursor(0, 1); // second row
  lcd.print("+/- 30 Amp");
  for (index = 0; index < numReadings; index++) { // fill the array for faster startup
    readings[index] = analogRead(inputPin);
    total = total + readings[index];
  }
  index = 0; // reset index
  delay(2000); // info display time
}

void loop() {
  total = total - readings[index]; // subtract the last reading
  readings[index] = analogRead(inputPin); // one unused reading to clear ghost charge
  readings[index] = analogRead(inputPin); // read the sensor
  total = total + readings[index]; // add the reading to the total
  index = index + 1; // advance to the next position in the array
  if (index >= numReadings) // if we're at the end of the array
    index = 0; // wrap around to the beginning

  // convert value to current
  current = (total / numReadings - offset) * span; // value to current conversion

  // print to LCD
  lcd.clear();
  lcd.print("Current");
  lcd.setCursor(0, 1);
  lcd.print(current, 1); // one decimal place
  lcd.print(" Amp");

  // print to serial monitor
  Serial.print("Current is  ");
  Serial.print(current);
  Serial.print("  Amp");

  delay(1000); // use a non-blocking delay when combined with other code
}

Hey Leo, I'm getting negative values with the code. I tried tweaking the zeroing to different values and still the same problem. I've attached a screenshot. So I had lying around an INA219 (INA219 High Side DC Current Sensor Breakout - 26V ±3.2A Max [STEMMA QT] : ID 904 : $9.95 : Adafruit Industries, Unique & fun DIY electronics and kits) and I tried the same circuit that I posted earlier which is essentially measuring current through a switching MOSFET with two coils as load and a 9V source, but I'm getting almost zero values. I only get readings when transistor is ON for a while and not constantly switching ON and OFF. I changed the code to work with I2C protocol and I tested it measuring current through a simple LED with a limiting resistor in series and it worked. This sensor is supposed to be more sensitive and has lower ratings if I'm not mistaken. What am I missing here? Sorry for all the trouble, I'm such a noob.

I assume you have a bi-directional (+/-30A) ACS712. Not all are.
How did you connect the ACS712.
Is there 2.5volt on the sensor output with zero current through the sensor.
If you use a PWM signal, you have to measure current during the time the PWM signal is high.

The INA is a different animal.
It does not use Arduino's A/D.
Leo..

My ACS712 is bi-directional. I'm connecting the sensor as my attached drawing shows (squem.png) but I keep getting negative values on my serial monitor when I'm suppose to be getting from 100mA to 200mA according to my meter. Also, I tried measuring voltage in the output of the sensor and I'm only getting 0 Volts and not 2.5V like its supposed to when there's zero current. I tried the same connections with the ina219 (obviously using A4 and A5 for I2C and not A1) and i'm getting almost zero current like one of the attached pictures shows (ina.png). The picture "ina2.png" shows a higher current reading of about 1.4 A. When the MOSFET is ON and not switching I get accurate readings like this one, but as soon as I start switching the MOSFET I start getting like 1.60 mA which is essentially zero. My input signal to the gate is not PWM per se because I'm switching ON and OFF (digitalWrite HIGH and LOW) the transistor depending on another trigger and not on a predefined AnalogWrite. How could I measure current in this case? Do I need some kind of RMS or averaging algorithm? If so, can you get me started with the code? Thanks, I really appreciate the help you are giving me.

The code I gave you expects 2.5volt on A1 with zero current.
A higher voltage gives positive amps, and a lower voltage gives negative amps.
So what you get is normal if the sensor outputs 0 volt.
Is this a bare ACS712 chip (that needs supporting decoupling caps), or a breakout board.

As said, only take readings when the mosfet is "on".
No code yet, so I can't comment.
Leo..

Hey Leo, the chip is a breakout board. How can I only take readings when it is on while the transistor is constantly pulsating? Can you show me how it is done in code? What I don't understand is why can my meter read current under these same pulsating ON and OFF conditions and not the sensors. Also, apologies for not posting my code. It is such a simple sketch that I kind of ignored it. This is the code for the MOSFET and Hall sensor bit.

// When Hall sensor detects LOW, MOSFET turns ON

const int MOSFET = 13;
const int SENSOR = 7;

int val = 0;

void setup(){
  pinMode(MOSFET, OUTPUT);
  pinMode(SENSOR, INPUT);
//  Serial.begin(9600);
}
void loop(){
  val = digitalRead(SENSOR); 
  
  if (val == LOW){
    delay(10);
    digitalWrite(MOSFET, HIGH);
  }
  else{
    digitalWrite(MOSFET, LOW);
  }
}
// When Hall sensor detects LOW, MOSFET turns ON

const int MOSFET = 13; // this pin might toggle during bootup
const int SENSOR = 7;
int current;
boolean hall;

void setup() {
  pinMode(MOSFET, OUTPUT);
  pinMode(SENSOR, INPUT);
  //  Serial.begin(9600);
}

void loop() {
  hall = digitalRead(SENSOR);

  if (hall == LOW) {
    digitalWrite(MOSFET, HIGH);
    delay(10);
    current = analogRead(A1); // read sensor here
  }
  else {
    digitalWrite(MOSFET, LOW);
  }
}

Hey Leo,

I feel kind of silly with the last questions. Sorry about such noob questions. As you know the idea with the hall sensor is to trigger the MOSFET. The problem with getting readings in any part of this code is that I disturb the momentum of my spinning rotor which depends on feeding the coils on time which in part depends on turning the transistor ON in time. For this reason, I was using a second microcontroller to act independenly as a monitoring system for power, RPMs, etc. The question is, how can read current from the second arduino while getting readings in the HIGH state of the transistor which depends on the code of the first arduino? Also, if you have any suggestions or comments regarding the configuration please feel free to shoot. Maybe I'm complicating my system and there is an easier way to implement it. Thanks again.

If you share grounds, you can connect an output pin of the motor Arduino to an input pin of the measuring Arduino. For safety (phantom powering), if 5volt is not shared, use a 4k7 or 10k resistor between the pins instead of a wire.
Now the measuring Arduino knows when to measure.
Not sure if this all is needed. Code happens really fast. Faster than mechanical things.
There are gurus here that can help you speed up the code if needed.
Post your code (inside code tags).
Leo..