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.
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.
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?
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.
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);
}
}
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..