Timer values on screen

I was wondering if it is possible in FPMI to have some sort of timer that will start when an event occurs on the screen and as it is accumulating it will display the value. Then when the event clears it will stop accumulating and clear till the next time.

We have an indicator light on one screen and when the indicator is on start accumulating time and display in H:mm:ss then when the indicator is cleared it will stop accumulating and clear. So how would be the best way to handle this?

THanks and have a great day.

Sounds like the timer component.

Ooooh, I need this too. I was excited to see this post. However, I need a bit more hand holding. Iā€™m trying the timer, but canā€™t get the time to display right. Iā€™m guessing I bind a label to the value?

What should the ā€œboundā€ property be on the timer? :prayer:

Thanks. :prayer:

Jeff,

Iā€™ve come up with a couple of ways of doing this, depending on whether you want to display more than 23 hours.

Youā€™re right in thinking you have to bind a label to the value of the timer. However, this will only give you the number of seconds. To display it in time format you will need to bind label.text to an expression.

First off you need to configure a timer. The fields should be set as follows:

Delay: 1000
Initial delay: 1000
Running: tied to the trigger, a point that will be true when you want to time and false when you donā€™t
Step by: 1, if you want your time to increment every second
Bound: the maximum value the timer can reach e.g. 86,400 for 24 hours

The following code works if you want to display less than 24 hours i.e. up to 23:59:59:

dateFormat(dateArithmetic(toDate("2008-01-01 00:00:00"),{Root Container.Timer.value},"second"),"H:mm:ss")This code adds the number of seconds from the timer to an arbitrary date (we ignore the date part anyway), then display only the time part on-screen.

The following code works if you want to display more than 24 hours:

[code]numberFormat(toInteger({Root Container.Timer.value}/3600),ā€œ00ā€)

  • ā€œ:ā€
  • numberFormat(toInteger(({Root Container.Timer.value}%3600)/60),ā€œ00ā€)
  • ā€œ:ā€
  • numberFormat({Root Container.Timer.value}%60,ā€œ00ā€)
    [/code]Remember that in this case youā€™ll have to set the Timer.Bound field to a suitable maximum value.

This still leaves you with the problem of when to reset the timer. The way I achieved this was by creating a new Dynamic property called ā€˜Triggerā€™ on the label, binding its value to the actual trigger point, then adding the following code to the label propertyChange event:

if event.propertyName == 'Trigger': if event.newValue == 1: event.source.parent.getComponent('Timer').value = 0 This resets the timer value every time the trigger goes true.

Also remember that this will only work while the window containing the timer is open. It would be best to put the timer on a window that is never closed, like a common buttonbar.

Let me know if you need any more help.

Al

@ AlThePal: Great ideas! The only thing I can add to this is a suggestion. If you are using triggers from the PLC anyway, and you want your timer to count all the time, you should use a FactorySQL Hour Meter. Any time I hear someone say they want a value to record/count/update regardless of what window is open, I think ā€œThis needs to be done in FactorySQL.ā€

Any OPC Item in the PLC can be used as an hour meter (itā€™s a check box in the Edit Item pop up). What this means is when you reference that OPC Item in an Action Item, you get the number of seconds it has been active. ie: when a trigger goes high, it would start at 0 and keep counting until the trigger goes low again. You can then use that Action Item to write the number of seconds to the database.

Wow! Thanks Guys! Great Stuff Al. I think the hour meter may work best this time to record the data for me. Have a good one!!!

I think I must be missing something. I am attempting something similar. I want to start an accumulating timer while a trigger is 0 (low). I have created a group with 1 OPC tag (PE1). I set this tag as an Hour Meter, & Accumulate On Zero (because I want to time the low state).

I then created an Action item to store the value in a db table. The action item is ā€œ{PE1}ā€ with the result to be stored in the table.

All I am getting in the table is the boolean value of the tag. Did I miss something? or am I off in left field?

Thanks,

Adam

Hmmā€¦ Iā€™m kind of thinking that the action item should represent the accumulated value, but this is a point we go back and forth on here.

At any rate, if all youā€™re doing with the action item is writing it to the DB, itā€™s unnecessary. Your hourmeter OPC item will write itself to the database just like any other opc item. Make sure itā€™s not set to ā€œread onlyā€, and it will write itā€™s value to the corresponding field (defined by ā€œfield nameā€) in the groupā€™s table.

Let me know if Iā€™m missing something about your setup/intention.

Regards,

One more thingā€¦ you mentioned ā€œbooleanā€. I just noticed that for some reason, hour meters donā€™t seem to work as youā€™d expect with boolean data types. If using boolean types, try switching them to ā€œIntegerā€ (by double clicking the item and changing the ā€œData typeā€ property).

Regards,

Colby, thanks for the tip. I changed the datatype to INT and it now accumulates.

My problem now is that all of the values in the column change. I have the setting to change only the Last Record, however, it changes all of the values. I will look at that next.

Thanks for the help yet again,

Adam

Youā€™re sure you have it set to only update the last record, and yet it still updates all rows? Thatā€™s very strangeā€¦ I think a little more information is required: What version of fsql are you using? Did you create the table yourself, or was it auto-generated by FactorySQL? Do you still have the action item writing, and if so, is it set to ā€œignore group triggerā€ (<- wordage may be different depending on your version). Does the group have a trigger?

Basically, I canā€™t see how it would be possible to write to all rows unless you had the group set to ā€œcustom where clauseā€ with a setting of 1=1 or something else that was true for each row. However, depending on your version of fsql and your trigger/action item settings, there may be one other way. Or, there may just simply be something Iā€™m missing.

Regards,

I am using FSQL version 4.1.5 with a table that I created using FSQL.

I am using a trigger to begin the timing.

The function I am attempting to do is monitor a photoeye for a ā€œ0ā€ condition. As long as this condition is FALSE, I want to accumulate time. When the photoeye becomes blocked, I want to store that accumulated time, then get ready for the next instance.

I am looking into it nowā€¦

Thanks so far for your help.

I now have a new record being created at each instance of the photoeye block condition. Now my only problem is that the accumulated count resets when the trigger clears.

Iā€™m looking into that now.

<UPDATE 2>

OK, I have it resolved; a little messy, but it works for me. I hade to create (3) FSQL groups and perform the individual db functions within each one. Every thing looks good.

Hi-

Iā€™m glad you got it working. Usually in these cases there are 2 groups involved, though certainly this depends a lot on the fine details of what you want to accomplish. One group usually inserts a new row, on some trigger. This is also meant to clear out the hour meter. The other group updates the last row with the hour meter value.

I think the main trick is to make sure that your DB is set to default the hour meter column to 0, instead of NULL. That way, the new row is inserted with a value of 0, and the next time the update group runs, it will see that and reset the hour meter.

Anyhow, if you have it working, great. Just wanted to post this because I know changing the columnā€™s default to 0 is a bit of a ā€œtrickā€ that isnā€™t mentioned anywhere.

Regards,

1 Like