Page 1 of 2

Calculate percent value

Posted: Wed Dec 29, 2021 12:51 am
by soggycashew
Hello, I have a Capacitive Soil Moisture Sensor and I want to give a percent value of a min and max value from adc0. The code below gives be an error that is from the print line. What am I doing wrong? Thanks!
Error:
TypeError: unsupported types for __sub__: 'ADC', 'int'

Code: Select all

from machine import ADC
import utime

#Capacitive Soil Moisture Sensor
adc0 = machine.ADC(machine.Pin(26))

wet = 60000
dry = 24854

def scale_value(value, in_min, out_max, out_min):
  scaled_value = ((value - in_min) * 100) / (out_max - out_min)
  return scaled_value

while True:
        
    print(scale_value(adc0, dry, wet, dry))
    utime.sleep(0.5)

Re: Calculate percent value

Posted: Wed Dec 29, 2021 2:58 am
by hlovatt
I think you need `adc0.read()` when you call `scale_value`, not just `adc0`. The error message looks like it is expecting an `int`, but you are giving it an `ADC`.

Re: Calculate percent value

Posted: Wed Dec 29, 2021 3:11 am
by soggycashew
Thank you.. the below #2 worked but its giving a decimal like 89.29324. How do I round that? would the below #1 be correct and can I add it to the scaled_value instead to avoid it in my print?

1) print(str(round(scale_value(adc0.read_u16(), dry, wet, dry))))

2) print(scale_value(adc0.read_u16(), dry, wet, dry))

Re: Calculate percent value

Posted: Wed Dec 29, 2021 3:24 am
by davef
Rounding sometimes gives you more "significant" digits than the stated rounding parameter.

I have found that string formatting:

Code: Select all

 HWT_temp = "{:.1f}".format(HWT_temp)
battery_26V = "{:.2f}".format(battery_26V)
at least controls the number of displayed digits, if not any supposed benefit from rounding up or down.

Re: Calculate percent value

Posted: Wed Dec 29, 2021 7:21 am
by bulletmark
Modern way is to prefer f-strings over .format():

Code: Select all

print(f"{HWT_temp:.1f}")
print(f"{battery_26v:.2f}")

Re: Calculate percent value

Posted: Wed Dec 29, 2021 8:29 am
by davef
About a month ago I "discovered" .format after the rounding issue raised its ugly-head. I read through RealPython's string formatting tutorial ending with this:
https://realpython.com/python-string-fo ... ld-you-use and perhaps decided for the wrong reason that .format applied to me.
Python String Formatting Rule of Thumb: If your format strings are user-supplied, use Template Strings (#4) to avoid security issues. Otherwise, use Literal String Interpolation/f-Strings (#3) if you’re on Python 3.6+, and “New Style” str.format (#2) if you’re not.
Are strings that I want to format in my code not user-supplied? The word "security" suggests that these strings are coming from the outside world. What does user-supplied mean?

Re: Calculate percent value

Posted: Wed Dec 29, 2021 9:48 am
by bulletmark
davef wrote:
Wed Dec 29, 2021 8:29 am
What does user-supplied mean?
It means externally entered by a user of your program. E.g, you may have an app which uses a web page to accept text input from your users. The app should check the raw text field (e,.g limit the length, limit the range of chars input, etc) before using that string.

You potentially can't trust all external users, but you can trust yourself when writing your own code! So this concern does not apply here.

Re: Calculate percent value

Posted: Wed Dec 29, 2021 7:03 pm
by davef
Thank you. Looks like my next learning opportunity!

Re: Calculate percent value

Posted: Wed Jan 05, 2022 5:01 pm
by nekomatic
davef wrote:
Wed Dec 29, 2021 3:24 am
Rounding sometimes gives you more "significant" digits than the stated rounding parameter.
Python's round calculates the result of rounding the input to the specified number of decimal places, not significant figures.

If you want to round to significant figures there are several methods suggested here, although not all will work in MicroPython.

Or did I misunderstand you and you find round misbehaves in some other way? Can you give an example?

Re: Calculate percent value

Posted: Wed Jan 05, 2022 6:52 pm
by davef
Maybe I should have said "decimal" places. Especially with 1-wire measurements and using round 1 on the returned floating point number, I would often get:
66.4
66.30001
66.2