# Increasing the tag value in different rates

**URL:** <https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391>\
**Category:** Ignition\
**Created:** [April 24, 2024, 6:52pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391 "2024-04-24T18:52:51Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Majid\_Zamani](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@Majid\_Zamani](https://forum.inductiveautomation.com/u/Majid_Zamani)\
**Post date:** [April 24, 2024, 6:52pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/1 "2024-04-24T18:52:51Z")

</div>

I am trying to start a tag value from 0 and increase with different rate at different conditions. Example, at High rate, the value starts to increase from 0 to a value, then when rate condition changed to Medium, it continuous to increase the value but with a medium rate, and so on until it resets to 0 and start again.  
Below is my script, but it doesn’t work:  
(I am not very experience in this so it might look simple for many but has been challenging for me, please advise):

> # Define the tag paths
> 
> ```
> X_tag_path = ["[default]PredictionTabTags/ModelSuggestedO2Rate.value"]  
> Test_tag_path = ["[default]PredictionTabTags/O2LanceTEST.value"]  
>    
> # Define the increase rates for eachX_tag value
> increase_rate = {
> "High": 60 / self.props.data[0].High_O2_Flow, # Increase by 1 every 3 seconds to reach 1800 in a minute
> "Medium": 60 / self.props.data[0].Medium_O2_Flow, # Increase by 1 every 2.5 seconds to reach 1200 in a minute
> "Low": 60 / self.props.data[0].Low_O2_Flow # Increase by 1 every 1.67 seconds to reach 900 in a minute
> }
>    
> # Function to update the Test tag value based on the value of X_tag
> def updateTestValue(tagPath, previousValue, currentValue, initialChange, missedEvents):
> global increase_rate
> if currentValue.value in increase_rate:
> system.tag.writeBlocking(Test_tag_path, 0) # Reset Test tag to 0
> rate = increase_rate[currentValue.value]
> system.tag.writeBlocking(Test_tag_path, 0, 0, rate) # Start increasing Test tag with the calculated rate
> else:
> system.tag.writeBlocking(Test_tag_path, 0) # Reset Test tag to 0 if X_tag is not one of the defined values
>    
> # Bind the updateTestValue function to the X_tag
> system.tag.addTagChangeListener(X_tag_path, updateTestValue)
> 
> ```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [April 24, 2024, 6:59pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/2 "2024-04-24T18:59:58Z")

</div>

> [@Majid\_Zamani](#):
>
> `system.tag.addTagChangeListener`

You can't just make up [system functions](https://www.docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions). And this wouldn't be appropriate for a tag change event anyways. (And tag listeners run when something **else** changes a tag--they do not **produce** changes in the tag.)

This needs a state machine, which typically means a timer event.

Make a project library script with your critical code in a function, and your constant definitions outside any function. The function would use `system.tag.readBlocking()` to retrieve the current value, compute the new value, then use `system.tag.writeBlocking()` to update the tag.

In a gateway timer event, put a one-line call to your library function, like so:

```python
myLibraryScript.myGeneratorFunction()

```

Set the pace of the timer event to something appropriate for your purpose, and corresponding to your increase/decrease constants.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [April 24, 2024, 7:04pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/3 "2024-04-24T19:04:59Z")

</div>

And stop trusting ChatGPT (or whatever you're using) to understand anything about Ignition. It can _maybe_ write independent Python code for you. It _cannot_ successfully write arbitrary scripts that will drop into Ignition.

---

<div class="post-metadata">

**Author:** ![Majid\_Zamani](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@Majid\_Zamani](https://forum.inductiveautomation.com/u/Majid_Zamani)\
**Post date:** [April 24, 2024, 7:42pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/4 "2024-04-24T19:42:28Z")

</div>

Thanks for the advise @paul-griffith , as mentioned, I am not experienced in Ignition and have a deadline, so I need to get help wherever possible. Hopefully, I'll have time after this project completion to learn more and not relay on other sources.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [April 24, 2024, 7:47pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/5 "2024-04-24T19:47:39Z")

</div>

> [@Majid\_Zamani](#):
>
> get help wherever possible

Wading through the drek ChatGPT (or other LLM) produces is very _ **demotivating** _ for volunteers like me. Just don't.

---

<div class="post-metadata">

**Author:** ![Majid\_Zamani](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@Majid\_Zamani](https://forum.inductiveautomation.com/u/Majid_Zamani)\
**Post date:** [April 24, 2024, 7:51pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/6 "2024-04-24T19:51:38Z")

</div>

Thanks @pturmel, I kind of understand now, but not fully.  
I created a timer in the gateway as you explained, got rid of the listener, and used system.tag.readBlocking() to get the current value. and then write the new value, but still no luck. I'm sure I am not doing it right, yet to figure it out.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [April 24, 2024, 7:54pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/7 "2024-04-24T19:54:04Z")

</div>

Post your code (as text, in this forum's "preformatted text" block). Use screenshots only to add context surrounding the code (timer settings, script library arrangement, perhaps).

Then we might spot what your problem is.

---

<div class="post-metadata">

**Author:** ![Majid\_Zamani](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@Majid\_Zamani](https://forum.inductiveautomation.com/u/Majid_Zamani)\
**Post date:** [April 24, 2024, 8:56pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/8 "2024-04-24T20:56:54Z")

</div>

I should explain what I need to do first:  
I created a tag called "ModelSuggestedO2Rate", this tag will read the rate values of Low, Medium or High.  
Another tag called "O2LanceTEST", this is the tag I want to increase the value from 0 at a rate. It usually start with High (1800/min), up to a value let's say 30000 (This value could change as it is controlled by other factors, this is just an example of the value) , the rate tag "ModelSuggestedO2Rate" changes to medium, with rate of 1200/min. so now I want the value of the "O2LanceTEST" tag to continue increasing from 30000 but at the medium rate (1200/min), then at "O2LanceTEST" tag value of Low, the value increases at Low rate (900/min).  
The value changes will be written into the "O2LanceTEST" tag, it will be reset to 0 when the "ModelSuggestedO2Rate" tag is not Low, Medium or High.

Thanks

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [April 24, 2024, 9:17pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/9 "2024-04-24T21:17:25Z")

</div>

> [@Majid\_Zamani](#):
>
> explain what I need to do first:

Ok, that's done.

Now you can post your code. 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![Majid\_Zamani](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@Majid\_Zamani](https://forum.inductiveautomation.com/u/Majid_Zamani)\
**Post date:** [April 25, 2024, 7:22pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/10 "2024-04-25T19:22:42Z")

</div>

```python
# Define the rates of increase for Y tag
	rates = {'Low': 900, 'Medium': 1200, 'High': 1800}
	
	# Initialize the previous value of X tag to None
	previous_x = None
	
	# Initialize the value of Y tag
	y_value = 0
		# Function to update Y tag based on X tag value
	def update_y(x_tag_value, y_tag_value):
	    global previous_x, y_value
	    # Check if X tag value has changed
	    if x_tag_value != previous_x:
	        # Update the previous X tag value
	        previous_x = x_tag_value
	        # Check if the new X tag value is one of the specified rates
	        if x_tag_value in rates:
	            # Calculate the new Y tag value based on the rate for the current X tag value
	            y_value += rates[x_tag_value] / 60 # Divide by 60 to get the rate per second
	            # Write the new Y tag value to the Y tag
	            system.tag.writeBlocking("[default]PredictionTabTags/O2LanceTEST", y_value)
	        else:
	            # If X tag value is not one of the specified values, stop updating Y tag
	            return
	
	# Main loop to continuously check the X tag and update the Y tag
	while True:
	    # Read the current value of the X tag
	    x_tag_value = system.tag.readBlocking("[default]PredictionTabTags/ModelSuggestedO2Rate")
	    # Call the function to update the Y tag
	    update_y(x_tag_value, y_value)
	    # Sleep for 1 second before checking the tags again
	    time.sleep(1)

```

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [April 25, 2024, 8:11pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/11 "2024-04-25T20:11:29Z")

</div>

So much is wrong here.

First off, you've got an infinite while loop. Don't ever do this. Call this script with a periodic gateway script at a 1 second rate if you want it to execute continuously, but don't put an infinite loop.

Secondly, your readBlocking is reading a qualified value, so your call to update\_y needs to be:  
`update_y(x_tag_value[0].value, y_value)`

As long as your x\_tag\_value is a string of 'Low', 'Medium', or 'High', then you should be fine, otherwise, what value does x\_tag\_value return?

Edit: If you're trying to add every second a fraction of one of your rate values to the y value, this script won't work anyway. Try something more along these lines in a gateway timer script set for 1 second (modified from your script):

```python
# Define the rates of increase for Y tag
rates = {'Low': 900, 'Medium': 1200, 'High': 1800}
tags = system.tag.readBlocking(["[default]PredictionTabTags/ModelSuggestedO2Rate", "[default]PredictionTabTags/O2LanceTEST"])

x_value = tags[0].value
y_value = tags[1].value

# Check if the new X tag value is one of the specified rates
if x_value in rates:
	# Calculate the new Y tag value based on the rate for the current X tag value
	y_value += rates[x_value] / 60 # Divide by 60 to get the rate per second
	# Write the new Y tag value to the Y tag
	system.tag.writeBlocking(["[default]PredictionTabTags/O2LanceTEST"], [y_value])

```

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [April 25, 2024, 8:19pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/12 "2024-04-25T20:19:22Z")

</div>

```python
    else:
        # If X tag value is not one of the specified values, stop updating Y tag
        return

```

These lines aren't required.

---

<div class="post-metadata">

**Author:** ![Majid\_Zamani](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@Majid\_Zamani](https://forum.inductiveautomation.com/u/Majid_Zamani)\
**Post date:** [April 26, 2024, 12:38pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/13 "2024-04-26T12:38:01Z")

</div>

Thank you so much @michael.flagler it works very well.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [April 26, 2024, 12:45pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/14 "2024-04-26T12:45:55Z")

</div>

Did you eliminate the `while` loop and run the modified script from a gateway timer event?

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [April 26, 2024, 2:27pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/15 "2024-04-26T14:27:31Z")

</div>

I have another advice for you:  
Don't over comment your code.

Examples of comments no one will ever need:

```python
# Initialize the previous value of X tag to None
previous_x = None

```

If someone doesn't understand that code, no comment will ever help.

```python
# Check if X tag value has changed
if x_tag_value != previous_x:

```

Pretty much as above. The variables names are clear, you don't need to over-explain.

```python
# Update the previous X tag value
previous_x = x_tag_value

```

I guess you get the point by now

```python
# Check if the new X tag value is one of the specified rates
if x_tag_value in rates:

```

The code is clear enough here as well.

```python
# Calculate the new Y tag value based on the rate for the current X tag value
y_value += rates[x_tag_value] / 60 # Divide by 60 to get the rate per second

```

That line could warrant a comment, but I suggest explaining why you're doing something instead of what you're doing. Anyone can see from the code that it's doing a calculation, and adding a comment to tell you what variables you're using in that calculation doesn't say much. `# calculate the rate of {whatever} per second` is more helpful. But using a self-explaining variable name would render the whole comment useless anyway.

```python
# Write the new Y tag value to the Y tag
system.tag.writeBlocking("[default]PredictionTabTags/O2LanceTEST", y_value)

# Read the current value of the X tag
x_tag_value = system.tag.readBlocking("[default]PredictionTabTags/ModelSuggestedO2Rate")

```

Yes, the function names contains `tag.write*` and `tag.read*`. The reader should be able to figure out that they write to a tag / read a tag.

```python
# Call the function to update the Y tag
update_y(x_tag_value, y_value)

```

Here as well, the function is called `update_y`. You don't need a comment that says "call the function to update y"

```python
# Sleep for 1 second before checking the tags again
time.sleep(1)

```

You probably already know by now what I would have said, so I won't.

The point is: comments should HELP the reader understand what's going on. If they don't, remove them.  
Too many comments just add bloat and make code hard to read.

Over commenting is a pet peeve of mine. I tend to believe that if you need to comment everything, it should be better written in the first place as to not require comments.  
I use 2 types of comments:

- the docstring that explains what a function is for and how to use it: what parameters it expects, what it returns, maybe give an example if it's not straight forward.  
While I like functions that don't need too much explanation (clear name, obvious parameter names, etc), having a consistent doc string format helps create a sense of cohesion in a code base, and more importantly they allow auto-generated documentation and can be retrieved through introspection (with `help()`)
- inline comments that explain the logic or a difficult line of code (regex for example).  
You're using an equation ? Explain that.  
You're using something that's not obvious ? Explain that !

Here are examples from my own code:

```python
# NFKD: https://fr.wikipedia.org/wiki/Normalisation_Unicode#NFKD
nfkd_form = normalize('NFKD', s)

```

Do you know what 'NKFD' is ? Me neither. When I wrote this, I knew. Now ? Couldn't remember for the life of me.

```python
def chunks(it, size, fval=None):
	"""
	'Chunkify' an iterable.
	Splits 'it' into chunks of size 'size', padding with 'fval' if necessary.
	
	params:
		it (iterable):	the source iterable to split into chunks
		size (int): the size of the chunks
		fval (): a value to use for padding if the last chunk's size is less than 'size'
	return:
		an iterator over a list of lists
	
	examples:
	iterable = [1, 2, 3, 4, 5, 6, 7]
	size = 3
	fval = 'x'
	=> [[1, 2, 3], [4, 5, 6], [7, 'x', 'x']]
	
	with size = 4:
	=> [[1, 2, 3, 4], [5, 6, 7, 'x']]
	"""
	return zipl(*[iter(it)]*size, fillvalue=fval)

```

Explains what the function does, not how it does it. Who cares how it does it ! Frankly I just took the recipe from the itertools doc page.  
But what it does and what to expect from it, that's what you need to know.  
note: I took this example because the docstring is ridiculously long compared to the actual code, and because even if the actual code is way too hard to understand at first glance (at least for me), I still only explained how to use it, and not how it works.

Now I understand that it's my own VERY personal take on comments, but please, please, don't comment every little thing !

---

<div class="post-metadata">

**Author:** ![Majid\_Zamani](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@Majid\_Zamani](https://forum.inductiveautomation.com/u/Majid_Zamani)\
**Post date:** [April 26, 2024, 2:54pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/16 "2024-04-26T14:54:30Z")

</div>

Understood, thank you for the explanations.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [April 26, 2024, 5:21pm UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/17 "2024-04-26T17:21:58Z")

</div>

> [@pascal.fragnoud](#):
>
> Don't over comment your code.

Smells like GPT output to me, honestly. Unless you specifically tell them to avoid being "helpful", most GPT systems seem to default to these totally unnecessary comments.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [April 27, 2024, 6:02am UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/18 "2024-04-27T06:02:47Z")

</div>

> [@pascal.fragnoud](#):
>
> comments should HELP [...] If they don't, remove them.

Solid advice, and this is an area that I probably need to work on improving. I've been super guilty of writing more comments than the minimum necessary to understand the code, and I imagine it mostly happens when I put my commenting off until the end of the day when my brain is no longer firing on all cylinders.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [April 27, 2024, 6:52am UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/19 "2024-04-27T06:52:54Z")

</div>

I rarely comment code when I'm writing it, but rather before or after.  
Before is a good time to write a basic docstring for the functions you're about to write - you already know what it will do, and if you don't it can help you figure it out (though you probably shouldn't be writing a function that you don't know the purpose of)  
And when you're done with a piece of code, read it, and comment the things that made you stop or took time to read. Those are likely the things that will need some explanation.

There's another type of comment I didn't mention and that is helpful when working on the same codebase with other people:

```python
# modified on 27/04/2024 by pascal:
# changed x to y to avoid z issue

```

Those are not meant to stay forever, but they're super helpful during dev, especially in an environment like ignition where running diffs is unpractical.  
Actually I even do it (kind of) when working alone on something that I know I will have to get back to. I leave breadcrumbs to easily find what I should be working on.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [April 27, 2024, 7:38am UTC](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391/20 "2024-04-27T07:38:24Z")

</div>

> [@pascal.fragnoud](#):
>
> before or after.

This makes sense. While I'm developing the code, it feels like a waste of time to comment because what I'm typing is just as likely to get deleted or rewritten as it is to be kept. I start by getting the code to do what I want, and then spend time making it correct: meshing repetitive stuff into concise functions, simplifying convolution, eliminating stuff that was written but wasn't needed, etc. _[Not to mention the approaches that were tried, didn't work, and were deleted completely]_ It makes sense to me to wait until after everything has been hammered out into its final shape to start trying to explain it.

Here's the thing though; in the end, if I take the time to over comment, it works out better for my final product because I see things that I would have otherwise missed. It's kind of like an after the fact rubber duck programming where I'm spelling out what I did and why I did it, and a lot of times, I realize mistakes, misconceptions, or I simply have a better idea as a result of the effort. I probably don't need to fix this stage of my development process per say; I probably just need to be more diligent about cleaning it up afterwards.

[Next page](https://forum.inductiveautomation.com/t/increasing-the-tag-value-in-different-rates/89391.md?page=2)
