Arduino UNO with ACS758 50A Current Sensor - Detailed Example

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.

Detailed Steps

Arduino Code


/*
 * 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");
    }
  }
}  
        

How It Works