Power meter using Raspberry pi & SEN0211

Hello,

Full disclosure: I have a computer science background. I have have some basic knowledge in electronics and limited knowledge in electric circuits (only what I can remember from 10 years ago :slight_smile: )
I am trying to build a power meter using the following:

How does my setup look like?

  • I connected the jack to the SEN0211 current sensor.
  • I connected the VCC and GND of SEN0211 to 3.3V that’s coming from the raspberry.
  • I connected the output of SEN0211 to pin A0 on ADS1115
  • I connected the SCL & SDA pins from ADS1115 to the associated pin on the raspberry
  • I connected ADS1115 to the same 3.3V

I am getting consistent raw values when sampling once every 8 ms

I am now trying to transform the raw values in amp readings. (I am in the UK so I will assume 50Hz freq)

I have tried applying the math suggested on the github repo of the SEN0211:Analog-AC-Current-Sensor/AC_Current.ino at master · DFRobot/Analog-AC-Current-Sensor · GitHub but I can’t make sense of the data. Probably the set of assumptions that their code contains doesn’t apply in my setup?

I started reading the docs from openenergy and in the example setup they are using some Current sensing electronics.

Am I right in believing that the purpose of those components is exactly the same as what SEN0211 is doing?

The below readings show the raw values over time: At first it’s for 0amps; the next step is for 2.8 amps and the next step is for 4.015 amps


It’s worth mentioning that I am executing my code in node js and thus I can’t use EmonLib easily but I have converted the code from the Irms method into js. I suspect that the problem may lie around here.

const calc = (samples) => {
let ICAL = 111.1;
let ADC_COUNTS = 4096;
let SupplyVoltage = 3300;
let sumI = 0;
console.log(`start calc. Number of samples: ${samples.length}`);
for (let i = 0; i < samples.length; i++) {
    let sampleI = samples[i];
    let offsetI = ADC_COUNTS >> 1;
    let filteredI = 0;

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    //  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI - offsetI) / 1024);
    filteredI = sampleI - offsetI;

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

    console.log(`sampleI: ${sampleI}; offsetI: ${offsetI}; filteredI: ${filteredI}; sqI: ${sqI}; sumI: ${sumI}`);
}

let I_RATIO = ICAL * ((SupplyVoltage / 1000.0) / (ADC_COUNTS));
let Irms = I_RATIO * Math.sqrt(sumI / samples.length);
console.log(`finish calc. Irms: ${Irms}; I_Ratio: ${I_RATIO};`)

return Irms * 230;

}

Here are some partial logs of what the above code is doing:
start calc. Number of samples: 125
sampleI: 47; offsetI: 2046.0458984375; filteredI: -1999.0458984375; sqI: 3996184.5040597916; sumI: 3996184.5040597916
sampleI: 46; offsetI: 2046.044921875; filteredI: -2000.044921875; sqI: 4000179.689517975; sumI: 7996364.193577766
sampleI: 47; offsetI: 2046.0458984375; filteredI: -1999.0458984375; sqI: 3996184.5040597916; sumI: 11992548.697637558
sampleI: 47; offsetI: 2046.0458984375; filteredI: -1999.0458984375; sqI: 3996184.5040597916; sumI: 15988733.20169735
sampleI: 47; offsetI: 2046.0458984375; filteredI: -1999.0458984375; sqI: 3996184.5040597916; sumI: 19984917.70575714
sampleI: 47; offsetI: 2046.0458984375; filteredI: -1999.0458984375; sqI: 3996184.5040597916; sumI: 23981102.209816933
sampleI: 50; offsetI: 2046.048828125; filteredI: -1996.048828125; sqI: 3984210.924259186; sumI: 496363245.5779867
sampleI: 46; offsetI: 2046.044921875; filteredI: -2000.044921875; sqI: 4000179.689517975; sumI: 500363425.2675047
finish calc. Irms: 179.0836027357205; I_Ratio: 0.08950927734374999

That is not consistent: the 20 A c.t is a SCT-013-020, the SCT013-000 is 100 A : 50 mA.
Which do you have?

What do you mean by that? The first problem is your sample rate. It is way too slow for 50 Hz mains - one cycle of mains takes 20 ms, so you have less than 3 samples per cycle. (The Arduino (Atmel 328P) in current-only mode does something like 100 samples per cycle. You won’t get a very accurate representation of the mains wave.)

But what you should be seeing is samples that vary - apparently randomly because of your very low sample rate - between 0 - 65535 (or -32768 - +32767 – it’s a 16-bit ADC but I haven’t read the data sheet very carefully).

What I suggest you do is spend a little time understanding exactly what functions in emonLib do.

Basically, in the Atmel 328P, the voltages should be centred on 511 (they never are, hence the filter) and vary symmetrically either side of that, not quite hitting 0 and 1023 at the extremes. But to calculate rms current, you first need to extract the actual value of that centre bias voltage and then subtract it (so the values swing between -512 & +511), then you square each sample, average them and finally get the square root (hence Root Mean Square).
Having got that, you must work out the calibration, knowing what current produces what voltage that produces what number out of the ADC.

Depending on which c.t. you have, the gain of the buffer amplifier and how the ADC is set up, you should be able to calculate that.

What do you get if you plot the individual values of the samples array? How does that relate to what I’ve written above. That should give you a valuable insight into whether the hardware is behaving as you expect.

That’s where I’d start investigating and verifying the system.

I’m afraid not. You can find the schematic for your SEN0211 here. That thing basically outputs a DC signal, so sampling rate doesn’t much matter. It half-wave rectifies the signal and latches the peak voltage which then decays over a very long period.

If you look at their original software you’ll see it divides the measured value by sqrt(2) to convert it from peak to RMS, which is only useful when your current is a sine wave. It’s pretty much mimicking what a non RMS multimeter does to measure current. You could potentially use it to measure apparent power (Vrms x Irms) but I’m afraid it won’t be much use for real power.

I missed that - down to not having my computer in a working state! Thanks for spotting it, @dBC

So basically - all the code lifted from emonLib can be discarded, except for the last scaling bit.

Thank you all for getting back quickly.

From the provided feedback I will:

  • Work on improving the sample speed. What would be an appropriate number of samples ?
  • Build the circuit described here: Learn | OpenEnergyMonitor

After all of this, I will collect some data and report back. I am aware that my code needs to change as well, but I will get to that step once I have the right hardware in place.

@Robert.Wall sorry I wasn’t very clear before. This is the AC probe that I am using: Gravity: Analog AC Current Sensor (20A) - DFRobot.
My understanding (might be wrong) is that the maximum current that can be measured is 20 amps.
For a maximum current of 20 amps it will output 1V. I imagine that for a current of 10 amps it will output 0.5V and so on.

I will be looking at getting the model that allows 100 amps to be measures but this will due for now.

I will report back once I sort out the things pointed out.

Thank you all.

The absolute minimum according to theory, is two samples of the highest harmonic of the waveform you’re interested in. There are rules that give limits for the amplitudes of the harmonics that are permitted - but those tend to be based on the harmonic number and the total load, so there’s no clear answer. I think most electronic meters go up to at least the 30th, so in excess of 3000 samples per second. See: Sampling rate of emonLib

Bear in mind, that still needs a decent ADC to get digital numbers into your RPi.

OK, but you must check the part number, because your description and the part number you gave don’t relate to the same thing.

And there are two of those in the SCT-013 family - one that outputs 1 V and one that gives you 50 mA at your 100 A.

I checked and the model that I have is SCT013-020. Looking at their website http://m.en.yhdc.com/product/SCT013-401.html it says that it has a built in resistance.

I am curious to know if I can take the output of the sensor and connect it to my adc.
This page suggests that I can Learn | OpenEnergyMonitor
But I would like to double check first.

Answering the question of how to use the SCT-013-020 c.t. in the now-deleted post:

You will get 1 V rms (2.82 V approx peak-peak) out of that c.t for 20 A rms in, assuming a perfectly formed sine wave.Âą

You must not allow any input pin to go more negative than GND, or more positive than VCC. If you use it in the differential mode, the circuit you need will be pretty much as the way we use a c.t. with the Atmel 328P noting that the burden resistor is built in to your c.t. You need to arrange the “mid-point” bias voltage to be the middle of the full-scale voltage range, and that point can very conveniently be connected to the AINN input and one side of the c.t. The AINP input of course goes to the other c.t. connection. You should make that voltage as close as conveniently possible to the middle of the input voltage range, and that’s affected by the PGA setting (table 3 of the data sheet).

Doing that should mean that you won’t need to remove that d.c. bias in software, because the ADC has removed it for you.


ÂąUnlikely in practice, but most higher-powered domestic loads will be a reasonably good approximation to that. But if you have a waveform like this (source: @dBC) then that approximation goes out of the window:

That’s an LG washing machine with a DC brush-less motor.

I’ve got one of those.

Now I know why my PF is so lousy sometimes. :wink: :grin:

I have managed to put together the circuit described in the CT Sensors - Interfacing with an Arduino section. it looks like this:


The raw values that I am reading now are:
values gathered in 1ms: [ 13 ]
values gathered in 1ms: [ 18 ]
values gathered in 1ms: [ 12 ]
values gathered in 1ms: [ 65530 ]
values gathered in 1ms: [ 65515 ]
values gathered in 1ms: [ 65504 ]
values gathered in 1ms: [ 65509 ]
values gathered in 1ms: [ 65531 ]
values gathered in 1ms: [ 4 ]
values gathered in 1ms: [ 23 ]
values gathered in 1ms: [ 17 ]
values gathered in 1ms: [ 2 ]
values gathered in 1ms: [ 65522 ]
values gathered in 1ms: [ 65493 ]
values gathered in 1ms: [ 65501 ]
values gathered in 1ms: [ 65521 ]
values gathered in 1ms: [ 0 ]
values gathered in 1ms: [ 25 ]
values gathered in 1ms: [ 19 ]
values gathered in 1ms: [ 4 ]

@Robert.Wall You’ve mentioned that I should run the ADC in differential mode but I didn’t quite get it. I imagine the what currently goes in my ADC (blue wire from photo) will remain the same, and instead of comparing the input against GND, I need compare against the other connection of the CT?

Yes, that’s the general idea. Then you won’t get the d.c. offset in the ADC output and so won’t need to remove it in the software. I think that is a better engineering solution. But you don’t have to do it that way. If you need to use all four ADC inputs of your ADC for four separate measuring circuits, keep it as you have it.

1 Like

You can see it varies quite a bit of from half cycle to half cycle as it needs to tweak how much energy to put in to keep the drum spinning at the required speed. I suspect it’s another load that would benefit from continuous monitoring.

Assuming that the hand cranked circuit i’ve put together is fine here are the logs that show what happens in a 20ms window:
start calc. Number of samples: 120
sample 0: 5; offsetI: 32736.0048828125; filteredI: -32731.0048828125; sqI: 1071318680.6386957; sumI: 1071318680.6386957
sample 1: 3; offsetI: 32704.03905773163; filteredI: -32701.03905773163; sqI: 1069357955.4552895; sumI: 2140676636.093985
sample 2: 5; offsetI: 32672.106402401812; filteredI: -32667.106402401812; sqI: 1067139840.7058414; sumI: 3207816476.7998266
sample 3: 5; offsetI: 32640.204931305718; filteredI: -32635.204931305718; sqI: 1065056600.908321; sumI: 4272873077.7081475
sample 4: 4; offsetI: 32608.33363742749; filteredI: -32604.33363742749; sqI: 1063042571.9406857; sumI: 5335915649.648833
sample 5: 4; offsetI: 32576.49346785969; filteredI: -32572.49346785969; sqI: 1060967330.7137623; sumI: 6396882980.362596
sample 6: 5; offsetI: 32544.685368769984; filteredI: -32539.685368769984; sqI: 1058831123.8985434; sumI: 7455714104.261139
sample 7: 5; offsetI: 32512.908332277046; filteredI: -32507.908332277046; sqI: 1056764104.1397274; sumI: 8512478208.4008665
sample 8: 7; offsetI: 32481.164281171306; filteredI: -32474.164281171306; sqI: 1054571345.7605023; sumI: 9567049554.16137
sample 9: 5; offsetI: 32449.449276990475; filteredI: -32444.449276990475; sqI: 1052642288.8872077; sumI: 10619691843.048576
sample 10: 5; offsetI: 32417.765244493414; filteredI: -32412.765244493414; sqI: 1050587350.7946402; sumI: 11670279193.843216
sample 11: 4; offsetI: 32386.111176871837; filteredI: -32382.111176871837; sqI: 1048601124.2712879; sumI: 12718880318.114504
sample 12: 5; offsetI: 32354.488997988174; filteredI: -32349.488997988174; sqI: 1046489438.4309579; sumI: 13765369756.545462
sample 13: 3; offsetI: 32322.895747013576; filteredI: -32319.895747013576; sqI: 1044575661.0978262; sumI: 14809945417.643288
sample 14: 4; offsetI: 32291.334325385633; filteredI: -32287.334325385633; sqI: 1042471957.8392253; sumI: 15852417375.482513
sample 15: 4; offsetI: 32259.8037254585; filteredI: -32255.8037254585; sqI: 1040436873.9753025; sumI: 16892854249.457815
sample 16: 6; offsetI: 32228.305870257856; filteredI: -32222.305870257856; sqI: 1038276995.5964539; sumI: 17931131245.054268
sample 17: 3; offsetI: 32196.835844993933; filteredI: -32193.835844993933; sqI: 1036443066.4144162; sumI: 18967574311.468685
sample 18: 4; offsetI: 32165.397528739057; filteredI: -32161.397528739057; sqI: 1034355491.0015827; sumI: 20001929802.47027
sample 19: 6; offsetI: 32133.9918670899; filteredI: -32127.9918670899; sqI: 1032207861.4117947; sumI: 21034137663.882065
sample 20: 5; offsetI: 32102.615898469692; filteredI: -32097.615898469692; sqI: 1030256946.3656944; sumI: 22064394610.24776
sample 21: 7; offsetI: 32071.27252356884; filteredI: -32064.27252356884; sqI: 1028117572.4656918; sumI: 23092512182.71345
sample 22: 4; offsetI: 32039.956827745045; filteredI: -32035.956827745045; sqI: 1026302529.8691444; sumI: 24118814712.582596
sample 23: 5; offsetI: 32008.67269021795; filteredI: -32003.67269021795; sqI: 1024235065.6626023; sumI: 25143049778.245197
sample 24: 3; offsetI: 31977.41715048141; filteredI: -31974.41715048141; sqI: 1022363352.1129998; sumI: 26165413130.358196
sample 25: 7; offsetI: 31946.196039982893; filteredI: -31939.196039982893; sqI: 1020112243.6804589; sumI: 27185525374.038654
sample 26: 3; offsetI: 31915.001512600098; filteredI: -31912.001512600098; sqI: 1018375840.5401909; sumI: 28203901214.578846
sample 27: 6; offsetI: 31883.84037831045; filteredI: -31877.84037831045; sqI: 1016196707.1850402; sumI: 29220097921.763885
sample 28: 4; offsetI: 31852.707721691007; filteredI: -31848.707721691007; sqI: 1014340183.5417004; sumI: 30234438105.305588
sample 29: 7; offsetI: 31821.608397744043; filteredI: -31814.608397744043; sqI: 1012169307.5018058; sumI: 31246607412.807392
sample 30: 5; offsetI: 31790.53749110562; filteredI: -31785.53749110562; sqI: 1010320393.5984809; sumI: 32256927806.405872
sample 31: 4; offsetI: 31759.495950586963; filteredI: -31755.495950586963; sqI: 1008411523.067745; sumI: 33265339329.473618
sample 32: 5; offsetI: 31728.485700635218; filteredI: -31723.485700635218; sqI: 1006379544.9984071; sumI: 34271718874.472023
sample 33: 4; offsetI: 31697.504757568193; filteredI: -31693.504757568193; sqI: 1004478243.8179977; sumI: 35276197118.29002
sample 34: 7; offsetI: 31666.55699901588; filteredI: -31659.55699901588; sqI: 1002327549.3739355; sumI: 36278524667.663956
sample 35: 5; offsetI: 31635.637509759028; filteredI: -31630.637509759028; sqI: 1000497229.2737749; sumI: 37279021896.93773
sample 36: 6; offsetI: 31604.749191878404; filteredI: -31598.749191878404; sqI: 998480950.4912361; sumI: 38277502847.42896
sample 37: 6; offsetI: 31573.891038370708; filteredI: -31567.891038370708; sqI: 996531744.6104456; sumI: 39274034592.039406
sample 38: 6; offsetI: 31543.06301977855; filteredI: -31537.06301977855; sqI: 994586343.9134837; sumI: 40268620935.95289
sample 39: 5; offsetI: 31512.264130110798; filteredI: -31507.264130110798; sqI: 992707692.9645666; sumI: 41261328628.91746
sample 40: 5; offsetI: 31481.495317483736; filteredI: -31476.495317483736; sqI: 990769757.4715755; sumI: 42252098386.38903
sample 41: 5; offsetI: 31450.756552525254; filteredI: -31445.756552525254; sqI: 988835605.160685; sumI: 43240933991.54971
sample 42: 3; offsetI: 31420.04585276693; filteredI: -31417.04585276693; sqI: 987030770.1148597; sumI: 44227964761.66457
sample 43: 5; offsetI: 31389.367097051338; filteredI: -31384.367097051338; sqI: 984978498.0824786; sumI: 45212943259.747055
sample 44: 5; offsetI: 31358.718301058125; filteredI: -31353.718301058125; sqI: 983055651.3021072; sumI: 46195998911.049164
sample 45: 4; offsetI: 31328.098458967248; filteredI: -31324.098458967248; sqI: 981199144.2670743; sumI: 47177198055.31624
sample 46: 3; offsetI: 31297.507542503412; filteredI: -31294.507542503412; sqI: 979346202.3278029; sumI: 48156544257.64404
sample 47: 4; offsetI: 31266.947476543937; filteredI: -31262.947476543937; sqI: 977371884.921145; sumI: 49133916142.565186
sample 48: 4; offsetI: 31236.417254398875; filteredI: -31232.417254398875; sqI: 975463887.5528725; sumI: 50109380030.11806
sample 49: 6; offsetI: 31205.918800048876; filteredI: -31199.918800048876; sqI: 973434933.1296433; sumI: 51082814963.2477
sample 50: 5; offsetI: 31175.449152783203; filteredI: -31170.449152783203; sqI: 971596900.3862431; sumI: 52054411863.63395
sample 51: 5; offsetI: 31145.00926103244; filteredI: -31140.00926103244; sqI: 969700176.777186; sumI: 53024112040.41113
sample 52: 5; offsetI: 31114.599095738464; filteredI: -31109.599095738464; sqI: 967807155.8975714; sumI: 53991919196.3087
sample 53: 5; offsetI: 31084.21862787153; filteredI: -31079.21862787153; sqI: 965917830.5190368; sumI: 54957837026.827736
sample 54: 5; offsetI: 31053.86782843025; filteredI: -31048.86782843025; sqI: 964032193.4273311; sumI: 55921869220.255066
sample 55: 7; offsetI: 31023.54862156655; filteredI: -31016.54862156655; sqI: 962026288.394002; sumI: 56883895508.64907
sample 56: 3; offsetI: 30993.255117053304; filteredI: -30990.255117053304; sqI: 960395912.2200485; sumI: 57844291420.86912
sample 57: 4; offsetI: 30962.992172603055; filteredI: -30958.992172603055; sqI: 958459196.3432972; sumI: 58802750617.21242
sample 58: 4; offsetI: 30932.758781809498; filteredI: -30928.758781809498; sqI: 956588119.7833581; sumI: 59759338736.99577
sample 59: 4; offsetI: 30902.554915811637; filteredI: -30898.554915811637; sqI: 954720695.8854275; sumI: 60714059432.8812
sample 60: 5; offsetI: 30872.381522339165; filteredI: -30867.381522339165; sqI: 952795242.0456452; sumI: 61666854674.92685
sample 61: 5; offsetI: 30842.237595071256; filteredI: -30837.237595071256; sqI: 950935222.494876; sumI: 62617789897.42172
sample 62: 3; offsetI: 30812.12115210732; filteredI: -30809.12115210732; sqI: 949201946.1652267; sumI: 63566991843.58695
sample 63: 5; offsetI: 30782.036072857216; filteredI: -30777.036072857216; sqI: 947225949.4299543; sumI: 64514217793.01691
sample 64: 4; offsetI: 30751.979397004816; filteredI: -30747.979397004816; sqI: 945438236.9986327; sumI: 65459656030.01554
sample 65: 5; offsetI: 30721.953049937427; filteredI: -30716.953049937427; sqI: 943531204.6720601; sumI: 66403187234.6876
sample 66: 5; offsetI: 30691.956025474596; filteredI: -30686.956025474596; sqI: 941689270.1094116; sumI: 67344876504.79701
sample 67: 5; offsetI: 30661.98829498097; filteredI: -30656.98829498097; sqI: 939850931.3186002; sumI: 68284727436.115616
sample 68: 5; offsetI: 30632.04982984915; filteredI: -30627.04982984915; sqI: 938016181.2800629; sumI: 69222743617.39568
sample 69: 4; offsetI: 30602.13962493719; filteredI: -30598.13962493719; sqI: 936246148.5071514; sumI: 70158989765.90283
sample 70: 4; offsetI: 30572.25862920971; filteredI: -30568.25862920971; sqI: 934418435.622254; sumI: 71093408201.52509
sample 71: 4; offsetI: 30542.406814142123; filteredI: -30538.406814142123; sqI: 932594290.746042; sumI: 72026002492.27113
sample 72: 4; offsetI: 30512.584151237686; filteredI: -30508.584151237686; sqI: 930773706.9131514; sumI: 72956776199.18428
sample 73: 4; offsetI: 30482.790612027493; filteredI: -30478.790612027493; sqI: 928956677.1718153; sumI: 73885732876.3561
sample 74: 6; offsetI: 30453.028121195435; filteredI: -30447.028121195435; sqI: 927021521.4128656; sumI: 74812754397.76897
sample 75: 4; offsetI: 30423.29274217083; filteredI: -30419.29274217083; sqI: 925333370.9338869; sumI: 75738087768.70285
sample 76: 5; offsetI: 30393.587378164804; filteredI: -30388.587378164804; sqI: 923466242.8403573; sumI: 76661554011.54321
sample 77: 5; offsetI: 30363.911023303313; filteredI: -30358.911023303313; sqI: 921663478.5208474; sumI: 77583217490.06406
sample 78: 4; offsetI: 30334.26267269462; filteredI: -30330.26267269462; sqI: 919924833.7946525; sumI: 78503142323.8587
sample 79: 5; offsetI: 30304.644252115813; filteredI: -30299.644252115813; sqI: 918068441.8047749; sumI: 79421210765.66348
sample 80: 3; offsetI: 30275.05280265086; filteredI: -30272.05280265086; sqI: 916397180.8864816; sumI: 80337607946.54996
sample 81: 4; offsetI: 30245.49122764827; filteredI: -30241.49122764827; sqI: 914547791.6719272; sumI: 81252155738.22188
sample 82: 4; offsetI: 30215.958521371267; filteredI: -30211.958521371267; sqI: 912762437.697058; sumI: 82164918175.91893
sample 83: 3; offsetI: 30186.453679065242; filteredI: -30183.453679065242; sqI: 911040875.9962771; sumI: 83075959051.9152
sample 84: 5; offsetI: 30156.97960320678; filteredI: -30151.97960320678; sqI: 909141873.9921976; sumI: 83985100925.90741
sample 85: 4; offsetI: 30127.53333406302; filteredI: -30123.53333406302; sqI: 907427260.5284059; sumI: 84892528186.43582
sample 86: 4; offsetI: 30098.115821041476; filteredI: -30094.115821041476; sqI: 905655807.0502589; sumI: 85798183993.48608
sample 87: 5; offsetI: 30068.72801262249; filteredI: -30063.72801262249; sqI: 903827742.0169423; sumI: 86702011735.50302
sample 88: 5; offsetI: 30039.368903235165; filteredI: -30034.368903235165; sqI: 902063315.4156195; sumI: 87604075050.91864
sample 89: 4; offsetI: 30010.0374882906; filteredI: -30006.0374882906; sqI: 900362285.7487009; sumI: 88504437336.66734
sample 90: 4; offsetI: 29980.734717305942; filteredI: -29976.734717305942; sqI: 898604624.3117354; sumI: 89403041960.97908
sample 91: 5; offsetI: 29951.461538871074; filteredI: -29946.461538871074; sqI: 896790558.6990845; sumI: 90299832519.67816
sample 92: 4; offsetI: 29922.21597096202; filteredI: -29918.21597096202; sqI: 895099646.885127; sumI: 91194932166.5633
sample 93: 5; offsetI: 29892.999939740377; filteredI: -29887.999939740377; sqI: 893292540.3979208; sumI: 92088224706.96121
sample 94: 4; offsetI: 29863.811463236725; filteredI: -29859.811463236725; sqI: 891608340.6200433; sumI: 92979833047.58125
sample 95: 3; offsetI: 29834.650514542158; filteredI: -29831.650514542158; sqI: 889927372.4217834; sumI: 93869760420.00304
sample 96: 6; offsetI: 29805.52097302405; filteredI: -29799.52097302405; sqI: 888011450.2217002; sumI: 94757771870.22473
sample 97: 6; offsetI: 29776.41987832383; filteredI: -29770.41987832383; sqI: 886277899.7316988; sumI: 95644049769.95644
sample 98: 5; offsetI: 29747.346226098907; filteredI: -29742.346226098907; sqI: 884607159.03314; sumI: 96528656928.98958
sample 99: 4; offsetI: 29718.29998954998; filteredI: -29714.29998954998; sqI: 882939623.86897; sumI: 97411596552.85855
sample 100: 4; offsetI: 29689.282118466435; filteredI: -29685.282118466435; sqI: 881215974.4529431; sumI: 98292812527.3115
sample 101: 5; offsetI: 29660.29356171012; filteredI: -29655.29356171012; sqI: 879436436.2312058; sumI: 99172248963.5427
sample 102: 4; offsetI: 29631.332337528762; filteredI: -29627.332337528762; sqI: 877778821.4383775; sumI: 100050027784.98108
sample 103: 4; offsetI: 29602.399395792894; filteredI: -29598.399395792894; sqI: 876065246.7928731; sumI: 100926093031.77396
sample 104: 5; offsetI: 29573.49568544544; filteredI: -29568.49568544544; sqI: 874295937.1002055; sumI: 101800388968.87416
sample 105: 4; offsetI: 29544.61922481512; filteredI: -29540.61922481512; sqI: 872648184.1855167; sumI: 102673037153.05968
sample 106: 5; offsetI: 29515.771940415885; filteredI: -29510.771940415885; sqI: 870885660.5192375; sumI: 103543922813.57892
sample 107: 4; offsetI: 29486.95185063032; filteredI: -29482.95185063032; sqI: 869244449.8265859; sumI: 104413167263.4055
sample 108: 5; offsetI: 29458.16088202619; filteredI: -29453.16088202619; sqI: 867488685.9425178; sumI: 105280655949.34802
sample 109: 5; offsetI: 29429.398029602336; filteredI: -29424.398029602336; sqI: 865795199.4044659; sumI: 106146451148.75249
sample 110: 5; offsetI: 29400.663265901552; filteredI: -29395.663265901552; sqI: 864105018.842274; sumI: 107010556167.59476
sample 111: 4; offsetI: 29371.955586930944; filteredI: -29367.955586930944; sqI: 862476815.3559484; sumI: 107873032982.9507
sample 112: 4; offsetI: 29343.27594280308; filteredI: -29339.27594280308; sqI: 860793112.8479435; sumI: 108733826095.79865
sample 113: 5; offsetI: 29314.625282702687; filteredI: -29309.625282702687; sqI: 859054134.2124445; sumI: 109592880230.0111
sample 114: 6; offsetI: 29286.00357832505; filteredI: -29280.00357832505; sqI: 857318609.5467277; sumI: 110450198839.55782
sample 115: 6; offsetI: 29257.409824830593; filteredI: -29251.409824830593; sqI: 855644976.7401958; sumI: 111305843816.298
sample 116: 4; offsetI: 29228.842041798533; filteredI: -29224.842041798533; sqI: 854091392.368075; sumI: 112159935208.66608
sample 117: 4; offsetI: 29200.30215699209; filteredI: -29196.30215699209; sqI: 852424059.642381; sumI: 113012359268.30846
sample 118: 6; offsetI: 29171.7920962919; filteredI: -29165.7920962919; sqI: 850643428.6041231; sumI: 113863002696.91258
sample 119: 4; offsetI: 29143.307924322868; filteredI: -29139.307924322868; sqI: 849099266.3085054; sumI: 114712101963.22108
Irms: 2.3588703394044135; I_Ratio: 0.0000762939453125;

And the associated code:
const calc = (samples) => {
let ICAL = 1;
let ADC_COUNTS = 65536; // numeric span of the ADC for your platform
let SupplyVoltage = 5000;
let sumI = 0;
let offsetI = ADC_COUNTS >> 1;

console.log(`start calc. Number of samples: ${samples.length}`);
for (let i = 0; i < samples.length; i++) {
    let sampleI = samples[i];
    let filteredI = 0;

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    //  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI - offsetI) / 1024);
    filteredI = sampleI - offsetI;

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

    console.log(`sample ${i}: ${sampleI}; offsetI: ${offsetI}; filteredI: ${filteredI}; sqI: ${sqI}; sumI: ${sumI}`);
}

let I_RATIO = ICAL * ((SupplyVoltage / 1000.0) / (ADC_COUNTS));
let Irms = I_RATIO * Math.sqrt(sumI / samples.length);
console.log(`Irms: ${Irms}; I_Ratio: ${I_RATIO};`)

return Irms * 230;
}

From what I can tell, the code is doing the same thing as emonLib is doing.

My fear is that I may have a bug in the hardware (since I have no idea what I am doing anymore :slight_smile:) that is causing the measurement to be incorrect.

Another hypothesis is that I may be using the ADC in the wrong way (given that it is one more thing that is different between my setup compared and the learning page. I just connected the VCC and GND of the ADC to that of the Raspberry PI (5V). Connected the SCL & SDA, and then I connected the live wire coming from the sensor to my A0 pin (blue cable in the photo from couple posts above)

Can anyone spot my errors?

Firstly, How do you know that, and which 20 ms window is it? If it’s immediately after you connect the power, then the electronics have yet to stabilise - you should leave it a few seconds before start your program. Then, the d.c. filter needs to run in order for that to stabilise, before you can get meaningful numbers.

So I suggest you delay reporting the numbers until you’ve done a few hundred times around the loop.

Second, the data sheet says: “The ADS1113/4/5 can perform conversions at rates
up to 860 samples per second (SPS).” What have you set that to? (See Config Register - Bits [7-5] ). Because 120 samples in 20 ms implies 6000 samples per second. Even the 12-bit ADS1015 can only do 3300 SPS.

So how do you know that you have collected 120 samples in 20 ms? I think, at best, you can collect 17.2 samples in 20 ms.

When you get it working, I’d expect to see - running at 860 SPS - is something like this: 108 samples over about 124 ms (the amplitude scaled appropriately of course).
adc