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, displaying **peak current**, **RMS current**, **voltage**, and **frequency** for AC signals. AC detection is based on the current waveform. The sensor outputs 2.5V at 0A, and the analog value is processed by the Arduino's ADC.
/*
* Arduino UNO with ACS758 50A Current Sensor.
* Measures DC current, AC RMS current and frequency.
* © 2024 Copyright Peter I. Dunne, all rights reserved.
* Prepared for educational use.
* The ADC is 10 bit, this is of relatively low accuracy, use professional test equipment for accuracy.
* 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; // the 0v point, we use integer for faster comparisons
const unsigned long interval = 500; // 500ms hold period if AC is detected
// Variables for RMS and frequency calculations
unsigned long lastZeroCrossingTime = 0;
float sumSquaredCurrent = 0;
int sampleCount = 0;
bool polarity =false; // used by AC, DC detection
bool zcd = false; // zero cross detection, part of the AC component
unsigned long previousACmillis = 0; // Stored the last time AC was detected
int zcp = 512; // zero crossing point
unsigned long previousMillis = 0; // used by display updates
float frequency = 0;
void setup() {
Serial.begin(115200); // Start serial communication
Serial.println("Arduino DMM, current measurement, by Peter Ivan Dunne, ©2024, all rights reserved");
Serial.println("Released under the Mozilla Public License");
Serial.println("https://jazenga.com/educational");
Serial.println("Purpose: to demonstrate use of ADC system as a current meter for both AC and DC voltages.");
Serial.println("Auto detection of AC and measurement of AC frequency");
}
void loop() {
// Read the analog value from the current sensor
int adcValue = analogRead(currentPin);
// Convert ADC value to voltage
float voltage = (adcValue / float(maxADCValue)) * VRef;
// Convert voltage to current (50A corresponds to full range)
float current = (voltage - sensorOffset) * (maxCurrent / sensorOffset);
unsigned long currentMillis = millis();
unsigned long currentMicros = micros();
// Detect AC or DC by checking voltage oscillation
if (polarity!=adcValue>zcp){
polarity = adcValue>zcp;
if (polarity){
// add hysterisis to prevent false triggering
zcp=threshold-10;
// period is calculated only on the positive edge for greater accuracy
previousACmillis = currentMillis;
unsigned long period = currentMicros - lastZeroCrossingTime; // Time between zero crossings
lastZeroCrossingTime = currentMicros;
// Calculate frequency in Hz
if (period>0){
frequency = 1000000.0 / (period); // Period is in microseconds
} else {
// add hysterisis to prevent false triggering
zcp=threshold+10;
}
zcd = true;
}
}
if ((currentMillis - previousACmillis) <= interval){
sumSquaredCurrent += current * current; // Sum of squares for RMS calculation
sampleCount++;
if (zcd && polarity) {
// Output AC parameters
if ((currentMillis - previousMillis) >= interval) {
// Save the last time action was taken
previousMillis = currentMillis;
// Calculate RMS current
float rmsCurrent = sqrt(sumSquaredCurrent / sampleCount);
// Output AC parameters
Serial.print("RMS Current: ");
Serial.print(rmsCurrent, 2);
Serial.print(" A, Frequency: ");
Serial.print(frequency, 2);
Serial.println(" Hz");
// Reset variables for next cycle
sumSquaredCurrent = 0;
sampleCount = 0;
}
}
} else {
// For DC, output the voltage directly
// update the output every 500ms
if ((currentMillis - previousMillis) >= interval) {
// Save the last time action was taken
previousMillis = currentMillis;
// For DC, output current directly
Serial.print("DC Current: ");
Serial.print(current, 2);
Serial.println(" A");
}
}
}