### # GND ADC VCC # | | | # R1 | | # | | | # |______| | # | | # R2_1 | # | | # R2_2 | # | | # ... ... # | | # ~~~~~WATER~~~~~~~~~ # | - current - -| # R2_n | # # # VCC gets toggeled by 'power_pin', so current doesn't flow continously. # # To have equal distances between the voltages following calculation can be used: # r2 = [r1/(1-i/n) - r1/(1-(i-1)/n) for i in range(1,n)] # # example for # n = 4 # 4 r2 resistors # r1 = 10000 # 10k Ohms Resistor to GND # gives resistance values: # -> r2_1 := 3333.3 (~3300 Ohm) # -> r2_2 := 6666.7 (~6800 Ohm) # -> r2_3 := 20000.0 # ### from machine import Pin, ADC # import uasyncio as asyncio import time class WaterLevelSensor: def __init__( self, power_pin=Pin(26), adc_pin=Pin(35), resistor_ground=10000, resistors_water=[3300, 6800, 20000], resistance_water_tolerance=[400, 550, 700, 850], volume_liter=11*9*8.5/1000): self.power_pin = power_pin self.power_pin.init(mode=Pin.OUT, value=0) self.adc_pin = adc_pin self.adc = ADC(self.adc_pin) self.adc.atten(ADC.ATTN_11DB) self._r1 = resistor_ground self._r2 = resistors_water self.resistance_water_tolerance = resistance_water_tolerance self._voltage_levels = \ [4096 * self._r1 / (self._r1 + sum(self._r2[:i])) for i in range(len(self._r2), 0, -1)] print(self._voltage_levels) self.min_measure_time_ms = 500 self._last_measurment_time_ms = time.ticks_diff(time.ticks_ms(), 500) self._last_level_rel = 0 self.volume = volume_liter # asyncio.create_task(self._polling()) # from waterlevel_sensor import WaterLevelSensor; wls = WaterLevelSensor() def _measure_value(self): self.power_pin.on() self._last_measure = self.adc.read() self.power_pin.off() return self._last_measure @property def _level_rel(self): now = time.ticks_ms() if time.ticks_diff(now, self._last_measurment_time_ms) \ > self.min_measure_time_ms: self._last_measurment_time_ms = now adc_value = self._measure_value() for i, voltage in enumerate(self._voltage_levels): if adc_value >= voltage - self.resistance_water_tolerance[i]: self._last_level_rel = (i / (len(self._voltage_levels))) else: break return self._last_level_rel @property def level(self): return self._level_rel * self.volume @property def level_percent(self): return self._level_rel * 100