This example demonstrates how to measure current using the ACS758 50A current sensor with an Arduino UNO. The code calculates both DC and AC current, and for AC signals it measures:
The ACS758 outputs 2.5V at 0A. The Arduino reads this offset using its 10-bit ADC.
/*
* Arduino UNO with ACS758 50A Current Sensor.
* Measures DC current, AC RMS current and frequency.
* © 2024 Copyright Peter I. Dunne, all rights reserved.
* The ADC is 10 bit, accuracy is limited. Use proper equipment for precision.
* Released under the Mozilla Public License.
*/
const int currentPin = A0; // Current sensor connected to A0
const float sensorOffset = 2.5; // 2.5V corresponds to 0A
const float maxCurrent = 50.0; // ACS758 measures up to 50A
const float VRef = 5.0; // Arduino reference voltage
const int maxADCValue = 1023; // 10-bit ADC resolution
const int threshold = 512; // Midpoint of ADC (0A)
const unsigned long interval = 500;
unsigned long lastZeroCrossingTime = 0;
float sumSquaredCurrent = 0;
int sampleCount = 0;
bool polarity = false;
bool zcd = false;
unsigned long previousACmillis = 0;
int zcp = 512;
unsigned long previousMillis = 0;
float frequency = 0;
void setup() {
Serial.begin(115200);
Serial.println("Arduino DMM current measurement, by Peter I. Dunne, ©2024");
Serial.println("Released under the Mozilla Public License");
Serial.println("https://jazenga.com/educational");
Serial.println("Demonstrates ADC system for AC and DC current measurement.");
}
void loop() {
int adcValue = analogRead(currentPin);
float voltage = (adcValue / float(maxADCValue)) * VRef;
float current = (voltage - sensorOffset) * (maxCurrent / sensorOffset);
unsigned long currentMillis = millis();
unsigned long currentMicros = micros();
if (polarity != adcValue > zcp) {
polarity = adcValue > zcp;
if (polarity) {
zcp = threshold - 10;
previousACmillis = currentMillis;
unsigned long period = currentMicros - lastZeroCrossingTime;
lastZeroCrossingTime = currentMicros;
if (period > 0) {
frequency = 1000000.0 / period;
} else {
zcp = threshold + 10;
}
zcd = true;
}
}
if ((currentMillis - previousACmillis) <= interval) {
sumSquaredCurrent += current * current;
sampleCount++;
if (zcd && polarity) {
if ((currentMillis - previousMillis) >= interval) {
previousMillis = currentMillis;
float rmsCurrent = sqrt(sumSquaredCurrent / sampleCount);
Serial.print("RMS Current: ");
Serial.print(rmsCurrent, 2);
Serial.print(" A, Frequency: ");
Serial.print(frequency, 2);
Serial.println(" Hz");
sumSquaredCurrent = 0;
sampleCount = 0;
}
}
} else {
if ((currentMillis - previousMillis) >= interval) {
previousMillis = currentMillis;
Serial.print("DC Current: ");
Serial.print(current, 2);
Serial.println(" A");
}
}
}