Hysteresis in float value for temperature display - Page 1
Forum section: electronics / beginners

author: Vindhyachal.takniki
author_rank: Frequent Contributor
timestamp: April 28, 2021, 03:18:02 pm
content: 1. I am measuring temperature of PT100 whose value is calculated in float inside the code, but on display only integer value is displayed. Now what happens is when 31.9 or 32.0, display fluctuates between 31 & 32 very rapidly.2. I tried used round off from maths library, but again display fluctuates at 34.5 and 34.4. display keep fluctuates at 34 & 35.3. how to add some hysteresis to this float value so that:a) temperature keep on showing 31 if temperature goes from 31 to 31.9b) at 32.0, it shows 32 onlyc) but when now temperature falls to 31.9, it don't fall back to 31 on display, but keep it showing 32 until temperature falls below 31.5 ?d) is there any math function for it in library?

author: Martian Tech
author_rank: Regular Contributor
timestamp: April 28, 2021, 03:22:22 pm
content: You might consider using a moving average.https://en.wikipedia.org/wiki/Moving_average

author: Syntax Error
author_rank: Frequent Contributor
timestamp: April 28, 2021, 03:48:38 pm
content: I am not sure if this the solution to your problem, but as a firmware developer it is worth knowing about anyway.For C and C++ there is the GSL, or GNU Scientific Library. This lib contains a whole zoo of functions for calculating everything from running statistics to fast fourier transforms, and a lots lots more.https://www.gnu.org/software/gsl/GSL is ported to Cygwin, so it should work with even the Arduino IDE.Running statistics library:https://www.gnu.org/software/gsl/doc/html/rstat.html

author: ejeffrey
author_rank: Super Contributor
timestamp: April 28, 2021, 04:17:38 pm
content: The easiest solution is to lower the display update rate. If your application doesn't actually demand sub-second response times (very few temperature displays do!) then don't update that quickly. It's generally no big deal if something that flickers between 24.9 and 25.0 every few seconds.It's definitely possible to add some hysteresis around the 0-9 rollover of the last digit if you want, but probably smoothing your data and reducing the update rate will solve your problem.

author: atmfjstc
author_rank: Regular Contributor
timestamp: April 28, 2021, 04:52:31 pm
content: A moving average will not necessarily be effective - you're just moving the problem from the original data potentially hovering around 31.99-32.00 to the average itself hovering around 31.99-32.00 etc. Same if you quantize/round the result.I would try a simple hysteresis algorithm like this (pseudocode):// Initializationlast_display_value = 0last_compare = 0streak = 0// Somewhere in the main loop, for each sample:value = get_incoming_data_sample()current_compare = (value > last_display_value) // 1 if true, 0 if notif (current_compare == last_compare) {streak++if (streak >= 5) { // or whatever other value, by trial and errorupdate_display(value)last_displayed_value = value}} else {streak = 1last_compare = current_compare // streak broken}

author: BeBuLamar
author_rank: Super Contributor
timestamp: April 28, 2021, 05:33:54 pm
content: I vote for slower the update rate as temperature can't change very fast any way.

author: Zero999
author_rank: Super Contributor
timestamp: April 28, 2021, 07:27:21 pm
content: Quote from: Vindhyachal.takniki on April 28, 2021, 03:18:02 pmIf your display shows3231, when the input is 31.9, then the rounding is broken. How are you converting the floating point to an integer? It sound like you're simply truncating, rather than properly rounding the result.

author: BeBuLamar
author_rank: Super Contributor
timestamp: April 28, 2021, 08:00:50 pm
content: Quote from: Zero999 on April 28, 2021, 07:27:21 pm

author: Manul
author_rank: Super Contributor
timestamp: April 28, 2021, 08:07:50 pm
content: To add hysteresis is not hard, usually it is done symetrically around 0.5, so for example the rounding point is 0.6 when going up, and 0.4 when going down.Code:double Temperature; //inputint IntValue; //last rounded value, needs to be preserved, for example, declared as global, or static local variableif (IntValue <= floor(Temperature)) {IntValue = round(Temperature - 0.1);} else {IntValue = round(Temperature + 0.1);}

author: Zero999
author_rank: Super Contributor
timestamp: April 28, 2021, 09:07:08 pm
content: Quote from: BeBuLamar on April 28, 2021, 08:00:50 pmYes, you're right. That's what he said. I'll edit it.Quote from: Manul on April 28, 2021, 08:07:50 pmYes, that's really the correct way to round, if the value is changing.

author: David Hess
author_rank: Super Contributor
timestamp: April 29, 2021, 09:54:00 pm
content: Hysteresis is the way to go and should be applied to rotary encoders as well. I wish they would include it for PC fan controls.

author: wizard69
author_rank: Super Contributor
timestamp: April 30, 2021, 01:55:51 am
content: It depends upon what you want to achieve here. For example the use of a slower update rate will reduce the flicker. Many commercial temperature display units will implement a sampling system that might give your an averaged reading of every ten or so samples. That is the meter update rate is not the sample rate.The bigger question is why is this a problem and why display only the integer value. If the fractional part was displayed, whomever is reading the display would know immediately that the readings are on the edge.Others have already discussed rounding methods that would reduce this some but from my perspective it just changes the point where you have a transition. You would just move your problem to 31.5 or similar half way point. It really comes down to how stable you want that reading to be and what the real problem is here but I suspect that some sort of filtering (possibly averaging or a running average) is needed. So is it a question of flickering at all or flickering back and forth to close to 32?By the way I'm not sure why the Math library you are using didn't give you the results you wanted. Most seem to round at 0.5.

author: Manul
author_rank: Super Contributor
timestamp: April 30, 2021, 02:37:47 pm
content: It is all about signal and noise and the problem is either real or aesthetical.If a slow signal comes to logic gate, there will be digital flicker on the output, which might mess up the otherwise correctly working circuits (real problem). In some cases it might also start oscillating. The standard solution is schmitt trigger inputs (with hysteresis), so the rising edge and falling edge thresholds are not the same. Logic gate is like 1 bit ADC. And the principle is same, does not matter how much bits there are. At least the LSB bit will flicker if signal is randomly crossing the threshold of that bit. Some amount of noise is fundamental part of nature, so this is unavoidable.If analog signal is periodically digitized, there will be bit flicker which is not correlated to the change of a true signal. Bit reduction or rounding does not remove that, because bit flicker will unavoidably propagate to higher bits at some threshold points. Slow sampling or long averaging does remove flicker in a sense that the true signal is expected to change during that time, so it masks the flicker. But it might not be an optimal, preferred solution. Even if the problem is purely aesthetical, like outputting the data to the screen, LED bar graph, things like that. Personally I do not like transition flicker. The solution is to measure the noise and apply just enough hysteresis to cancel it. Too much hysteresis is of course destroying signal information, so it is important to not overdo. The same hysteresis idea like in the example algo I posted above can be used to round to float, not just integer.

author: RJSV
author_rank: Super Contributor
timestamp: May 09, 2021, 10:52:44 pm
content: Manul gave a good reply: You want to use a hysterisis value just big enough, like 0.2 degrees, that example would use 29.6 degrees, crossed by a rising (set of readings), as your RISING EDGE event.Then, also, use 29.4 degrees as your threshold, in the case of a FALLING EDGE event. You won't need to keep track of which direction of reading, is being tracked: Just compare for > (greater than) XX.6 to find out if should round up. Plus, you also check for the second case: Any reading XX.4 or lower will signify you should round off downward.Did I re-state the info given by Manul clearly ?I recall an older WIND SPEED computer, had featured a simple LOW PASS Filter, as a higher resolution 'improvement' was exhibiting the very same value flickers. Sorry I don't have a LP filter code example, but I believe the firmware performed a type of 'averaging' where older values had less 'weight'.