delay analog value

2022-07-06
2022-07-07
  • energykonnex

    energykonnex - 2022-07-06

    Hi everyone I am new to the forum. I hope you guys can help me out. What function block can I use to delay the throughput of an analog signal? I want to have a sample rate of KW every second so I can calculate kwh. If I can measure the KW’s exactly every second, this will help.
    Thanks.

     
  • ojz0r - 2022-07-06

    There are a couple of ways to do this.
    The easiest would be to have a 1 second task that simply move the momentary analog value to another variable.
    But you should probably add some kind of a filter to the input so that one misread value wont effect the whole reading.
    If you use an array of 3600 records you will have one hour, then you can shift new values in and old values out of the array and do the calculations. Best would be to initialize the array with the first value and then let the shifting continue, otherwise you have to wait one hour before all records are filled.

     
  • i-campbell

    i-campbell - 2022-07-06

    Do you mean, you want a moving average? so at 12:31:00 you show the average kW used since 11:31:01. Then a few seconds later, you show the average kW used between 11:31:06 and 12:31:05?

    Or do you mean, you want to show how many kWh have been used, since someone pressed the reset counter button?

    If its the first, I would use CODESYS Installer to install the AddOn called Control Loop Library. (If you are using before SP17, you can download this from store)

    Add the Control Loop Library to your library manager.

    Create, as ojz0r suggested, a one second task, and then a program as follows:

    Then use this declaration:

    VAR
        coeffs               : ARRAY [0..3599] OF LREAL := [3600(1.0/3600.0)];
        OneHourMovingAverage : CTRL.Filter_FIR;
        kwMovingAverageHour  : LREAL;
        kwInstantaneous      : LREAL;
    END_VAR
    

    and this implementation:

    OneHourMovingAverage(xEnable := TRUE,
                         lrValue := kwInstantaneous, 
                         lrFilteredValue => kwMovingAverageHour, 
                         palrCoefficientsB := ADR(coeffs), 
                         udiSizeCoefficientsB := SIZEOF(coeffs) );
    

    The second one is a totaliser function, and you have to do a quick sanity check for precision. What if it runs for 788,400,000 seconds continuously (25 years)?
    So a LREAL Can store any whole number between 0 to 9,007,199,254,740,992...
    Meaning you can safely just add numbers, as long as the kw measuring device you use is only accurate to 24bits (or, you only want 24bits of precision).

    so if that sanity check is OK by you, in the same task you could add:

    VAR
        kWhTotal  : LREAL;
    END_VAR
    
    kWhTotal := kWhTotal + (kwInstantaneous / 3600.0);
    
     
  • energykonnex

    energykonnex - 2022-07-07

    Hi forumers, thanks for your replys! great to hear different solutions, and I am going to look into them aswel. After messing around for a while I eventually used the following. I used the MOVE function with a 1 second timer. Every second I add the previous KW per second value to the new KW value. Eventually adding the 3600 together will have the KWh reading after one hour. seems to work.

     

Log in to post a comment.