Continue to Site

# STPM10 Based Energy Meter

Status
Not open for further replies.

#### osyed

##### Newbie level 4
Hello everyone,

I am working on a project which involves metering. For this purpose I am using single phase energy metering chip STPM10 from STMicroelectronics. I have successfully interfaced it with the microcontroller via SPI interface and I can read the Vrms Irms and Line Frequency by reading the internal registers of STPM10. There are four internal registers which contain 20bits energy up/down counters. I want to ask here if someone has experience with working with this device and can help me in obtaining the energy values from the device by using a sample code if possible it would be very helpful to me.

Best regards,
Owais.

I am working on a project which involves metering. For this purpose I am using single phase energy metering chip STPM10 from STMicroelectronics. I have successfully interfaced it with the microcontroller via SPI interface and I can read the Vrms Irms and Line Frequency by reading the internal registers of STPM10. There are four internal registers which contain 20bits energy up/down counters. I want to ask here if someone has experience with working with this device and can help me in obtaining the energy values from the device by using a sample code if possible it would be very helpful to me.

Are you not able to read the energy counters as you have done with the Vrms, Irms and Line Frequency?

BigDog

I am having trouble with accumulation of the energy, since the counters roll over every time they reach maximum and therefore they have to be read at least once in a second.

I am using a timer to do the reading 4 times in a second just to be sure that the difference is properly accumulated in the energy variable inside the uC.

Since the energy step for active energy is about 7.63uWh which is to be multiplied with fractional part of the energy and added to the integral part as below:

Code:
#define STEP 0.00000763

uint32_t energy = 0;
uint32_t integral = 0;
int32_t fractional = 0;

energy = integral + (fractional * STEP);

In the above code I am just concerned about the type conversion since STEP is a float which is multiplied by fractional part of energy which is a signed integer and the result is added to integral part which is defined as unsigned integer. In the end I am saving the result of the calculation in an unsigned integer energy, Doing so the fractional part of the value is truncated and only the integral part is saved. How can I make sure that I also save the fractional part of the calculation in the energy variable without using float type?

Any help would be appreciated.

Best regards.

How can I make sure that I also save the fractional part of the calculation in the energy variable without using float type?

What is the reasoning behind not using a float type?

Also, what is the specific microcontroller and compiler you are currently using?

A possible alternative is to implement or use an existing fixed point math routines and types. Which are often utilized in many DSPs and microcontrollers to reduce execution time and specific types inherent error associated with floating point types and operations.

BigDog

The reason is the speed.

I am using SAMD21 from Atmel and the development tool is Atmel Studio.

Can you please elaborate your suggestion above of using fixed point types and math routines?

Best regards.

The reason is the speed.

I wanted to ensure the avoidance was for the right reasons, operation execution times is certainly one.

Rather than regurgitate the reasons for choosing fixed point types and math routines over their floating point counterparts, I suggest you instead examine the following:

Fixed-Point Arithmetic

Fixed-Point Arithmetic GCC Support

I believe the Atmel Studio typically utilizes a GCC variant, whether or not that particular GCC variant offers the aforementioned Fixed-Point Arithmetic Support, I am unsure.

However, the SAMD21 is an ARM Cortex-M0+, there are certainly CMSIS DSP Libraries available, which provides Fixed-Point Types and Math Routines.

CMSIS - Cortex Microcontroller Software Interface Standard

I have limited experience with utilizing Atmel Studio with ARMs, particularly with the ARM Cortex-Mx series, so unfortunately I cannot provide any specific advice in those regards.

However, CMSIS libraries are available for most compilers, including many GCC variants, so I suspect it should not be an issue.

BigDog

Hi,

Add up the LSB values from the metering device. My be you need 64 bit accumulation ...

Just before displaying the energy multiply the accumulated LSB value with the stepvalue.

****
Another approach is to add up the LSB values.
And each time the accumulated value is >= 131062, then increment the Wh counter and subtract the 131062 from the accumulated value.
--> when 1 LSB means 76.3uWh, then you need 131062 LSB for 1Wh.
This technique completely avoids floating point variables as well as multiplication while maintaining high precision.

Klaus

Hi Klaus,

Thanks for the response.

I am in fact something similar to what you explained here. I am reading the counter 4 times in a second and then keeping then checking the delta between new count and old count. Then I add the delta to a signed integer since energy direction could be negative for reactive energy as well. Then I keep track of the fractional part and as soon as it reaches 131062 I increase the integral part by 1 which corresponds to 1Wh.

The problem arises when I need to read energy value with a precision of 1mWh. Lets say at any instant the integral part has 0Wh because the load connected is very small but the fractional part has accumulated about 1mWh energy then in this case I need to be able to store 1mWh in a variable.

Hi,

a signed integer since energy direction could be negative for reactive energy as well
reactive power will not result in energy flow (averaged over integers of mains period time, 1s surely is. )

The energy wil become negative if you really push energy into main frame, like photovoltaik does. If you have to take caro of this, then you surely need negative values.
You may need to adjust my calculation below on this case (mind the shift_right)

*****

there is a LSB_value remainder. (wich represents 131062 LSB for 1 Wh)

Now you could divide it by 131 and get the value in mWh
or multiply it by 0.00763.

example: there is 54321 in the remainder:
multiply it by 0.00763 and get 414,47mWh
or divide it (integer) by 131 and get 414 mWh (415 if rounded)

***
To save processing power i´d shift the lsb value 2 bits to the right. Then in any case it fits into a 16 bit value. (now 32765.5 representing 1Wh)
now perform a 16 bit x 16 bit multiplication with a constant of (1000 * 32765.5 / 65536 = 500)
54321 x 500 gives 27160500 in a 32 bit value. Use the upper 16 bit of the result and get 414 (the value in mWh)
--> this solution uses a 16 bit shift, and a 16 x 16 multiplication. No floats. But you get the result in mWh. With a max error of 1mWh (rounding and shifting)

Klaus

osyed

### osyed

Points: 2
Hi thanks again for the explanation.

While doing a 16x16 multiplication you have used 32765.5 which is a float value would this cause undefined behaviour while calculating?

Secondly, Please see below calculation let me know if I have understood it correctly:

Code:
uint32_t energy = 0;
uint32_t integral = 0;
int32_t fractional = 0;

energy = integral + (fractional / 131);

The above calculation will give me correct values in the resolution of mWh, is that correct? Since I am using a 32bit processor I think I can save the 16bit multiplication stuff because doing a 32bit calculation doesn't take much processing power specially if I am not using any floats in the calculation.

Thank again.

Hi,

While doing a 16x16 multiplication you have used 32765.5 which is a float value would this cause undefined behaviour while calculating?
You shouldn´t put the whole formula into you"C" program. Just use 500.
If you want to be more readable in the future I recommend to define a constant
.. uint16 mW_mul = (1000 * 32765.5 / 65536 )
and use mW_mul in your code.

This ensures that the controller works with a constant of "500" instead of calculating the whole formula every loop in runtime.

****
Your calculation seems to be right.

****

Yes, of course you should use 32bit variables on a 32 microcontroller. (i´m always thinking of 8 bit controllers)

Klaus

osyed

### osyed

Points: 2
Hi,

Thanks again for the response.

Okay if I understood you correctly, I should be doing something as follows:

Code:
#define MW_MUL   (1000 * 32765 / 65536)

uint32_t energy = 0;
uint32_t integral = 0;
int32_t fractional = 0;

energy = (integral * 1000) + ((fractional * MW_MUL) >> 16);

Let me know is this is correct. Moreover, I have removed the decimal from the constant since it would cause the compiler to consider the constant as float and then the rest of the variables will be converted to float before calculation. So, to avoid float I have used 32765. Secondly, I forgot to multiply the integral part with 1000 since one step of integral part represent 1000mWh = 1Wh, I was having incorrect values before since I was adding integral part directly without multiplying with 1000 first.

Best regards.

Hi,

Code:
#define MW_MUL 500 ; //  (1000 * 32765 / 65536)

uint32_t energy_mWh = 0;
uint32_t integral_Wh = 0;
int32_t fractional_LSB = 0;

energy_mWh = (integralintegral_Wh * 1000) + ((fractional_LSB * MW_MUL) >> 16);

Seems OK.
It should be fast. (I hope it doesn´t shift 16 times right)

Defining mW_mul like above, no calculation is needed (neither compiler nor microcontoller), but information is still there. It helps to read the code in some years..
I just added some unit_info to variables, so it´s easier to me to understand. You may use it or not.

Klaus

osyed

### osyed

Points: 2
Hi,

Thanks again for your help Klaus.

I have a few questions about the above method of extracting the mWh value. If I understood it correctly the shifting of the LSB is only for the reason so that we can fit it in a 16 bit value is that correct? If so lets take the example of Reactive energy counter where one step is 0.0000152uVAR, in this case since 65790 steps make up 1VAR do we still need to shift 2 bits to right and divide and multiply by 65536 and 1000 after which shifting 16 bits to the right? Moreover, the division by 65536 is to scale the value by 16 bits and lastly multiplication by 1000 is for extracting the milli out of the whole value, let me know if I understood the method correctly, if not please make corrections.

Thank you for your help in this regard.

Hi,

you have 32 bitregisters, so a shift right to fit into a 16 bit maybe is not needed. It depends on your multiplier.
What input and what output does it have? (bit count and sign)

***********
in this case since 65790 steps make up 1VAR
in other words: 65790 steps make 1000 mVAR.

The formula is: 65790 x MUL = 1000 --> MUL = 1000/65790 = 0.0152
But this is a float. If we want an integer value, we just multiply it by 65536. (=996) But then the result is also multiplied with 65536. Therefore we shift the result back 16 bits. Or just juse another 16 bit "package".
(With 8 bit and 16 bit processors we just access the upper bytes/word, then we need no shift).
I don´t know how this is with your 32 bit machine...

****
I think you got it right how I avoid float calculations.

Klaus

osyed

### osyed

Points: 2
Dear Owais,

I have a question not really related to your question !
i am just asking because i saw you had worked with STPM10 for energy metering ...

in STPM10 datasheet it is mentioned dynamic range is 1000 and for current sensing inputs which are differential inputs, it says max voltage is +-0.3 V.
but it doesn't say anything about minimum voltage, is the minimum input 0.3/1000=3mV ? it means it won't measure lower inputs ?

if i want to design a 5(100)A meter, which should be able to measure current from 20mA to 100A, so i can't use this chip ?
if i adjust the higher side on (100A) then the lowest side will be 0.1 A.
if i adjust the lower side on 0.02A then the highest side will be 20A !
are my calculations true ?!

if yes, i just saw a meter from a company which claims 5(100)A in specifications but uses this chip for ADC ... ! according to IEEE62053-21(8.3.3) standard, the meter should be able to start metering from 0.004*Ib = 20mA . and maximum 100A.

can i manage this problem by changing gain by software ?
for example i choose a shunt to produce 3mV for 20mA, then the max would be 300mV for 20A, but when i get near 20A, i decrease gain, so i have room for higher currents ...
is this possible ?!

about the minimum differential input voltage, it is written in ATM90E26 datasheet only, it is written 5uV to 25mV ( dynamic range is 5000 )
other Metering ICs just say maximum input voltage ! ( like STPM10 )
i myself calculated the minimum input voltage according to dynamic range of each device.

Status
Not open for further replies.