Trying to monitor 4 currents using ACS712 that trigger digital output at a certain value

Hello,

Using some pirated code and my meager understanding of Sketches, I have been able to get one ACS712 doing what I need using the Arduino MEGA.

The goal is to monitor 4 loads. When the load exceeds 500ma it triggers a digital pin to HIGH after a short delay, dropping out a relay. These loads are nearly non existent and then rise to about 800ma for a duration of only 50ms and dropping back to +/-0ma.

All 4 analog inputs will behave the same way and within the same parameters.

I have not been able to get a 2nd ADC added to the code successfully, much less 4.

This may expand to 8 current sensors at some point.

Any help multiplying my terrible coding to handle 4 ADC's is appreciated.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  int adc0 = analogRead(A0);
  float voltage = adc0 * 5 / 1023.0;
  float current = (voltage - 2.5) / 0.185;
  if (current > 0.5) {
  delay(200);
  digitalWrite(2,HIGH);
  }
  


  
  Serial.print("Current : ");
  Serial.println(current);
  delay(25);
}

I suggest you use a "for" loop.

for (int i = 0; i <4; i++){
  int adc0 = analogRead(i);
  float voltage = adc0 * 5 / 1023.0;
  float current = (voltage - 2.5) / 0.185;
  if (current > 0.5) {
       delay(200);
       digitalWrite(i+2,HIGH);
  }
} // end of for loop

I also suggest you replace:

  float voltage = adc0 * 5 / 1023.0;
  float current = (voltage - 2.5) / 0.185;
  if (current > 0.5)

with

  if (current > xxxx)

where xxxx is the count of the current you want to sense. There is no need to do all the math for this comparison.

Note: I'm not the greatest at code, I may have made a syntax error but you should get the point.

Thanks for the advice. Ill give it a try tomorrow.

use ADS1115 to save processor time

  int adc0 = abs(analogRead(A0)-512);
   digitalWrite(2,adc0 > 51);

or

   digitalWrite(2,analogRead(A0) > 523); // of course you must watch plus and minus pole

Stop showing off...

@shiftyvtec to make sure you read each input accurately, read each input twice.
This is because there is only one ADC and it is switched from input to input.
The ADC has a capacitor on its input, and it takes time for the charge on it to change to each new input as it is selected.
Suggested edit;

for (int i = 0; i <4; i++){
  int adc0 = analogRead(i);
  adc0 = analogRead(i);   // second read to give ADC time to input the channel.
  float voltage = adc0 * 5 / 1023.0;
  float current = (voltage - 2.5) / 0.185;
  if (current > 0.5) {
       delay(200);
       digitalWrite(i+2,HIGH);
  }
} // end of for loop
  }

Tom... :grinning: :+1: :coffee: :australia:

Thank you all for the replies.

I've played with Arduinos off and on for years but have 0 programming skills. The code I posted initially is modified code from another contributor.

Once I've found a code that works I can add to it to match my needs. This code doesn't have to be pretty if it works for what I think is a pretty simple task.

Tom,

The ADC switching delay due to the capacitor makes a lot of sense. I am finding I don't get reliable triggering of the outputs due to the input delay.

I will add my latest coding (again pilfered from the net and modified). When I try to add a line to take two samples as suggested above; A0 for example, the serial monitor still only shows one sample taken of A0 before moving on to A1,A2 and A3.

void loop() {
int currentA0 = analogRead(A0);
currentA0 = analogRead(A0);
int currentA1 = analogRead(A1);
int currentA2 = analogRead(A2);
int currentA3 = analogRead(A3);

I would like to keep this simple as possible as I am trying to get this put together for a trade show display in a month or so and can make expand on the code attached below easily because I mostly understand it.



void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {
  int currentA0 = analogRead(A0);
  int currentA1 = analogRead(A1);
  int currentA2 = analogRead(A2);
  int currentA3 = analogRead(A3);


  if (currentA0 > 525) {
    delay(200);
    digitalWrite(2, HIGH);
  }
  if (currentA1 > 525) {
    delay(200);
    digitalWrite(3, HIGH);
  }
  if (currentA2 > 525) {
    delay(200);
    digitalWrite(4, HIGH);
  }
  if (currentA3 > 525) {
    delay(200);
    digitalWrite(5, HIGH);
  }
  

  Serial.println("Current A0: " + String(currentA0));
  Serial.println("Current A1: " + String(currentA1));
  Serial.println("Current A2: " + String(currentA2));
  Serial.println("Current A3: " + String(currentA3));
  
}

Im not sure if this makes sense but i have adjuated the baud rate from 9600 to 1000000 and have had no issues with my code detecting the current spike and acting accordingly.

This is both powered by USB and powered externally with no USB interface to computer.

I thought the baud rate was just for serial comms to the computer.

Is this just a fluke that things are working with the increased baud rate or is there an increase in sampling of the analog inputs related to the increased rate?

Thank you

Hi, @shiftyvtec

Okay of you want to keep your code that way.

  int currentA0 = analogRead(A0);
  currentA0 = analogRead(A0);
  int currentA1 = analogRead(A1);
  currentA1 = analogRead(A1);
  int currentA2 = analogRead(A2);
  currentA2 = analogRead(A2);
  int currentA3 = analogRead(A3);
  currentA3 = analogRead(A3);

Will do the same thing.

Tom... :grinning: :+1: :coffee: :australia:

Id love to use a more elegant code but im not prepared for that just yet. Lol

Adding those lines of code in you examp above will result in two reads of each analog input?

I did add the second lines to each "int" but saw no increase in reliability of triggering and id expect to see each line called out in the serial monitor.

Yes, but only the last of the two will be available to your code.
The first read is taken and not used, this gives the ADC the time it needs, then the second read is the value your code uses.

Your print statement only gets the second read as it is written over the first read.

The comms rate does effect your code speed as the serial buffer has to be cleared before loading the next packet to be sent.
Increasing the comms rate means the buffer is cleared quicker and so it can be reloaded more often.

Tom... :grinning: :+1: :coffee: :australia:

Good explanation.

Any idea why it doesnt improve my success in recognizing the current spike and triggering the associated output?

As mentioned, i bumped the baud rate up and have had zero issues reliably triggering the output.

Thanks for your continued assistance. Im getting questions answered that i have a hard time finding with Google.

Edit: just saw your response to baud rate.

Please describe the loads you are trying to monitor.

At the moment a have 5 loads to monitor, they may sit for hours drawing no current.

When they do experience a load it is about 800ma at 270vdc with a duration of only 50-70ms at which point they fall back to drawing zero current.

When the spike occurs, the program should bring its associated digital pin HIGH and remain high until the arduino is manually reset.

What switches the 270V to the load? Is the switch between the 270V and load or between load and 0V (ground)? How is the ACS712 connected to the load?

Its a proprietary power supply. Switching is handled through a solid state relay. The ACS712 is on the poitive line just ahead of the load.

@shiftyvtec
Without any filtering, the output noise of the AC712 could be well over 100mV p-p
With a minimum sensitivity of 180mV/A that corresponds to a noise current of 555mA.
So your 500mA measurement will have an uncertainty of +/-277.5mA

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.