Hall effect sensor: ACS723, Help with measuring changes in AC current

Hi! I have been working on a project that is using the acs723 sensor to measure the ac current changes. Part of the problem I am having however is actually detecting the change because of how noisy the output is. This is my code that I am using. Thank you!

#include <SPI.h>


bool led_status = false;

const int leftAnalogInPin = A1;
//const int rightAnalogInPin = A1;


const int burstSamples = 10;  
float average = 0;
double sensorValue = 0;
const int windowSize = 30;
float windowBuffer[windowSize] = {0};
int windowIndex = 0;
int windowCount = 0;
float windowSum = 0;
int leftBallNum = 1;

float sensitivity = 40.0 / 100.0; 
float Vref = 2500;
void setup() {
  pinMode(leftAnalogInPin, INPUT);
  
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 
  
  // Defined in thingProperties.h

  double sumSquares = 0;
  for (int i = 0; i < burstSamples; i++) {
    double reading = analogRead(leftAnalogInPin);
    sumSquares += reading * reading;
    delay(6);
  }
  sumSquares /= burstSamples;
  average = sqrt(sumSquares);
  // Initialize moving average buffer with initial readings
  windowSum = 0;
  for (int i = 0; i < windowSize; ++i) {
    // take burst-averaged sensor reading
    double rawSum = 0;
    for (int k = 0; k < burstSamples; ++k) {
      rawSum += analogRead(leftAnalogInPin);
      delay(4);
    }
    double rawAvg = rawSum / burstSamples;
    double voltage = 4.88 * rawAvg;
    double current = (voltage - Vref) * sensitivity;
    windowBuffer[i] = current;
    windowSum += current;
  }
  windowCount = windowSize;
  average = windowSum / windowCount;
  Serial.print("Init moving average: "); Serial.println(average);
  delay(1500);
  
  // Get MAC address:
  //if(!SetupMapping())
  //{
    //Serial.println("Failed"); 
  //}
}


void loop() {
  //if (led_status){
    //digitalWrite(LED_BUILTIN, HIGH);
  //}
  //else
    //digitalWrite(LED_BUILTIN, LOW);
  
  //matrix.setTextSize(1);
  //matrix.fillScreen(0);  
  double sumSquares = 0;
  for (int i = 0; i < burstSamples; i++) {
    double reading = analogRead(leftAnalogInPin);
    sumSquares += reading;//reading * reading;
    delay(6);
    //while(timer.read() < 6)
    //{
      //drawEverything( rightLaneValue, rightBallNum, leftLaneValue, leftBallNum,
         //rightStartPos, rightString, leftString,  leftStartPos);
      //matrix.show();
    //}
    //timer.pause();
    //timer.restart();
  }

  sensorValue = sumSquares / burstSamples; 

  double voltage = 4.88 * sensorValue;
  double current = (voltage - Vref) * sensitivity;
  float diff = abs(current - average);

  // Toggle logic disabled for tuning:
  if (diff >= 6.25f) {
    // leftBallNum toggles 1<->2 on threshold exceed
    leftBallNum = (leftBallNum == 1) ? 2 : 1;
  }
  else {
    windowSum -= windowBuffer[windowIndex];
    windowBuffer[windowIndex] = current;
    windowSum += current;
    windowIndex++;
    if(windowIndex >= windowSize)
    {
      windowIndex = 0;
    }
    if (windowCount < windowSize)
    {
      windowCount++;
    }
    float movingAvg = windowSum / windowCount;
    average = movingAvg;
  }
  Serial.println(current);

  
  //delay(500);
  //drawEverything( rightLaneValue, rightBallNum, leftLaneValue, leftBallNum,
   //rightStartPos, rightString, leftString,  leftStartPos);
  //matrix.show();
}

/*
  Since LeftLaneName is READ_WRITE variable, onLeftLaneNameChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onLeftLaneNameChange()  {
  // Add your code here to act upon LeftLaneName change
}

/*
  Since LeftStartPos is READ_WRITE variable, onLeftStartPosChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onLeftStartPosChange()  {
  // Add your code here to act upon LeftStartPos change
}

/*
  Since LeftString is READ_WRITE variable, onLeftStringChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onLeftStringChange()  {
  // Add your code here to act upon LeftString change
}

/*
  Since Light is READ_WRITE variable, onLightChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onLightChange()  {
  // Add your code here to act upon Light change
}

/*
  Since RightLaneNum is READ_WRITE variable, onRightLaneNumChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onRightLaneNumChange()  {
  // Add your code here to act upon RightLaneNum change
}

/*
  Since LeftLaneNum is READ_WRITE variable, onLeftLaneNumChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onLeftLaneNumChange()  {
  // Add your code here to act upon LeftLaneNum change
}

/*
  Since RightStartPos is READ_WRITE variable, onRightStartPosChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onRightStartPosChange()  {
  // Add your code here to act upon RightStartPos change
}

/*
  Since RightString is READ_WRITE variable, onRightStringChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onRightStringChange()  {
  // Add your code here to act upon RightString change
}

/*
  Since ShowDefaultValues is READ_WRITE variable, onShowDefaultValuesChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onShowDefaultValuesChange()  {
  // Add your code here to act upon ShowDefaultValues change
}


/*
  Since LeftBallNum is READ_WRITE variable, onLeftBallNumChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onLeftBallNumChange()  {
  // Add your code here to act upon LeftBallNum change
}
/*
  Since RightBallNum is READ_WRITE variable, onRightBallNumChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onRightBallNumChange()  {
  // Add your code here to act upon RightBallNum change
}
/*
  Since SensorValue is READ_WRITE variable, onSensorValueChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onSensorValueChange()  {
  // Add your code here to act upon SensorValue change
}

We don’t normally offer custom code support, but at a glance it looks like your averaging samples with VCC/2, but for AC calculations you want to use RMS and a sliding window

I kicked this to a few AI models and they all 3 basically agreed about how to fix it, posted below

Claude
Perplexity
ChatGPT

I’d try Claude’s, then ChatGPT, then perplexity (it had a TON of suggestions/filters/etc)

I’ll try those out then. I wanted to ask too, what should the output look like when measuring ac current? When the current switches to a higher value for me it just spikes in either direction and then goes back to the baseline, and then when the circuit turns off it only sometimes spikes again and other times it’ll just stay at the baseline? I want to think it is something to do with the averaging I am doing, but I want to check

I got it to work :+1:

1 Like