0

first I want to say that I'm a beginner in Arduino programming, so please explain the code if possible. I want to design a system which can monitor the 3 phase supply currents and voltages and take action e.g. activate a relay to isolate the system from load if there is a phase loss.

I'm using ACS712 current sensors and AC voltage measurement circuit to measure the voltages.

I wrote a code to monitor the phases and trigger the relay to isolate the load if the voltage drop below 100V for instance. but one issue I'm facing is the relay is getting activated randomly on and off, even though the phase voltage is 220V well above the threshold value which is 100V.

My real question is how do I write a code which can take samples and divide it with a number of samples and calculate the RMS value?

I found this code below online but failed to understand it.so if you explain it will be very appreciated.

float current=0;
const int currentPin = A0;
const unsigned long sampleTime = 100000UL; // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 250UL;  // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up
const unsigned long sampleInterval = sampleTime/numSamples;  // the sampling interval, must be longer than then ADC conversion time
const int adc_zero = 510;                                                     // relative digital zero of the arudino input from ACS712 (could make this a variable and auto-adjust it)

void setup()
{
 Serial.begin(9600);
}

void loop()
{

CurrentSense();
Serial.println(current);
delay(1000);

}

void CurrentSense()
{
 unsigned long currentAcc = 0;
 unsigned int count = 0;
 unsigned long prevMicros = micros() - sampleInterval ;
 while (count < numSamples)
 {
   if (micros() - prevMicros >= sampleInterval)
   {
     int adc_raw = analogRead(currentPin) - adc_zero;
     currentAcc += (unsigned long)(adc_raw * adc_raw);
     ++count;
     prevMicros += sampleInterval;
   }
 }

 float rms = sqrt((float)currentAcc/(float)numSamples) * (50 / 1024.0);
rms=rms-0.10;
if (rms<0.20)
{
rms=0;
}

current=rms;
}

I didn't understand the following line of codes:

const unsigned long sampleTime = 100000UL; what is unsigned long & what is UL?
const unsigned long numSamples = 250UL;
const unsigned long sampleInterval = sampleTime/numSamples;

unsigned long prevMicros = micros() - sampleInterval ; what is Micro() function?
while (count < numSamples)
 {
   if (micros() - prevMicros >= sampleInterval)
   {
     int adc_raw = analogRead(currentPin) - adc_zero;
     currentAcc += (unsigned long)(adc_raw * adc_raw);
     ++count;
     prevMicros += sampleInterval;
   }
 }

 float rms = sqrt((float)currentAcc/(float)numSamples) * (50 / 1024.0);
Alvaro
  • 491
  • 3
  • 16
Hilal
  • 13
  • 1
  • 3
  • For the micros function the [arduino documentation](https://www.arduino.cc/en/Reference/Micros) helps. Also for the [unsigned long](https://www.arduino.cc/en/Reference/UnsignedLong) question.... basically the function gives you the time in microseconds since you started the board and the unsigned long is a positive integer that can have a value up to 4294967295 – api55 Jan 17 '17 at 16:39
  • i think it would be easier to find the peak for a phase, then convert the peak-to-peak to rms, assuming a sine-ish wave. then your main "loop" just has to ask if each value is bigger than the last, and if so, increase the "leader" value. once it drops twice in a row, you know you have found the peak. once you find the peak, RMS is a trivial calculation, assuming a sine wave. – dandavis Jan 17 '17 at 19:13

1 Answers1

0

To answer your first question about the unsigned long, with numerical data types the most-significant bit is usually used to determine if a number is positive or negative. However, this is at the cost of halving the positive capacity of the data type. If a negative value is not an expected outcome, then you can declare a data type as unsigned to use the most significant bit for a greater positive capacity.

So for example:

  • An unsigned long using 4 bytes has a value range from 0 to 4,294,967,295
  • A (signed) long using 4 bytes has a value range from -2,147,483,648 to 2,147,483,647

The use of UL at the end of a number explicitly tells the compiler that this value is an unsigned long. Note that the size of a long (or any other numerical types) may not be consistent across compilers.

See also - What's the difference between unsigned long/long/int in c/c++?

As for your other question, the Arduino docs describe the micros() function:

Returns the number of microseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 70 minutes. On 16 MHz Arduino boards (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution of eight microseconds.

Note: there are 1,000 microseconds in a millisecond and 1,000,000 microseconds in a second.

Community
  • 1
  • 1
Michael Dodd
  • 10,102
  • 12
  • 51
  • 64
  • I know now it is the timer in microseconds. Please, could you explain the flowing line of code if possible? unsigned long prevMicros = micros() - sampleInterval ; why sampleInterval taking away from Micro() function? float rms = sqrt((float)currentAcc/(float)numSamples) * (50 / 1024.0); why the sqrt((float)currentAcc/(float)numSamples) is mutiplied by 50/1024.0 and what does number 50 represent? – Hilal Jan 18 '17 at 21:16
  • I've not actually dabbled in Arduino at all. However, looking at the code, `prevMicros` would be the timestamp of the most recent sample prior to the one you're about to take. This will set the minimum waiting period before taking a new sample, as demonstrated in `if (micros() - prevMicros >= sampleInterval)` – Michael Dodd Jan 18 '17 at 21:22
  • Unfortunately I'm not electrically-trained enough to figure out what the last line does, but my guess is that 50 relates to the frequency of the AC current i.e. 50Hz is the standard AC frequency across Europe. Again, take a pinch of salt with that advice. – Michael Dodd Jan 18 '17 at 21:24
  • thanks a lot now it has cleared my doubts. thanks again for being very quick in answering. God bless you – Hilal Jan 18 '17 at 21:35