### Help with my build - ADS1115 monitoring Current

Hello,

I apologise is this is the incorrect place to post this question.

I have been reading on this site for a while now and decided to take the plunge and build a little test system to see if I could measure the current on a circuit in my house.

I wanted to us an ADS1115 ADC to get higher precision, but I am strugging with the Arduino code and whether I need to change any of the library and formulas to compensate.

I have hacked the library and have it reading from the ADS1115, and I have forced it to be 15bit as I am doing Single ended readings at the moment, so its very similar to the Arduino in that respect.

Basically I am just trying to find out if I need to modify this line:

filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);

I found the page that attempts to explain this, but it doesnt make sense to me 100%. It seems to remove the offset, but the comments in the library say the offset is 2.5V which it is going to remove, and in my case it should be 1.65V due to the 3.3V system.

I am running on a 3.3V system, and have 32768 ADC_COUNTS due to using the ADS1115, but I am unsure if the SUPPLYVOLTAGE variable needs to be 3300 for 3.3V, or if it needs to be what I have the gain on the ADS1115 set to.

I have the gain set to be 1, which means +/-4.096V, which in single ended I am guessing means I get 32768 counts over the range of 0 to 4.096V.

In the library, this line:

double I_RATIO = ICAL *((SUPPLYVOLTAGE/1000.0) / (ADC_COUNTS));

Does this need to change or is it OK? and is supply voltage for me 4096 or 3300?

ICAL I have calculated to be 100, as I have 100A clamp which is 50mA output, and a 20ohm burden resistor.

With that set, I clamped onto a phase line in the house which measured to be 230VAC with my scope/meter, and it was reporting to me that I was pulling about 11A. However this should be 13A based on the reading I took earlier in the day with an electrician who was over at our place, and he has a clamp on meter. I am not sure where this error comes in, why I am reading 2A lower.

I have the ADS1115 set up to be 0-4.096V as mentioned above, and the signal I seem to be getting between the input I am concerned with at the moment, is 500mV P-P and is centrally offset by 1.65V, and is 50Hz (as we are a 230V 50Hz country). It doesn't look like its 100% central though at the 1.65V mark, it looks to be more positive than negative. I am not sure if that is a problem or what that means exactly though. My scope is saying 52.8% +Duty.

Instead of hacking the library too much, I ended up just copying the main function for measuring current out, into my main program, just while I am tinkering. This is what I have

double calcIrms(int NUMBER_OF_SAMPLES, int Channel)

{
int ADC_COUNTS = 65536/2; //15bit due to single ended.
int SUPPLYVOLTAGE = 4096; //3300 ?
int ICAL = 100; //current constant = (100 / 0.050) / 20 = 100

for (int n = 0; n < NUMBER_OF_SAMPLES; n++)
{
lastSampleI = sampleI;
if(Channel == 1)
{
}
else if(Channel == 3)
{
}
else
{
return 0;
}

lastFilteredI = filteredI;
filteredI = 0.996 * (lastFilteredI + sampleI - lastSampleI);

// Root-mean-square method current
// 1) square current values
sqI = filteredI * filteredI;
// 2) sum
sumI += sqI;
}

double I_RATIO = ICAL * ((SUPPLYVOLTAGE / 1000.0) / (ADC_COUNTS));
double Irms = I_RATIO * sqrt(sumI / NUMBER_OF_SAMPLES);

//Reset accumulators
sumI = 0;

return Irms;
}

void loop()
{
Irms1 = calcIrms(500, 1);  // Calculate Irms only
Irms3 = calcIrms(500, 3);  // Calculate Irms only

float supplyVoltage = 230.0;                 //extract Vrms into Variable
float apparentPower1 = supplyVoltage * Irms1;     //extract Apparent Power into variable
float apparentPower3 = supplyVoltage * Irms3;     //extract Apparent Power into variable

}

Its pretty crude at the moment, but im just trying to understand what is going on at the moment.

My hardware is as the website describes, but I have a 20ohm burden resistor. I have also made the refence voltage for offsetting the AC into the +ve region, using an Opamp, which is set to 3.3V/2.

Is anyone able to assist?

I would greatly appreciate it.

After I tackle the current, I will look at the voltage.

Kind Regards

WanaGo

### Re: Help with my build - ADS1115 monitoring Current

"filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);

I found the page that attempts to explain this, but it doesnt make sense to me 100%. It seems to remove the offset, but the comments in the library say the offset is 2.5V which it is going to remove, and in my case it should be 1.65V due to the 3.3V system."

That line is a software high pass filter (Google will explain fully). It takes the offset out, no matter what the absolute value of the offset is. (Which is why we use it - the offset is almost never exactly 511 in a 10-bit system, and any offset makes the rms value wrong.)

SUPPLYVOLTAGE, ICAL etc - if you haven't found it yet, the theoretical basis of the calibration is in Building Blocks. When you go through that calculation to work out what your calibration values are, you need to remember that I wrote it for a 10-bit system in which 0 counts represented 0 V and 1023 counts represented 3.3 (or 5) V, and these two limits represented the maximum swing of the input. Your situation is a little different, as the maximum input is something like 26400 counts, and you don't appear to be (or indeed need to be) calibrating the supply voltage against an internal reference, which is how the calibration needs to be done with battery power.

You calculate your burden resistor value so as to give you the maximum peak-peak swing that you input can accept at the maximum current you want to measure, with due allowance for the current wave not being a pure sine wave, component tolerances etc. If you can guarantee a pure sine wave of current, 5% should be enough for tolerances, but depending on the sort of loads you have, you might need a lot more than that to allow for the crest factor of the waveform.

I'm answering in very general terms because as you've changed so much, I'd need to work through your design from the beginning to check it fully. After you've looked at the calibration theory, feel free to ask again if it's not clear.

### Re: Help with my build - ADS1115 monitoring Current

Hello Robert

Yes I have read the calibration theory, and based on that is where I am now with what I wrote above. Its just how to move from the default theory you wrote for the 10bit system, over to what I have now, which I am uncertain about.

So the ADS1115 is 16 bit, but since I am using Single Ended mode, input relative to GND, I believe its 15bit, which by my count is 32768. And since I have it set on a gain of 1, this is 0 to 4.096V, so 0 to 32768. Is this incorrect? You mentioned 26400 counts, I am unsure where you got this figure.

So the whole system is run off 3.3V, so while the ADS1115 has a gain set so it is 0 - 4.096 to be full scale, it is really only 0 - 3.3V input tolerant. As the next gain down is 0 - 2.048 which isnt enough, given that the 100A probe can create a voltage of 0 to 3.064V in theory.

Here is my calculation:

3.3V Analog System
0-100A is 0-50mA output on the SCT-013-000 CT Sensor.
50mA x 1.414 (RMS) x 20R = 1.414V AC (+/-)
Offset this by 3.3V/2 = 1.414 + 1.65V = 3.064V
so 0-100A is 0-50mA is 0 - 3.064V

If 3.064 is the max voltage I could ever possibly get, then I suppose the max counts I would ever see is (32768 / 4.096) * 3.064 = 24512. Maybe that is where you were getting your 26400 counts above from.... hmm.

If you are able to assist to change what I have, that would be appreciated.

So given the above, do I need to set my SUPPLYVOLTAGE to be 3064V instead of 4096V as I have currently?
And my ICAL I have set to 100 given the 100A to 50mA through a 20R burden resistor.
My ADC_COUNTS value I have currently set to be 32768, but do I actually change that to be 24512 instead?

If you could help me nut that out, that would be appreciated.

Also, the number of Samples (NUMBER_OF_SAMPLES) that is specified when you do the calcIrms() function (which I have modified a little), I am not sure if this number of samples is critical to anything, or if it really is just to help average the value coming in so its not jumping around....?

Sorry if this is a pain and my hacked version is causing problems.

Basically all I have taken is the one function I call from the library, and then added in the ability to call the function for 2 different channels on the ADC. All very crude but does the job for now.

Kind Regards

WanaGo

### Re: Help with my build - ADS1115 monitoring Current

I haven't read the data sheet for your ADC - that is the ultimate authority. But what you can do to verify the operation is to put a potentiometer across the 3.3 V rail to GND and connect the input to the wiper. (If your pot is say 10 kΩ or less and your bias resistors are 470 kΩ, you don't even need to remove the CT bias circuit first!)  Then with a simple one-line sketch (OK, maybe a handful of lines all told) you can read the numbers you get for the input at or near 0 V and 3.3 V. I got the 26400 value as 3.3 / 4.095 * 32767, on the assumption that what you wrote meant the output was calibrated to give 32767 out for 4.095 V in. The pot test should remove all uncertainty, it should also show any dead band - there should be none.

Your maximum input voltage looks to be correct for the nominal current, subject to component tolerances of course. But I wouldn't go as far as saying it's the maximum you will ever see - especially if you have a fault downstream of the CT that causes the circuit protection to operate. On the emonTx V3, we've included a series resistor to limit the current into the on-chip protection diodes in the event of a fault.

SUPPLYVOLTAGE derives from the value that the ATMega 328P reads for its internal 1.1 V reference when using the supply as the ADC reference voltage. I think you'll only be able to determine what value you should use when you know the result of the pot test. It depends also on ADC_COUNTS, so you might need to change emonlib.h to put the correct value in there.

NUMBER_OF_SAMPLES should be chosen to give you the closest to an integer number of whole cycles over which to average the current, and should be large enough so that 'end effects' (part-cycles) are sufficiently small so that they can be ignored. You will inevitably have end effects because the sample rate cannot be (unless you change to the PLL sketch!) an exact multiple of mains frequency.

When you wrote "added in the ability to call the function", you should have it as a method of the class EnergyMonitor, and you should be instantiating that class for the two inputs. If you haven't (and it looks as if you haven't), the high pass filter won't work correctly. It will see a step each time you switch channels. It depends on picking up where it left off to work properly. That's a fundamental change and you really need to revert to the original way of doing things there.

### Re: Help with my build - ADS1115 monitoring Current

Hi Robert

Yes I have noticed this too about the instances of the class, and went back to the Arduino and a single instance, and it all looks nice and stable. I then timed the time it took to take the 1480 samples that the arduino sketch by default was reading (I am not 100% yet why that number is important, but Im guessing its the number of samples required to see a full wave). I timed it, and it seemed to take about 239504 microseconds on the Arduino to do 1480 samples on a single channel. I then did the same using the same 10bit input on the Chipkit, and found it was 28323 microseconds. So what I did was extended the number of samples so that it was the same timing as the Arduino, and got close with 12465 samples and 239653 microseconds.

Beacuse the clock of the chipKit is faster, this is why I did this.

I am running this now, with 2 instances of the original library for 2 channels, and both are reading quite stable really. Need to be calibrated, but still looking pretty good.

I suppose now I need to do the same for the ADS1115 and see how long that takes to do 1480 samples and compare that to the Arduino, and then adjust it to suit.

Thinking out loud as I type here... 239504 microseconds is 0.2395 seconds, which is 4.175 Hz, which is the time it takes to do the 1480 samples on the Arduino. What does this relate to? Can you please explain?

I will read over what you said again with the POT etc and try that too.

Regards

WanaGo

### Re: Help with my build - ADS1115 monitoring Current

Oh and my Bias is done through an OpAmp, I use 10K's and then into a TLV2374IDR OpAmp, to give me the 3.3V/2 Reference.

Ah I think I see where the 1480 comes into it now. 4Hz so that is aiming for 12 cycles of the 50Hz to get an average I imagine.

### Re: Help with my build - ADS1115 monitoring Current

OK with the ADS1115 and the instances of your library, I have a problem. I dont get how to get the library to use the ADS1115 library, since there are 2 instances, as there is only 1 ADS1115 being used, and both instances have to be able to call it. I tried getting the library to do all the setup for the ADS1115 library, but I didnt have any luck.

Not sure how to get the Emon library to use the ADS1115 library when there are more than 1 instance of the Emon library at play. Ill try and do some more reading on this, but if anyone has any ideas I would greatly welcome it.

Regards

WanaGo

### Re: Help with my build - ADS1115 monitoring Current

The easy one first: The number of samples wants to be such that it takes an integral number of 20 ms to get them, hence an integral number of mains cycles. 200 ms / 10 cycles is a good number to aim for. It should give you enough samples so that the part-cycle you do or don't measure with the last sample has little effect on the average. 1480 is a carry-over from when the measurement loop of the Arduino was a little bit slower than it is now due to a few code tweaks. (It needed to work for the 60 Hz world also!)

Where you have:

if(Channel == 1)
{
}
else if(Channel == 3)
{
}
[etc]

what you need to do is make "Channel" a property of the class and set it when you instantiate (in exactly the same way as the input pin/channel was done originally). Then the method will pick up the correct call to the ADC library.

### Re: Help with my build - ADS1115 monitoring Current

Right I have the ADS1115 working in the Emon Library now with only a few minor changes.

I can have multiple instances and all compiles and appears to work.

However the value I am reading in looks rubbish.

The POT didnt work right, seems to be affected by something else in the circuit, ill look at this again.

What I dont fully understand is the ADC_COUNTS and SUPPLYVOLTAGE values.

Is the SUPPLYVOLTAGE the voltage of the full scale of the ADC input, or is it the maximum voltage that the Current Clamp/Burden can effectively output at 100A / 50mA ?

Is the ADC_COUNTS the full scale reading of the ADC input, or is it the maximum count that can be achieved with the Clamp/Burden combo?

For example, the ADS1115 I have set to 0 - 4.096V, which is 0 - 32767 counts, due to it being 15 bit when single ended.

The burden resistor I have is 20ohm which enables me to get theoretically a maximum of 3.064V if I am reading in 100A on the clamp (or 50mA). So therefore is the SUPPLYVOLTAGE support to be 4096 which I could never achieve and doesnt actually relate to the current clamp at all, or is it 3064 which to me makes more sense, as that is 100% of the current clamp.

The same with ADC_COUNTS, is this the full scale 0 - 32767, which relates to 0 - 4.096V, or is it the maximum I can achieve, which is 3.064V or 0 - 24512?

I am confused, as to me it would make sense to base these values on what is achievable and related to the device I am trying to measure, rather than what the full scale capability of the ADC Input is.

I am swaying towards needing SUPPLYVOLTAGE to be 3096 and ADC_COUNTS to be 24512. Is this correct or wrong?

Some guidance would be appreciated.

Regards

WanaGo

### Re: Help with my build - ADS1115 monitoring Current

"Is the SUPPLYVOLTAGE the voltage of the full scale of the ADC input,"  Yes.

In the ATMega 328P, those are both the maximum input that you can apply to the ADC for linear operation. Having downloaded and read the data sheet for your ADC, that is exactly the same: In "Absolute maximum ratings" it quotes !Analog input voltage to GND: –0.3 to VDD + 0.3 V". Note 1 to the Electrical characteristics table reinforces the point: "This parameter expresses the full-scale range of the ADC scaling. In no event should more than VDD + 0.3V be applied to this device."

According to my reading of the data sheet, you should set the PGA gain to 1, in that case the full-scale input voltage is ±4.096 V. That corresponds to output values of -32768 to +32767. You cannot use the negative values since you have a single-ended input. Therefore, if your input range is 0 - 3.3 V, you should see an output range of 0 - 26399. You can use 3300 and 26399 for SUPPLYVOLTAGE and ADC_COUNTS, or you can use 4096 and 32767. As it is the ratio of those that is used in the calibration, it should make no difference to the calibration. However, ADC_COUNTS is also used when detecting the zero crossing, so it will be necessary to look at and change that part of the library, because if the band is too small - it's set to ±50 counts in 1024 - you might well miss it.

I'm steering clear of "that is 100% of the current clamp." because that has no practical value, once you have established that it is inside the measurement range. It relates only to a point on a graph where it's thought that the errors become unacceptably large. If you look at the CT saturation curve in the report on the YHDC CT, you'll see that there is plenty of output way beyond 100 A - and the output is still rising at 250 A, albeit slowly and with a very distorted waveform.

If you want to be really smart, you can recognise that, in applying the calibration

. . .  =  [VCAL | ICAL] *((SUPPLYVOLTAGE/1000.0) / (ADC_COUNTS));

uses constant values that evaluate to 1/8000, therefore you can replace three floating point calculations with one and speed up the loop:

. . .  =  [VCAL | ICAL] / 8000.0;

### Re: Help with my build - ADS1115 monitoring Current

Thanks Robert

You mentioned the Zero Crossing. This appears to only be used in the calcVI() function. I am currently using the calcIrms() function only, as I dont yet have my Voltage measurement working. Circuit is made, just having plumbed it up yet.

Why is it only used in the calcVI() and not calcIrms() also?

I suppose though it is using the Voltage waveform which isnt present in the calcIrms() situation.

ill look at getting the voltage up and running.

Regards

WanaGo

### Re: Help with my build - ADS1115 monitoring Current

WanaGo,

Did you get everything working as you wished? Did you publish your modified library somewhere?

Regards,