BASIC IDE Delay Logic

Do something but wait 3 seconds first

I need a way to give a 3 second delay or pause when an ONCHANGE tag value occurs so I can keep the deadband logging enabled with a 1 value for another 3 seconds.

I need a way to put a sleep or delay command in an ELSE condition of an IF statement so if the condition is not true, wait 3 seconds and then run the command(s) there just one time only.

This should then make the deadband value change whether that be a call to another routine or whatever is needed to make that happen after the delay period only once.

I’ve dummied down some logic running on a Flexy 205 to give an example of what I’m running now logic wise that I need to adjust for a 3 second delay within the ELSE portion of the IF condition.


BASIC IDE Logic

ONCHANGE "HOPPER2_SETPOINT_MET", "GOTO Hopper2_SetPointMet"
TSET 1, 60
ONTIMER 1, "Goto CheckVPN"
TSET 2, 30
ONTIMER 2, "Goto eSync"
END

Hopper2_SetPointMet:
IF(HOPPER2_SETPOINT_MET@ < 1) THEN
  LOGIO "HOPPER2_LIVEWEIGHT"
  SETSYS TAG, "load","HOPPER2_LIVEWEIGHT"  // -- Load Tag
  SETSYS TAG, "LogEnabled", 1              // -- Enable historical logging
  SETSYS TAG, "LogDB", 1                   // -- Enable deadband logging
  SETSYS TAG, "save" 
  LOGIO "HOPPER2_LIVEWEIGHT"
ELSE
  LOGIO "HOPPER2_LIVEWEIGHT"
  SETSYS TAG, "load","HOPPER2_LIVEWEIGHT"  // -- Load Tag
  SETSYS TAG, "LogEnabled", 1              // -- Enable historical logging
  SETSYS TAG, "LogDB", -9                  // -- Disable deadband logging
  SETSYS TAG, "save"
  LOGIO "HOPPER2_LIVEWEIGHT"
ENDIF
END

You should just be able to put all of the TSETs in the top of your section. I’d avoid putting them in a goto function unless you want to change the value of a TSET.

@Tim_hms

Yes, I actually changed that yesterday after I created the post and I took the TSET out of the routine and put it above after finding another post you mention using the same TSET for multiple and separate ONTIMER; however, the result was when the ONTIMER was used in the conditional routine per the ONCHANGE of the tag, it made the tag start logging ever 5 seconds indefinitely rather than giving me the 5 second delay and having it only run once for LOGIO.

I found the Advanced data transfer schedule from last year where Jordan helped me and gave me a function type solution to emulate a delay which I marked as the solution but I was only after the DMSync command in that case and never used the function.

I guess I need a solution where if conditional logic goes to a routine or a function, etc. then I need a way to tell it to delay for X seconds and then run the logic beneath.

I read over the programming guide and all and read how the code is executed\queued but it’s not 100% clear to me if I use a function as per that post from Jordan and then call it and pass in the parameter for the number of seconds to delay, if that will delay all execution of everything else or just whatever is in the conditional logic or whatever I need it to delay on.

Essentially when there is a specific tag that ON, then I need to set the deadband logging to a negative value so it does not log when the value changes if it were set to 1 but I need it to wait 5 seconds before that change occurs without affecting the other logic from other stuff programmed in the BASIC IDE interface of the Flexy 205 device.

Is there not a sleep() or timeout() function or something like that I could use or so I need to use a custom function as per that one Jordan mentioned from that post, and if I am to use that one, will it affect the execution of other code while it counts or whatever?

Hi PJ,

Was this the code that you were looking at earlier?

delay example.txt (442 Bytes)

I think I should be able to make some kind of delay for your project using this. Can you try and implement it and if you run into issues, I can help you take a look at it on teamviewer?

Thanks,
Tim

1 Like

@Tim_hms

This might work for the need but I cannot test right now as they are running production from the eWON I need to use it.

I will test as soon as I can when they are not running and see if it works. I’ll circle back around to the post but this seems like it should do what I need but i’ll test and analyze with more thorough detail as soon as I can.

Thanks!!

Sounds good to me, let me know if you run into issues

@Tim_hms

I came up with some logic that I think will suffice but I’ll need to see if it actually works to turn off the deadband logging on the 3 second delay as expected though.

I believe the Init Section logic needs to be in this specific order to work as I need it but it’s still not clear to me how the eWON execution will work if ONCHANGE for the HOPPER1_SETPOINT_MET tag senses a change and during its 3 second delay (like second #1) the HOPPER2_SETPOINT_MET2 tag has a change how exactly does that work.

If I have a need for 3 second delay logic for more than 4 tags and if using separate TSET will be a requirement for such a solution as described above, then the TSET limitation of 1-4 quickly becomes an issue.

I turned this logic on last night and even though the plant didn’t run today, there were some 1 bits set on the HOPPER2_LIVEWEIGHT tag (nor 0 values) and the deadband for the tag was set to 1 rather than -9 so I changed that back and see what happens when they actually run tomorrow.

Perhaps there’s a more dynamic way to write a BASIC function to complete this sort of task.

Init Section

TSET 3, 0      // -- Initialize Timer
ONCHANGE "HOPPER1_SETPOINT_MET", "GOTO Hopper1_SetPointMet"
ONTIMER 3, "@timeroff()" // -- Disable Timer
ONCHANGE "HOPPER2_SETPOINT_MET", "GOTO Hopper2_SetPointMet"
ONTIMER 3, "@timeroff()"
END

Hopper2_SetPointMet:
IF(HOPPER2_SETPOINT_MET@ < 1) THEN
  LOGIO "HOPPER2_LIVEWEIGHT"
  SETSYS TAG, "load","HOPPER2_LIVEWEIGHT"  // -- Load Tag
  SETSYS TAG, "LogEnabled", 1              // -- Enable historical logging
  SETSYS TAG, "LogDB", 1                   // -- Enable deadband logging
  SETSYS TAG, "save" 
  LOGIO "HOPPER2_LIVEWEIGHT"
ELSE
  LOGIO "HOPPER2_LIVEWEIGHT"
  @delay()
  ONTIMER 3, "@Hopper2DBandOff()"
  LOGIO "HOPPER2_LIVEWEIGHT"
ENDIF
END

FUNCTION Hopper2DBandOff()
  //Run logic here that starts after the x second delay
  LOGIO "HOPPER2_LIVEWEIGHT"
  SETSYS TAG, "load","HOPPER2_LIVEWEIGHT"  // -- Load Tag
  SETSYS TAG, "LogEnabled", 1              // -- Enable historical logging
  SETSYS TAG, "LogDB", -9                  // -- Disable deadband logging
  SETSYS TAG, "save"
  LOGIO "HOPPER2_LIVEWEIGHT"
  @timeroff()
ENDFN
END

FUNCTION delay()
  TSET 3, 3 // -- Initialize timer with a 3 second delay
ENDFN
END

FUNCTION timeroff()
  TSET 3, 0  // -- Disable Timer
ENDFN
END

I think that this might help you if you need multiple delays for a tag. It’s only using one Tset and is just using an additional tag as a counter to create the delays.

multidelay example.txt (552 Bytes)

Hi PJ,

Just wanted to see if that code helped?

@Tim_hms -

I apologize for the delay as this plant just started back up a couple hours ago from planned downtime for a few days which I wasn’t aware of when I originally asked the question but I have data now and can provide some feedback.

I can confirm that the first script example you provided named "Delay example.txt " did indeed give us what we needed to control the logic to basically make it turn deadband to 1 when a specific tag goes OFF and then once that same specific tag goes ON to then log that tag for 3 or so more seconds before changing deadband back to a negative value to turn off logging but not disable it because once an hour we also LOGIO tag values so when we visualize the data, I get an hourly point always regardless.

We need to record specific tag data when a weight setpoint is met and record that for a few more seconds afterwards too. We get sporadic weights recorded/noise such as 299, 300,301, 300, 299, 301, etc. fluctuation incrementally increasing by one after the weight setpoint is met.

NOTE: Stopping that noise at the sensor/tag level does not seem to be an option in this particular case as I’ve already asked about the root level solution.

Keeping the [required] deadband to 1 for that tag’s value logs way too much data and we are bringing it into MySQL tables so this gives us another way to not have to work with or store unnecessary data at the eWON level between the PLC and the MySQL in addition to the other eWON services playing the middle man we use.

I’m not sure what the problem was when I checked the other day after I initially implemented it but everything seems to work as expected with the script as I posted in my above response labeled BASIC IDE Logic.

I still think the multidelay example.txt is good logic that I could use later potentially if needed as I scale it for business needs, but for now I’ll leave as-is since it’s giving me the expected result so far.

I appreciate the good help as usual; support here has always been great for us!!

Hi PJ,

Is there a number I can call you at to go over that specific tag weight setpoint and see if we can find a solution? I just want to try and get a little more info on what you’re trying to do with it first.

Thanks,
-Tim

Hey Tim -

The solution you provided which I tested worked as expected. I honestly won’t know if I’ll need to extend it or scale it further until they get the other hopper up and running and we start getting data from it.

This is for a new plant and Hopper2 is the only one running right now. I’m happy to open a new post and link/reference back to this one on it if I find there are issues if Hopper2 and Hopper1 setpoints are met at the same time.

My flexibility is less available at the moment for Mon. - Fri. 8-5 EDT so unless we can talked after (or before) those hours, I’ll only be able to use this forum, email, etc.

If I use the logic I provided right above your response with the attachment related to the multidelay example if Hopper1 and Hopper2 setpoints are met at the same time, will there be a conflict?

With that same logic I used in that post right above the response you provided with the multidelay example using only Hopper1 and Hopper2 only and no other hoppers, could you write me a snippet from the multidelay example and incorporate some of that other logic I used into it to give me a rough idea how I should structure the flow, etc.?

Even if it’s not perfect and you get me in the right direction, that’ll be good for me if you think the way I have it now (from that post) I will have trouble when 2 setpoints are met at the same time.

I think this might be a good starting point

example for pj.txt (1.6 KB)

1 Like

Wow, I didn’t think about or know it was possible for ONCHANGE to be used with a variable like that. Everything makes sense with the counter variable and the conditional and nested if statements too checking that value.

I am a little confused how it knows 1 is for hopper1 and 2 is for hopper2 with the way it’s written but I’ll need to test it more to know for sure but they need to start running the additional hopper I suppose first before I can do that.

If I have two triggers then I need to use something for each of those to be triggered, right?

ONCHANGE "Intialize1", "@delay()"
ONCHANGE "Intialize2", "@delay()"

It will be possible for Initialize1 to have 2 or 3 changes in a row and Initialize2 to not have any during that time. It seems like this logic expects the delay_count@ variable value of 1 to always be one ONCHANGE intialize and 2 to be another ONCHANGE initialize.

In any case, I don’t do much BASIC script so you will know better than me on this but I will get it tested and confirmed. In the meantime, I’m fine with this being the solution since it makes sense to me other than my lack of understanding the precise flow of logic with init and when functions are called, etc. with this language.

Feel free to update or include anything further if what additional detail I added here justifies any modifications of the logic you provided to accommodate for the tags’ inconsistent changing pattern and needs.

I appreciate your time and effort helping me with this Tim!!

Hi PJ,

the Initialize that I created was to just turn the counter on. The way I wrote it was basically so that it’s calling a tag on the Flexy called Initialize and when it sees that value change it would cause the counter to start. We could also do an if statement inside of the delay with something like this:

FUNCTION delay()
If Initialize@ = 1 Then
TSET 3, 3 // – Initialize timer with a 3 second delay
Print “Timer Started”
Endif
Else
ENDFN

If you want it to be time dependent you could do something like this:

Function Check()
current_time$ = TIME$ // grabs the current time
time_str$ = current_time$(12 To 13) //grabs the current hour
time_check% = Val time_str$ // converts from a string to an int
Print time_check%

if time_check% > 8 AND time_check% < 17 Then
print “Can Initialize”
else
print “Can’t Initialize”
endif
Endfn

We can then merge these to something like this:

Function Check()
current_time$ = TIME$ // grabs the current time
time_str$ = current_time$(12 To 13) //grabs the current hour
time_check% = Val time_str$ // converts from a string to an int
Print time_check%

If time_check% > 8 AND time_check% < 17 AND Initialize@ > 0 AND Initialize@ < 5 Then
Print “Can Initialize, Timer Started”
TSET 3, 3 // – Initialize timer with a 3 second delay
Else
Print “Can’t Initialize”
TSET 3, // – Doesn’t allow initialization
Endif
Endfn

1 Like

To maybe clarify more just to be sure I’m explaining it so you understand with more clarity just in case since I’m new to BASIC logic, I wanted to mention two main points below itemized in case it helps or justifies modifications to your snippet example…

  1. There is no “standard” as for the order which Hopper# may come on first or if they’ll be using both at the same time, or just one or the other only, or one only one for 5 minutes then both for x minutes, and then only the other, and so forth for any combination or variation as such with respect to order or timing.

  2. It needs to be dynamic enough to handle each Hopper# having its own “Trigger” for ONCHANGE too.

You could either have 4 different initializes that cause the code to run, or you could have it so the initialize triggers on 4 different values

Here’s a visual to see what I’m trying to do to keep data collection points efficiently since data is retained and you can imagine having hundreds of tags of data points for every change 24x7x365.

This is a zoomed in view without data all data points show for how it’s typically viewed since it’s drillable

Here’s a view I wanted to show where I unhid all the data points for an entire day where we are only catching the data when the hopper starts filling.

I’ll scale the eWON BASIC logic accordingly for all applications where this method of efficient data collection is applicable.

Can we set up a time for you to call me to go over more of this if you’re still running into issues with the code above?

Thanks,
-Tim