Custom Energy Meter Sampling

Hey,

Please help me in the following code. I have made a custom energymeter card which gives the output of voltage, current and powerfactor where it throws high number of samples per second.

My friend has helped me in this regard, he had written a trapezoidal moving average method in a visual studio and made it as a pc application..

Now what i need is, i want that trapezoidal moving average method to be implemented in arduino itself.. so that it looks like standalone, which gives one averaged sample per minute...

I have attached both energy meter code as well as visual studio trapezoidal average code with this attachment.

Please help me.. Thanks in advance..

Trapezoidal Avg.txt (6.88 KB)

Energymetercodes.txt (18.4 KB)

...where it throws high number of samples per second.

Does that mean you're finding the peak over a 1 second period? Do you want a moving average of that data?

Now what i need is, i want that trapezoidal moving average method to be implemented in arduino itself.. so that it looks like standalone, which gives one averaged sample per minute...

I don't know what a trapezoidal moving average is... The [u]Smoothing Example[/u] shows you how to get a regular moving average using a circular buffer.

which gives one averaged sample per minute...

Sorry, I'm not sure what that means either.... Do you want to update the moving average once per minute, or do you want the moving-average array to hold one minute's worth of data? (i.e. report the moving average over the past minute?) And if you want one minute's worth of data, do you want to save one reading each second (so your array holds the last 60 values)? A moving-average array of 60 values is reasonable.

P.S.
Your friend doesn't seem to know about commenting code... :wink: And, is that written in Visual Basic? Java?

yeah... The thing is, i need all that samples for 60 seconds to be averaged and the serial monitor should give output as 1 sample per minute...!

The problem is, for Example, for 1 set of sixty seconds, the number of sample is 50, the second set of sixty seconds, the number of sample is 70.. so the samples keeps varying..

How do i take a average in this scenario ?

Trapezoidal average is a method where it gives the accurate averaged value than any other averaging methods...! so i'm particular in that..!

Trapezoidal method: (Current sample + previous sample)/2 = avg
(avg + current sample)/2 = avg
(avg + current sample)/2 = avg

Like this the samples keeps on adding and dividing by 2 till 60 seconds...and every one min it takes average...

I need help in this.. to form this algorithm..!

with that average ... and also i need guidance in UDP transmit of datas...

I want the current, voltage and power factor values to be transmitted using esp8266... and in my laptop.. i should connect to esp8266's wifi network and read the values in a windows application..

can anyone help me with this needs ???

Can any one convert this visual studio code into arduino code.... I'm struggling in this code for past 2 months..

this attached visual studio code gets voltage, current and powerfactor samples from the arduino and takes average and gives one sample per minute...!

Please help me

Thanks in advance

Trapezoidal Avg.txt (6.88 KB)

I'm struggling in this code for past 2 months..

So post your best shot so far.

Imports System.IO
Imports System.IO.Ports
Imports System.Threading
Imports System.Data
Imports System.Linq

Public Class PopupForm
    Dim Ports As New List(Of IO.Ports.SerialPort)
    Private WithEvents serPort As New IO.Ports.SerialPort
    Private data As String = ""
    Private table As New DataTable
    Private DateStart As DateTime


    Public Sub New()
        InitializeComponent()
        Icon = My.Resources.TrayIcon
    End Sub
    Private Sub CloseAppButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        Me.Visible = False
    End Sub
    Private Sub serPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles serPort.DataReceived

        'Wait for the buffer to fill up....
        Dim Writer As System.IO.StreamWriter
        Dim StrPath As String = TextBox4.Text
        Dim Heading As String
        Dim Word As String
        Dim curvalue As Decimal = 0
        Dim prevvalue As Decimal = 0
        Dim watts(20) As Decimal
        Dim i As Integer = 0
        Dim result As Decimal = 0.0
        Try
            System.Threading.Thread.Sleep(250)

            data = serPort.ReadExisting()
            Dim words As String() = data.Split(ControlChars.CrLf.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)

            For Each Word In words
                Dim Wordstring() As String = Split(Word, ",")
                If Wordstring.Length = 5 Then
                    If Not Decimal.TryParse(Wordstring(2), result) Then
                        Wordstring(2) = 0
                    End If
                    If Not Decimal.TryParse(Wordstring(3), result) Then
                        Wordstring(3) = 0
                    End If

                    If Not Decimal.TryParse(Wordstring(4), result) Then
                        Wordstring(4) = 0
                    End If
                    Wordstring(3) = Wordstring(3) * CDec(TextBox6.Text)
                    Wordstring(4) = Wordstring(4) * CDec(TextBox5.Text)
                    table.Rows.Add(Wordstring(0), Wordstring(1), Math.Round(CDec(Wordstring(2)), 1), Math.Round(CDec(Wordstring(3)), 1), Math.Round(CDec(Wordstring(4)), 2), Math.Round(CDec(Wordstring(2)), 1) * Math.Round(CDec(Wordstring(3)), 1) * Math.Round(CDec(Wordstring(4)), 1))
                End If
            Next

            If DateDiff(DateInterval.Minute, DateStart, DateTime.Now) >= 1 Then
                StrPath = TextBox4.Text & "_MIN.CSV"
                If File.Exists(StrPath) Then
                    Writer = File.AppendText(StrPath)
                Else
                    Writer = File.CreateText(StrPath)
                    Heading = "ted_timestamp,	ted_clientname,	ted_gwid,ted_id,	ted_device,	ted_KW,	ted_voltage,	ted_amp,	ted_pf,ted_cost" & vbCrLf
                    Writer.Write(Heading)
                End If

                Dim queryFirst = From r In table Group By key = r.Field(Of String)("ted_device") Into Group
                For Each grp In queryFirst
                    Dim Grptbl As New DataTable
                    Grptbl = grp.Group.CopyToDataTable()
                    For Each Grprow As DataRow In Grptbl.Rows
                        curvalue = Grprow("ted_watts")
                        If prevvalue <> 0 Then
                            watts(i) = watts(i) + (prevvalue + curvalue) / 2
                        Else
                            watts(i) = 0
                        End If
                        prevvalue = curvalue
                    Next Grprow
                    watts(i) = (watts(i) / Grptbl.Rows.Count) * (Grptbl.Rows.Count - 1)
                    i = i + 1
                Next

                Dim querysecond = From row In table
                Group row By ted_device = row.Field(Of String)("ted_device") Into tedGroup = Group
                Select New With {
                    Key ted_device,
                    .id = tedGroup.Min(Function(r) r.Field(Of String)("ted_id")),
                    .voltage = tedGroup.Average(Function(r) r.Field(Of Decimal)("ted_voltage")),
                    .amp = tedGroup.Average(Function(r) r.Field(Of Decimal)("ted_amp")),
                    .pf = tedGroup.Average(Function(r) r.Field(Of Decimal)("ted_pf"))
               }

                i = 0
                For Each x In querysecond
                    Word = Format(Date.Now, "MM/dd/yyyy HH:mm") & ",  " & TextBox1.Text & ",  " & TextBox2.Text & " , " & x.id & " , " & x.ted_device & ",  " & Math.Round((watts(i) / 60000), 2) & ",  " & Math.Round(x.voltage, 2) & ",  " & IIf(x.amp <= 0.5, 0, Math.Round(x.amp, 2)) & ",  " & Math.Round(x.pf, 2) & " , " & TextBox3.Text & vbCrLf
                    Writer.Write(Word)
                    i = i + 1
                Next
                Writer.Flush()
                Writer.Close()
                DateStart = DateTime.Now
                table.Clear()
            End If
        Catch ex As Exception
            ' Show the exception's message.
            MessageBox.Show(ex.Message)

            ' Show the stack trace, which is a list of methods
            ' that are currently executing.
            MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
        Finally
           
        End Try

    End Sub


    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim ports As String() = SerialPort.GetPortNames()
        Dim port As String
        Button2.Enabled = False
        If serPort.IsOpen Then
            serPort.Close()
        End If

        Try
            ' Create four typed columns in the DataTable.
            table.Columns.Add("ted_id", GetType(String))
            table.Columns.Add("ted_device", GetType(String))
            table.Columns.Add("ted_voltage", GetType(Decimal))
            table.Columns.Add("ted_amp", GetType(Decimal))
            table.Columns.Add("ted_pf", GetType(Decimal))
            table.Columns.Add("ted_watts", GetType(Decimal))
            For Each port In ports
                With serPort
                    .PortName = port
                    .BaudRate = 9600
                    .Parity = IO.Ports.Parity.None
                    .DataBits = 8
                    .StopBits = IO.Ports.StopBits.One
                    .ReceivedBytesThreshold = 2048
                    .RtsEnable = True
                End With
                DateStart = DateTime.Now
                serPort.Open()
                If serPort.BytesToRead < 1 Then serPort.Close()
            Next port
        Catch ex As Exception
            Console.Write(ex)
        End Try


        Console.ReadLine()
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Me.DialogResult = Windows.Forms.DialogResult.Abort
        Me.Close()
    End Sub


End Class

Exactly which Gokul are we talking to here?

i couldnt understand what do u mean ?

so kindly help me in this issue... trapezoidal average breaks my head

I've never heard of "trapezoidal" averaging, but average = ((average * 9) / 10) + (newReading / 10); or similar works for me.

I've never heard of "trapezoidal" averaging

energymet:
okay you may be confused of my brothers who posted..
we are three brothers.. im sai gokul.. my brothers... sree gokul and gokul nath
that makes u confuse...?

Maybe that confuses me, but at least two of you having the same email address certainly does.

How this code works ?

average = ((average * 9) / 10) + (newReading / 10);

can u explain me?
how this code helps me that fit into my problem?

Im measuring voltage, current and powerfactor .. per second it gives lot of samples..

my need is taking all the samples from 0th second to 60th second and displaying it as one sample per minute for all the inputs... is that possible ?

Grumpy_Mike:
How to Approximate Area with the Trapezoid Rule - dummies

Oh, I've done area estimations on live video using trapezoids - never thought of it as averaging.

it would seem that this post should be titled 'trapezoidal averaging help needed' and in the programming forum to catch the eyes of the programming guru's over there. although you seem to have caught the eye of two already.

As I see the problem of trying to average a RMS reading of a sine wave with a period of 1/50th of a second (1/60 for the USA) is if you are reading only the half above the zero or if you are inverting and reading each peak.

my first thoughts run to the basic sensing device, then to the amplifier stage. you certainly have an AC wave as the input and a 10bit ADC that requires a DC input value. that would mean elevating the zero and reading a value that is half the wave above that mid point of the ADC input.

I think I would look at a hardware solution. the more you can put into hardware, the less software is required and the accuracy and stability might improve by orders of magnitude.

this is the hard ware prototype..

emeter20001.png

ive got the thing...but i couldnt understand how the algorithm is be formatted for this project ?

But the hardware is already built... cant i do anything in software side? to convert the seconds samples into minutes sample in means of averaging...

If trapezoidal average is the problem...! how to take normal moving average which should give 1 sample per minute ?

I am not a good programmer, but if you can write a program for math in one platform, you should be able to write it in another.

if your hardware is fixed, then you want to make it work with software.

have you read how they do this at Home | OpenEnergyMonitor