Generate 0.5s and 0.25s pulse tag

Hi,

What is the most efficient way to generate a half and quarter second pulse for use in blinking animations on pages?
I have two internal expression tags and have been using expressions with getMillis(now(5)), but this seems like it could be done more efficiently. Using this also results in periods where the bit remains higher for longer than it should.

I really wish that colour binding ‘blink’ properties would be synchronised :frowning2:

Thanks

I would create 2 Boolean client tags:

flash_half
flash_quarter

These would be driven from a client timer script running at a fixed rate of 250mS:

flash_quarter = system.tag.read('[Client]flash_quarter').value
flash_half = system.tag.read('[Client]flash_half').value
if flash_quarter:
	system.tag.write('[Client]flash_quarter', 0)
else:
	system.tag.write('[Client]flash_quarter', 1)
	system.tag.write('[Client]flash_half', not flash_half)

I think you’ll find a quarter of a second is a bit fast for the animation to keep up. One second and half a second might be better values.

1 Like
2 Likes

Thanks for the replies.

I ended up using client tags and a client script:

# Set this to the script execution time period in ms
timeInterval = 125
# Time to count up to in ms. This affects the times pulses that may be generated
counterPeriod = 2000

tag = "[Client]System/Pulses/125ms Counter"
counter = system.tag.read(tag).value

# Increment the 125ms counter tag if the time is within the counterPeriod time, otherwise reset to 0
if counter > (counterPeriod/timeInterval - 1):
	system.tag.write(tag, 0)
else:
	system.tag.write(tag, system.tag.read(tag).value + 1)

# Write the pulse values to the client tags
system.tag.write("[Client]System/Pulses/125ms", int(counter*timeInterval / 125) % 2)
system.tag.write("[Client]System/Pulses/250ms", int(counter*timeInterval / 250) % 2)
system.tag.write("[Client]System/Pulses/500ms", int(counter*timeInterval / 500) % 2)
system.tag.write("[Client]System/Pulses/750ms", int(counter*timeInterval / 750) % 2)
system.tag.write("[Client]System/Pulses/1000ms", int(counter*timeInterval / 1000) % 2)

You could also do this all without any python scripting.

  1. Create a scan class that is your flash rate (If you want it on for 0.5s, off for 0.5s, make the scan class direct at 500ms)
  2. Create an expression tag, lets call it flasher. Leave the expression blank.
  3. Edit your tag, and add a script like
if(isNull({[~]Flasher}),False,!{[~]Flasher})

That should work just peachy.

4 Likes

I wouldn’t have even thought of this, cheers!

How would the script be if the flasher needs to go high for 1 second every 15 min of the hour?

So 10:00, 10:15,10:30,10:45,11:00 but 24/7

In theory the expression below in an expression tag would give you a one second flash at the start of each quarter hour, but, depending on scan class speed, the flash may be a bit short or it may miss executions:

// True when minutes divided by 15 has no remainder and seconds are zero.
getMinute(now()) % 15 = 0 && getSecond(now()) < 1
2 Likes

Here’s an even simpler way to create a tag to drive flashing: create a client tag and set its expression to

toMillis(now(1000)) % 2000 < 1000

The value of this tag will toggle between 0 and 1 every second. You can play with the values if you want asymmetrical flashing.

4 Likes

if you could explain the script as well that would be much appreciated.

The expression gets the time now every 1000ms and converts it to total milliseconds. It then uses the modulus operator, %, with 2000 to effectively turn it into a 0-2000 value which upon reaching 2000 will loop back around to 0 and start again. <1000 will then convert 0-2000 into 1-0 over 2000 ms, so 1 for 1s, 0 for 1s

2 Likes

I like to use objectScript’s state variable, with the timing determined by the scan class:

objectScript("state.get('toggle', False)\nstate['toggle'] = not __retv")

If you want something other than a 50% duty cycle, say, one-third, I do this:

objectScript("state.get('step', 0)<1\nstate['step'] = (state.get('step', 0)+1) % 3")

(Well, I tend to put helpers in a shared script file, to which I pass the state dictionary…)

2 Likes