pflanzen-box/code/waterlevel_sensor.py
2021-01-17 12:10:21 +01:00

99 lines
2.8 KiB
Python

###
# 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