From 649da8457cc0293851aefccf0d5bf19bb4bd0570 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 09:36:25 +0100 Subject: [PATCH 01/17] refactor(wsen-hids): remove test from examples --- lib/wsen-hids/examples/full_test.py | 482 ---------------------------- 1 file changed, 482 deletions(-) delete mode 100644 lib/wsen-hids/examples/full_test.py diff --git a/lib/wsen-hids/examples/full_test.py b/lib/wsen-hids/examples/full_test.py deleted file mode 100644 index 6c0bb692..00000000 --- a/lib/wsen-hids/examples/full_test.py +++ /dev/null @@ -1,482 +0,0 @@ -from time import sleep, sleep_ms - -from machine import I2C -from wsen_hids import WSEN_HIDS -from wsen_hids.const import * - -# --------------------------------------------------------------------- -# Update these pins and bus number to match your board -# --------------------------------------------------------------------- -MIN_HUMIDITY = 0.0 -MAX_HUMIDITY = 100.0 -MIN_TEMPERATURE = -40.0 -MAX_TEMPERATURE = 120.0 - -def print_header(title): - print() - print("=" * 60) - print(title) - print("=" * 60) - - -def print_pass(name): - print("[PASS] {}".format(name)) - - -def print_fail(name, err=None): - if err is None: - print("[FAIL] {}".format(name)) - else: - print("[FAIL] {} -> {}".format(name, err)) - - -def read_reg(sensor, reg): - return sensor._read_reg(reg) - - -def dump_registers(sensor): - print("DEVICE_ID = 0x{:02X}".format(read_reg(sensor, REG_DEVICE_ID))) - print("AV_CONF = 0x{:02X}".format(read_reg(sensor, REG_AV_CONF))) - print("CTRL_1 = 0x{:02X}".format(read_reg(sensor, REG_CTRL_1))) - print("CTRL_2 = 0x{:02X}".format(read_reg(sensor, REG_CTRL_2))) - print("CTRL_3 = 0x{:02X}".format(read_reg(sensor, REG_CTRL_3))) - print("STATUS = 0x{:02X}".format(read_reg(sensor, REG_STATUS))) - print("H_OUT_L = 0x{:02X}".format(read_reg(sensor, REG_H_OUT_L))) - print("H_OUT_H = 0x{:02X}".format(read_reg(sensor, REG_H_OUT_H))) - print("T_OUT_L = 0x{:02X}".format(read_reg(sensor, REG_T_OUT_L))) - print("T_OUT_H = 0x{:02X}".format(read_reg(sensor, REG_T_OUT_H))) - - -def test_i2c_scan(i2c): - print_header("1) I2C scan") - devices = i2c.scan() - print("I2C devices found:", [hex(x) for x in devices]) - - if WSEN_HIDS_I2C_ADDRESS in devices: - print_pass("WSEN-HIDS address found") - return True - else: - print_fail("WSEN-HIDS address found") - return False - - -def test_device_id(sensor): - print_header("2) Device ID") - - try: - dev_id = sensor.device_id() - print("Device ID:", hex(dev_id)) - - if dev_id == WSEN_HIDS_DEVICE_ID: - print_pass("Device ID matches 0x{:02X}".format(WSEN_HIDS_DEVICE_ID)) - return True - else: - print_fail( - "Device ID matches 0x{:02X}".format(WSEN_HIDS_DEVICE_ID), - hex(dev_id), - ) - return False - - except Exception as err: - print_fail("Device ID", err) - return False - - -def test_default_registers(sensor): - print_header("3) Default driver configuration") - try: - dump_registers(sensor) - - ctrl1 = read_reg(sensor, REG_CTRL_1) - av_conf = read_reg(sensor, REG_AV_CONF) - - bdu_ok = bool(ctrl1 & CTRL_1_BDU) - - # Driver defaults proposed: - # avg_t = AVG_16, avg_h = AVG_16 - avg_t = (av_conf >> 3) & 0x07 - avg_h = av_conf & 0x07 - avg_ok = (avg_t == AVG_16) and (avg_h == AVG_16) - - if bdu_ok: - print_pass("BDU enabled") - else: - print_fail("BDU enabled") - - if avg_ok: - print_pass("Default averaging configuration") - else: - print_fail( - "Default averaging configuration", - "AVG_T={}, AVG_H={}".format(avg_t, avg_h), - ) - - return bdu_ok and avg_ok - - except Exception as err: - print_fail("Default driver configuration", err) - return False - - -def test_reboot(sensor): - print_header("4) Reboot memory") - try: - sensor.reboot() - sleep(0.05) - dump_registers(sensor) - - if sensor.device_id() == WSEN_HIDS_DEVICE_ID: - print_pass("Reboot memory") - return True - else: - print_fail("Reboot memory", "device ID mismatch after reboot") - return False - - except Exception as err: - print_fail("Reboot memory", err) - return False - - -def test_one_shot(sensor): - print_header("5) One-shot read") - - try: - humidity_rh, temperature_c = sensor.read_one_shot(timeout_ms=500) - - h_ready = sensor.humidity_ready() - t_ready = sensor.temperature_ready() - ready = sensor.data_ready() - - print("Humidity : {:.2f} %RH".format(humidity_rh)) - print("Temperature : {:.2f} °C".format(temperature_c)) - print("humidity_ready :", h_ready) - print("temperature_ready:", t_ready) - print("data_ready :", ready) - - humidity_ok = MIN_HUMIDITY <= humidity_rh <= MAX_HUMIDITY - temperature_ok = MIN_TEMPERATURE <= temperature_c <= MAX_TEMPERATURE - - if humidity_ok: - print_pass("Humidity is in a valid range") - else: - print_fail("Humidity is in a valid range", humidity_rh) - - if temperature_ok: - print_pass("Temperature is in a valid range") - else: - print_fail("Temperature is in a valid range", temperature_c) - - return humidity_ok and temperature_ok - - except Exception as err: - print_fail("One-shot read", err) - return False - - -def test_one_shot_loop(sensor, count=5, delay_s=1): - print_header("6) One-shot loop") - - ok = True - - try: - for i in range(count): - humidity_rh, temperature_c = sensor.read_one_shot(timeout_ms=500) - - print( - "#{:d} H={:.2f} %RH T={:.2f} °C".format( - i + 1, - humidity_rh, - temperature_c, - ) - ) - - if not (MIN_HUMIDITY <= humidity_rh <= MAX_HUMIDITY): - ok = False - - sleep(delay_s) - - if ok: - print_pass("One-shot loop") - else: - print_fail("One-shot loop", "invalid humidity value detected") - - return ok - - except Exception as err: - print_fail("One-shot loop", err) - return False - - -def test_continuous_mode(sensor, odr, label, wait_ms=1500, loops=5, delay_s=0.5): - print_header("7) Continuous mode - {}".format(label)) - - try: - sensor.set_continuous(odr=odr) - - ctrl1 = read_reg(sensor, REG_CTRL_1) - pd_ok = bool(ctrl1 & CTRL_1_PD) - odr_ok = (ctrl1 & CTRL_1_ODR_MASK) == odr - - print("CTRL_1 after set_continuous = 0x{:02X}".format(ctrl1)) - - if pd_ok: - print_pass("PD bit set") - else: - print_fail("PD bit set") - - if odr_ok: - print_pass("ODR configured correctly") - else: - print_fail("ODR configured correctly", "CTRL_1=0x{:02X}".format(ctrl1)) - - print("Waiting {} ms for fresh samples...".format(wait_ms)) - sleep_ms(wait_ms) - - ok = pd_ok and odr_ok - - last_h = None - last_t = None - - for i in range(loops): - humidity_rh, temperature_c = sensor.read() - print( - "#{:d} H={:.2f} %RH T={:.2f} °C ready={}".format( - i + 1, - humidity_rh, - temperature_c, - sensor.data_ready(), - ) - ) - - if not (MIN_HUMIDITY <= humidity_rh <= MAX_HUMIDITY): - ok = False - - if not (MIN_TEMPERATURE <= temperature_c <= MAX_TEMPERATURE): - ok = False - - if last_h is not None and abs(humidity_rh - last_h) > 50: - ok = False - - if last_t is not None and abs(temperature_c - last_t) > 30: - ok = False - - last_h = humidity_rh - last_t = temperature_c - - sleep(delay_s) - - sensor.set_one_shot_mode() - - if ok: - print_pass("Continuous mode - {}".format(label)) - else: - print_fail("Continuous mode - {}".format(label), "invalid sample detected") - - return ok - - except Exception as err: - print_fail("Continuous mode - {}".format(label), err) - return False - - -def test_status_helpers(sensor): - print_header("8) STATUS helpers") - - try: - sensor.set_continuous(odr=ODR_1_HZ) - sleep(1.5) - - h_avail = sensor.humidity_ready() - t_avail = sensor.temperature_ready() - ready = sensor.data_ready() - - print("humidity_ready() =", h_avail) - print("temperature_ready() =", t_avail) - print("data_ready() =", ready) - - sensor.set_one_shot_mode() - - if h_avail or t_avail or ready: - print_pass("STATUS helper methods") - return True - else: - print_fail("STATUS helper methods", "helpers do not match STATUS bits") - return False - - except Exception as err: - print_fail("STATUS helper methods", err) - return False - - -def test_unitary_methods(sensor): - print_header("9) humidity() and temperature()") - - try: - sensor.set_continuous(odr=ODR_1_HZ) - sleep(1.2) - - humidity_rh = sensor.humidity() - temperature_c = sensor.temperature() - - print("humidity() = {:.2f} %RH".format(humidity_rh)) - print("temperature() = {:.2f} °C".format(temperature_c)) - - sensor.set_one_shot_mode() - - humidity_ok = MIN_HUMIDITY <= humidity_rh <= MAX_HUMIDITY - temperature_ok = MIN_TEMPERATURE <= temperature_c <= MAX_TEMPERATURE - - if humidity_ok: - print_pass("humidity() valid") - else: - print_fail("humidity() valid", humidity_rh) - - if temperature_ok: - print_pass("temperature() valid") - else: - print_fail("temperature() valid", temperature_c) - - return humidity_ok and temperature_ok - - except Exception as err: - print_fail("humidity() and temperature()", err) - return False - - -def test_heater(sensor): - print_header("10) Heater control") - - try: - sensor.enable_heater(True) - sleep_ms(20) - ctrl2_on = read_reg(sensor, REG_CTRL_2) - heater_on_ok = bool(ctrl2_on & CTRL_2_HEATER) - - print("CTRL_2 with heater ON = 0x{:02X}".format(ctrl2_on)) - - sensor.enable_heater(False) - sleep_ms(20) - ctrl2_off = read_reg(sensor, REG_CTRL_2) - heater_off_ok = not bool(ctrl2_off & CTRL_2_HEATER) - - print("CTRL_2 with heater OFF = 0x{:02X}".format(ctrl2_off)) - - if heater_on_ok: - print_pass("Heater enable") - else: - print_fail("Heater enable") - - if heater_off_ok: - print_pass("Heater disable") - else: - print_fail("Heater disable") - - return heater_on_ok and heater_off_ok - - except Exception as err: - print_fail("Heater control", err) - return False - - -def test_average_configuration(sensor): - print_header("11) Average configuration") - - try: - sensor.set_average(avg_t=AVG_8, avg_h=AVG_4) - av_conf_1 = read_reg(sensor, REG_AV_CONF) - avg_t_1 = (av_conf_1 >> 3) & 0x07 - avg_h_1 = av_conf_1 & 0x07 - - print("AV_CONF (AVG_T=AVG_8, AVG_H=AVG_4) = 0x{:02X}".format(av_conf_1)) - - ok1 = (avg_t_1 == AVG_8) and (avg_h_1 == AVG_4) - - sensor.set_average(avg_t=AVG_64, avg_h=AVG_32) - av_conf_2 = read_reg(sensor, REG_AV_CONF) - avg_t_2 = (av_conf_2 >> 3) & 0x07 - avg_h_2 = av_conf_2 & 0x07 - - print("AV_CONF (AVG_T=AVG_64, AVG_H=AVG_32) = 0x{:02X}".format(av_conf_2)) - - ok2 = (avg_t_2 == AVG_64) and (avg_h_2 == AVG_32) - - # restore defaults - sensor.set_average(avg_t=AVG_16, avg_h=AVG_16) - - if ok1: - print_pass("Average configuration set #1") - else: - print_fail("Average configuration set #1") - - if ok2: - print_pass("Average configuration set #2") - else: - print_fail("Average configuration set #2") - - return ok1 and ok2 - - except Exception as err: - print_fail("Average configuration", err) - return False - - -def test_register_dump_after_reads(sensor): - print_header("12) Register dump after measurements") - - try: - sensor.read_one_shot(timeout_ms=500) - dump_registers(sensor) - print_pass("Register dump after measurements") - return True - except Exception as err: - print_fail("Register dump after measurements", err) - return False - - -def main(): - print_header("WSEN-HIDS full driver test") - - i2c = I2C(1) - - if not test_i2c_scan(i2c): - print() - print("Stop: sensor not found on I2C bus.") - return - - try: - sensor = WSEN_HIDS(i2c) - print_pass("Driver init") - except Exception as err: - print_fail("Driver init", err) - return - - results = [] - - results.append(test_device_id(sensor)) - results.append(test_default_registers(sensor)) - results.append(test_reboot(sensor)) - results.append(test_one_shot(sensor)) - results.append(test_one_shot_loop(sensor, count=5, delay_s=1)) - results.append(test_continuous_mode(sensor, ODR_1_HZ, "1 Hz", wait_ms=1500)) - results.append(test_continuous_mode(sensor, ODR_7_HZ, "7 Hz", wait_ms=500)) - results.append(test_continuous_mode(sensor, ODR_12_5_HZ, "12.5 Hz", wait_ms=300)) - results.append(test_status_helpers(sensor)) - results.append(test_unitary_methods(sensor)) - results.append(test_heater(sensor)) - results.append(test_average_configuration(sensor)) - results.append(test_register_dump_after_reads(sensor)) - - print_header("Final result") - - passed = sum(1 for x in results if x) - total = len(results) - - print("Passed: {}/{}".format(passed, total)) - - if passed == total: - print("All tests passed.") - else: - print("Some tests failed.") - - -main() From 8e3ba779011cecd453a2ff9382c447834d0938b5 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 09:40:12 +0100 Subject: [PATCH 02/17] feat(wsen-hids): add simple single read example --- lib/wsen-hids/examples/humidity_temperature.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 lib/wsen-hids/examples/humidity_temperature.py diff --git a/lib/wsen-hids/examples/humidity_temperature.py b/lib/wsen-hids/examples/humidity_temperature.py new file mode 100644 index 00000000..b51b5d1a --- /dev/null +++ b/lib/wsen-hids/examples/humidity_temperature.py @@ -0,0 +1,14 @@ +from machine import I2C +from wsen_hids import WSEN_HIDS + +# Initialise le bus I2C +i2c = I2C(1) + +# Initialise le capteur +sensor = WSEN_HIDS(i2c) + +# Lecture unique +humidity, temperature = sensor.read_one_shot() + +print("Humidity: {:.2f} %RH".format(humidity)) +print("Temperature: {:.2f} °C".format(temperature)) From a5f5537cb79080a0bfe298b407c71a5d83b9036d Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 09:42:59 +0100 Subject: [PATCH 03/17] style(wsen-hids): add description for humidity_temp example --- lib/wsen-hids/examples/humidity_temperature.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/wsen-hids/examples/humidity_temperature.py b/lib/wsen-hids/examples/humidity_temperature.py index b51b5d1a..b95a5691 100644 --- a/lib/wsen-hids/examples/humidity_temperature.py +++ b/lib/wsen-hids/examples/humidity_temperature.py @@ -1,3 +1,5 @@ +"""Simple read: print humidity and temperature once (beginner-friendly first example)""" + from machine import I2C from wsen_hids import WSEN_HIDS From 90b04cab53012a705d96dd596fed0da670c0f136 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 09:44:42 +0100 Subject: [PATCH 04/17] feat(wsen-hids): add a comfort monitoring example --- lib/wsen-hids/examples/comfort_monitor.py | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 lib/wsen-hids/examples/comfort_monitor.py diff --git a/lib/wsen-hids/examples/comfort_monitor.py b/lib/wsen-hids/examples/comfort_monitor.py new file mode 100644 index 00000000..098d0b58 --- /dev/null +++ b/lib/wsen-hids/examples/comfort_monitor.py @@ -0,0 +1,28 @@ +"""Loop that reads humidity + temperature every 2s and prints a comfort indicator ("Dry", "Comfortable", "Humid") based on humidity thresholds (< 30%, 30-60%, > 60%)""" + +from time import sleep + +from machine import I2C +from wsen_hids import WSEN_HIDS + +i2c = I2C(1) +sensor = WSEN_HIDS(i2c) + +def comfort_label(humidity): + if humidity < 30: + return "Dry" + elif humidity <= 60: + return "Comfortable" + else: + return "Humid" + +while True: + humidity, temperature = sensor.read_one_shot() + comfort = comfort_label(humidity) + + print("Humidity: {:.2f} %RH".format(humidity)) + print("Temperature: {:.2f} °C".format(temperature)) + print("Comfort: {}".format(comfort)) + print() + + sleep(2) From d057dbe13422c44c5898a69bacfaf6ee039bb1b6 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 09:49:05 +0100 Subject: [PATCH 05/17] feat(wsen-hids): add a data logger example --- lib/wsen-hids/examples/data_logger.py | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 lib/wsen-hids/examples/data_logger.py diff --git a/lib/wsen-hids/examples/data_logger.py b/lib/wsen-hids/examples/data_logger.py new file mode 100644 index 00000000..fbf367c7 --- /dev/null +++ b/lib/wsen-hids/examples/data_logger.py @@ -0,0 +1,29 @@ +'''Read every 5s and print CSV-formatted output (timestamp, humidity, temperature) suitable for serial capture''' +from time import sleep, ticks_diff, ticks_ms + +from daplink_flash import DaplinkFlash +from machine import I2C +from wsen_hids import WSEN_HIDS + +i2c = I2C(1) +sensor = WSEN_HIDS(i2c) +flash = DaplinkFlash(i2c) + +# Set filename and erase +flash.set_filename("data", "CSV") +flash.clear_flash() +sleep(0.5) +print("Flash erased.") + +start_ms = ticks_ms() + +print("timestamp,humidity,temperature") + +while True: + humidity, temperature = sensor.read_one_shot() + elapsed_s = ticks_diff(ticks_ms(), start_ms) // 1000 + + print("{},{:.2f},{:.2f}".format(elapsed_s, humidity, temperature)) + flash.write_line("{},{:.2f},{:.2f}".format(elapsed_s, humidity, temperature)) + + sleep(5) From 434c4fa39e93c0a955cc1dc83a6da3f888844a69 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 09:52:34 +0100 Subject: [PATCH 06/17] feat(wsen-hids): add dew point example --- lib/wsen-hids/examples/dew_point.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 lib/wsen-hids/examples/dew_point.py diff --git a/lib/wsen-hids/examples/dew_point.py b/lib/wsen-hids/examples/dew_point.py new file mode 100644 index 00000000..875c32f4 --- /dev/null +++ b/lib/wsen-hids/examples/dew_point.py @@ -0,0 +1,24 @@ +"""Compute and display the dew point temperature from humidity + temperature using the Magnus formula. Useful to understand when condensation might occur.""" +from math import log + +from machine import I2C +from wsen_hids import WSEN_HIDS + +i2c = I2C(1) +sensor = WSEN_HIDS(i2c) + +def dew_point_celsius(temperature_c, humidity): + # Magnus formula + a = 17.62 + b = 243.12 # °C + + gamma = (a * temperature_c / (b + temperature_c)) + log(humidity / 100.0) + dp = (b * gamma) / (a - gamma) + return dp + +humidity, temperature = sensor.read_one_shot() +dew_point = dew_point_celsius(temperature, humidity) + +print("Humidity: {:.2f} %RH".format(humidity)) +print("Temperature: {:.2f} °C".format(temperature)) +print("Dew point: {:.2f} °C".format(dew_point)) From 3f7ccd6e7f1b10d43ad2bcee4081e908c751cc6b Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 09:53:04 +0100 Subject: [PATCH 07/17] style(wsen-hids): remove french comment --- lib/wsen-hids/examples/humidity_temperature.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/wsen-hids/examples/humidity_temperature.py b/lib/wsen-hids/examples/humidity_temperature.py index b95a5691..7668e552 100644 --- a/lib/wsen-hids/examples/humidity_temperature.py +++ b/lib/wsen-hids/examples/humidity_temperature.py @@ -3,13 +3,10 @@ from machine import I2C from wsen_hids import WSEN_HIDS -# Initialise le bus I2C i2c = I2C(1) -# Initialise le capteur sensor = WSEN_HIDS(i2c) -# Lecture unique humidity, temperature = sensor.read_one_shot() print("Humidity: {:.2f} %RH".format(humidity)) From adf4f5ea409aaf8bc10368e9e01acf2edc3455b9 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 10:03:24 +0100 Subject: [PATCH 08/17] feat(wsen-hids): add heater to reduce humidity example --- lib/wsen-hids/examples/heater_demo.py | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 lib/wsen-hids/examples/heater_demo.py diff --git a/lib/wsen-hids/examples/heater_demo.py b/lib/wsen-hids/examples/heater_demo.py new file mode 100644 index 00000000..972f889b --- /dev/null +++ b/lib/wsen-hids/examples/heater_demo.py @@ -0,0 +1,39 @@ +"""Show the effect of the built-in heater (enable_heater()): read humidity before, enable heater for a few seconds, read again. The heater evaporates condensation — humidity should drop. Demonstrates a feature unique to this sensor.""" +from time import sleep + +from machine import I2C +from wsen_hids import WSEN_HIDS + +i2c = I2C(1) +sensor = WSEN_HIDS(i2c) + +# Read before heater +humidity_before, temperature_before = sensor.read_one_shot() + +print("Before heater:") +print("Humidity: {:.2f} %RH".format(humidity_before)) +print("Temperature: {:.2f} °C".format(temperature_before)) +print() + +# Enable heater +print("Heater ON...") +sensor.enable_heater(True) + +# Wait a few seconds to see the effect +sleep(10) + +# New reading +humidity_after, temperature_after = sensor.read_one_shot() + +# Disable the heater +sensor.enable_heater(False) +print("Heater OFF") +print() + +print("After heater:") +print("Humidity: {:.2f} %RH".format(humidity_after)) +print("Temperature: {:.2f} °C".format(temperature_after)) +print() + +print("Delta humidity: {:.2f} %RH".format(humidity_after - humidity_before)) +print("Delta temperature: {:.2f} °C".format(temperature_after - temperature_before)) From cdbf8cf0bb71b4f889e5aca8cf589e40b29eb5e5 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 11:38:49 +0100 Subject: [PATCH 09/17] feat(wsen-hids): add low power sampling example --- lib/wsen-hids/examples/low_power_sampling.py | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 lib/wsen-hids/examples/low_power_sampling.py diff --git a/lib/wsen-hids/examples/low_power_sampling.py b/lib/wsen-hids/examples/low_power_sampling.py new file mode 100644 index 00000000..b1e841e1 --- /dev/null +++ b/lib/wsen-hids/examples/low_power_sampling.py @@ -0,0 +1,31 @@ +"""Use power_off() between readings to minimize energy consumption. Read one-shot every 10s, print values, then power down. Show gc.mem_free() and elapsed time to illustrate battery-friendly usage.""" + +import gc +from time import sleep, ticks_diff, ticks_ms + +from machine import I2C +from wsen_hids import WSEN_HIDS + +i2c = I2C(1) +sensor = WSEN_HIDS(i2c) + +while True: + gc.collect() + + t0 = ticks_ms() + + sensor.power_on() + + humidity, temperature = sensor.read_one_shot() + + sensor.power_off() + + elapsed_ms = ticks_diff(ticks_ms(), t0) + + print("Humidity: {:.2f} %RH".format(humidity)) + print("Temperature: {:.2f} °C".format(temperature)) + print("Free RAM: {} bytes".format(gc.mem_free())) + print("Elapsed: {} ms".format(elapsed_ms)) + print() + + sleep(10) From 815ab754c071e4d58616fc4b65bd65659ed07f9f Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 11:50:09 +0100 Subject: [PATCH 10/17] docs(wsen-hids): add new examples to readme. --- lib/wsen-hids/README.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/wsen-hids/README.md b/lib/wsen-hids/README.md index 140d3be2..47b5ccde 100644 --- a/lib/wsen-hids/README.md +++ b/lib/wsen-hids/README.md @@ -293,16 +293,19 @@ No calibration is required for basic usage. --- -# Examples - -Example scripts are located in: - -``` -examples/ -``` - -Examples include: - -* basic one-shot measurements -* continuous measurement mode -* driver validation tests +## Examples + +The `examples/` directory provides practical scripts demonstrating how to use the WSEN-HIDS sensor in different scenarios. + +### Overview + +| Example | Description | +|--------|------------| +| `one_shot_mode.py` | Basic one-shot measurements: trigger a measurement and read humidity and temperature on demand | +| `continuous_mode.py` | Continuous measurement mode: sensor runs continuously and values are read periodically | +| `humidity_temperature.py` | Beginner-friendly example: perform a single read and print humidity and temperature | +| `comfort_monitor.py` | Read every 2 seconds and display a comfort indicator (`Dry`, `Comfortable`, `Humid`) based on humidity | +| `data_logger.py` | Log data every 5 seconds in CSV format (`timestamp, humidity, temperature`) for serial capture | +| `dew_point.py` | Compute and display dew point using temperature and humidity (Magnus formula) | +| `heater_demo.py` | Demonstrate the built-in heater: compare readings before and after enabling it | +| `low_power_sampling.py` | Low-power sampling: perform one-shot measurements every 10 seconds, power down the sensor between reads, and display memory usage and timing | From 31e73d635feddf3c26967581267dfa5f78b69658 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 12:45:32 +0100 Subject: [PATCH 11/17] fix(wsen-hids): fix power down issue --- lib/wsen-hids/examples/low_power_sampling.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/wsen-hids/examples/low_power_sampling.py b/lib/wsen-hids/examples/low_power_sampling.py index b1e841e1..a181abcc 100644 --- a/lib/wsen-hids/examples/low_power_sampling.py +++ b/lib/wsen-hids/examples/low_power_sampling.py @@ -17,9 +17,6 @@ sensor.power_on() humidity, temperature = sensor.read_one_shot() - - sensor.power_off() - elapsed_ms = ticks_diff(ticks_ms(), t0) print("Humidity: {:.2f} %RH".format(humidity)) @@ -28,4 +25,6 @@ print("Elapsed: {} ms".format(elapsed_ms)) print() + sensor.power_off() + sleep(10) From cc384ace56b84327791bb5a2f9220973a1deb0eb Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 17:10:31 +0100 Subject: [PATCH 12/17] fix(wsen-hids): Add sleep_ms ans forgotten titile line in datalogger example - Added a warning for the date erasing - Replace sleep by sleep_ms - writen head line for csv file --- lib/wsen-hids/examples/data_logger.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/wsen-hids/examples/data_logger.py b/lib/wsen-hids/examples/data_logger.py index fbf367c7..ede64b3a 100644 --- a/lib/wsen-hids/examples/data_logger.py +++ b/lib/wsen-hids/examples/data_logger.py @@ -1,5 +1,12 @@ -'''Read every 5s and print CSV-formatted output (timestamp, humidity, temperature) suitable for serial capture''' -from time import sleep, ticks_diff, ticks_ms +''' +Read every 5s and print CSV-formatted output (timestamp, humidity, temperature) suitable for serial capture +This example writes data both to the serial console and to DAPLink flash storage. + +WARNING: If configured to erase on startup, this script will erase the entire +DAPLink flash contents before logging, which is a destructive operation. +Make sure you have backed up any important data before enabling erasure. +''' +from time import sleep_ms, ticks_diff, ticks_ms from daplink_flash import DaplinkFlash from machine import I2C @@ -12,12 +19,13 @@ # Set filename and erase flash.set_filename("data", "CSV") flash.clear_flash() -sleep(0.5) +sleep_ms(500) print("Flash erased.") start_ms = ticks_ms() print("timestamp,humidity,temperature") +flash.write_line("timestamp,humidity,temperature") while True: humidity, temperature = sensor.read_one_shot() @@ -26,4 +34,4 @@ print("{},{:.2f},{:.2f}".format(elapsed_s, humidity, temperature)) flash.write_line("{},{:.2f},{:.2f}".format(elapsed_s, humidity, temperature)) - sleep(5) + sleep_ms(5000) From 515e28deb9c86fb165c4638ce37f56753769ff7d Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 17:18:26 +0100 Subject: [PATCH 13/17] fix(wsen-hids): Added sleep_ms in comfort monitor example --- lib/wsen-hids/examples/comfort_monitor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/wsen-hids/examples/comfort_monitor.py b/lib/wsen-hids/examples/comfort_monitor.py index 098d0b58..75544f50 100644 --- a/lib/wsen-hids/examples/comfort_monitor.py +++ b/lib/wsen-hids/examples/comfort_monitor.py @@ -1,6 +1,6 @@ """Loop that reads humidity + temperature every 2s and prints a comfort indicator ("Dry", "Comfortable", "Humid") based on humidity thresholds (< 30%, 30-60%, > 60%)""" -from time import sleep +from time import sleep_ms from machine import I2C from wsen_hids import WSEN_HIDS @@ -8,6 +8,7 @@ i2c = I2C(1) sensor = WSEN_HIDS(i2c) + def comfort_label(humidity): if humidity < 30: return "Dry" @@ -25,4 +26,4 @@ def comfort_label(humidity): print("Comfort: {}".format(comfort)) print() - sleep(2) + sleep_ms(2000) From 0db64d12612e37300f34aab3223246f58be4d903 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 17:22:55 +0100 Subject: [PATCH 14/17] fix(wsen-hids): add sleep_ms to heater demo example Also put read() after heater disable --- lib/wsen-hids/examples/heater_demo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/wsen-hids/examples/heater_demo.py b/lib/wsen-hids/examples/heater_demo.py index 972f889b..f074076b 100644 --- a/lib/wsen-hids/examples/heater_demo.py +++ b/lib/wsen-hids/examples/heater_demo.py @@ -1,5 +1,5 @@ """Show the effect of the built-in heater (enable_heater()): read humidity before, enable heater for a few seconds, read again. The heater evaporates condensation — humidity should drop. Demonstrates a feature unique to this sensor.""" -from time import sleep +from time import sleep_ms from machine import I2C from wsen_hids import WSEN_HIDS @@ -20,7 +20,7 @@ sensor.enable_heater(True) # Wait a few seconds to see the effect -sleep(10) +sleep_ms(1000) # New reading humidity_after, temperature_after = sensor.read_one_shot() From 6b5d47d6678834c91eca96ca21e1910a01d285e9 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 17:28:10 +0100 Subject: [PATCH 15/17] style(wsen-hids): put docstring on multiple line in the example --- lib/wsen-hids/examples/comfort_monitor.py | 3 ++- lib/wsen-hids/examples/dew_point.py | 3 ++- lib/wsen-hids/examples/heater_demo.py | 4 +++- lib/wsen-hids/examples/low_power_sampling.py | 4 +++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/wsen-hids/examples/comfort_monitor.py b/lib/wsen-hids/examples/comfort_monitor.py index 75544f50..84b9db34 100644 --- a/lib/wsen-hids/examples/comfort_monitor.py +++ b/lib/wsen-hids/examples/comfort_monitor.py @@ -1,4 +1,5 @@ -"""Loop that reads humidity + temperature every 2s and prints a comfort indicator ("Dry", "Comfortable", "Humid") based on humidity thresholds (< 30%, 30-60%, > 60%)""" +"""Loop that reads humidity + temperature every 2s and prints a comfort indicator ("Dry", "Comfortable", "Humid") +based on humidity thresholds (< 30%, 30-60%, > 60%)""" from time import sleep_ms diff --git a/lib/wsen-hids/examples/dew_point.py b/lib/wsen-hids/examples/dew_point.py index 875c32f4..2431ae10 100644 --- a/lib/wsen-hids/examples/dew_point.py +++ b/lib/wsen-hids/examples/dew_point.py @@ -1,4 +1,5 @@ -"""Compute and display the dew point temperature from humidity + temperature using the Magnus formula. Useful to understand when condensation might occur.""" +"""Compute and display the dew point temperature from humidity + temperature using the Magnus formula. +Useful to understand when condensation might occur.""" from math import log from machine import I2C diff --git a/lib/wsen-hids/examples/heater_demo.py b/lib/wsen-hids/examples/heater_demo.py index f074076b..100a99d6 100644 --- a/lib/wsen-hids/examples/heater_demo.py +++ b/lib/wsen-hids/examples/heater_demo.py @@ -1,4 +1,6 @@ -"""Show the effect of the built-in heater (enable_heater()): read humidity before, enable heater for a few seconds, read again. The heater evaporates condensation — humidity should drop. Demonstrates a feature unique to this sensor.""" +"""Show the effect of the built-in heater +(enable_heater()): read humidity before, enable heater for a few seconds, read again. +The heater evaporates condensation — humidity should drop. Demonstrates a feature unique to this sensor.""" from time import sleep_ms from machine import I2C diff --git a/lib/wsen-hids/examples/low_power_sampling.py b/lib/wsen-hids/examples/low_power_sampling.py index a181abcc..d694e7d3 100644 --- a/lib/wsen-hids/examples/low_power_sampling.py +++ b/lib/wsen-hids/examples/low_power_sampling.py @@ -1,4 +1,6 @@ -"""Use power_off() between readings to minimize energy consumption. Read one-shot every 10s, print values, then power down. Show gc.mem_free() and elapsed time to illustrate battery-friendly usage.""" +"""Use power_off() between readings to minimize energy consumption. +Read one-shot every 10s, print values, then power down. +Show gc.mem_free() and elapsed time to illustrate battery-friendly usage.""" import gc from time import sleep, ticks_diff, ticks_ms From 12ec00e89bdee85df1b651e480cf2e28e8ef6ee5 Mon Sep 17 00:00:00 2001 From: Charly-sketch Date: Wed, 25 Mar 2026 17:32:56 +0100 Subject: [PATCH 16/17] fix(wsen-hids): added minimum humidity to ensure math + added lint style space --- lib/wsen-hids/examples/dew_point.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/wsen-hids/examples/dew_point.py b/lib/wsen-hids/examples/dew_point.py index 2431ae10..0cd60b2a 100644 --- a/lib/wsen-hids/examples/dew_point.py +++ b/lib/wsen-hids/examples/dew_point.py @@ -8,12 +8,15 @@ i2c = I2C(1) sensor = WSEN_HIDS(i2c) + def dew_point_celsius(temperature_c, humidity): # Magnus formula a = 17.62 b = 243.12 # °C - gamma = (a * temperature_c / (b + temperature_c)) + log(humidity / 100.0) + # Clamp humidity to a small positive value to avoid log(0) when humidity is 0.0 + safe_humidity = max(humidity, 0.01) + gamma = (a * temperature_c / (b + temperature_c)) + log(safe_humidity / 100.0) dp = (b * gamma) / (a - gamma) return dp From 97bfc6919359d7009400d0c81ae32416190ff96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Thu, 26 Mar 2026 08:51:00 +0100 Subject: [PATCH 17/17] fix(wsen-hids): Address review feedback on examples. --- lib/wsen-hids/README.md | 2 +- lib/wsen-hids/examples/data_logger.py | 31 ++++++++++++-------- lib/wsen-hids/examples/low_power_sampling.py | 27 ++++++++++------- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/lib/wsen-hids/README.md b/lib/wsen-hids/README.md index 47b5ccde..94f68765 100644 --- a/lib/wsen-hids/README.md +++ b/lib/wsen-hids/README.md @@ -308,4 +308,4 @@ The `examples/` directory provides practical scripts demonstrating how to use th | `data_logger.py` | Log data every 5 seconds in CSV format (`timestamp, humidity, temperature`) for serial capture | | `dew_point.py` | Compute and display dew point using temperature and humidity (Magnus formula) | | `heater_demo.py` | Demonstrate the built-in heater: compare readings before and after enabling it | -| `low_power_sampling.py` | Low-power sampling: perform one-shot measurements every 10 seconds, power down the sensor between reads, and display memory usage and timing | +| `low_power_sampling.py` | Low-power sampling: one-shot every 10 s with `power_off()` between reads. Requires firmware >= v0.1.0 (#238) | diff --git a/lib/wsen-hids/examples/data_logger.py b/lib/wsen-hids/examples/data_logger.py index ede64b3a..7b7020b6 100644 --- a/lib/wsen-hids/examples/data_logger.py +++ b/lib/wsen-hids/examples/data_logger.py @@ -1,26 +1,31 @@ -''' -Read every 5s and print CSV-formatted output (timestamp, humidity, temperature) suitable for serial capture -This example writes data both to the serial console and to DAPLink flash storage. - -WARNING: If configured to erase on startup, this script will erase the entire -DAPLink flash contents before logging, which is a destructive operation. -Make sure you have backed up any important data before enabling erasure. -''' +"""Log humidity and temperature to DAPLink flash and serial console. + +Reads every 5 seconds and writes CSV-formatted output (timestamp, +humidity, temperature). Data is stored on the DAPLink flash as +DATA.CSV and also printed to the serial console. + +WARNING: When ERASE_FLASH_ON_START is True, the entire DAPLink flash +is erased before logging. Make sure you have backed up any important +data before enabling erasure. +""" from time import sleep_ms, ticks_diff, ticks_ms from daplink_flash import DaplinkFlash from machine import I2C from wsen_hids import WSEN_HIDS +# Set to True to erase the DAPLink flash on startup (DESTRUCTIVE). +ERASE_FLASH_ON_START = False + i2c = I2C(1) sensor = WSEN_HIDS(i2c) flash = DaplinkFlash(i2c) -# Set filename and erase -flash.set_filename("data", "CSV") -flash.clear_flash() -sleep_ms(500) -print("Flash erased.") +flash.set_filename("DATA", "CSV") +if ERASE_FLASH_ON_START: + flash.clear_flash() + sleep_ms(500) + print("Flash erased.") start_ms = ticks_ms() diff --git a/lib/wsen-hids/examples/low_power_sampling.py b/lib/wsen-hids/examples/low_power_sampling.py index d694e7d3..f3bce16f 100644 --- a/lib/wsen-hids/examples/low_power_sampling.py +++ b/lib/wsen-hids/examples/low_power_sampling.py @@ -1,6 +1,12 @@ -"""Use power_off() between readings to minimize energy consumption. -Read one-shot every 10s, print values, then power down. -Show gc.mem_free() and elapsed time to illustrate battery-friendly usage.""" +"""Low-power sampling with power_off() between readings. + +Minimises energy consumption by powering the sensor down between +one-shot measurements taken every 10 seconds. Displays humidity, +temperature, free RAM and measurement duration to illustrate a +battery-friendly sampling pattern. + +Requires firmware >= v0.1.0 (fix for power_off/power_on cycle, #238). +""" import gc from time import sleep, ticks_diff, ticks_ms @@ -13,20 +19,19 @@ while True: gc.collect() - t0 = ticks_ms() + # Wake the sensor, take a single measurement, then power down sensor.power_on() - humidity, temperature = sensor.read_one_shot() + sensor.power_off() + elapsed_ms = ticks_diff(ticks_ms(), t0) - print("Humidity: {:.2f} %RH".format(humidity)) - print("Temperature: {:.2f} °C".format(temperature)) - print("Free RAM: {} bytes".format(gc.mem_free())) - print("Elapsed: {} ms".format(elapsed_ms)) + print("Humidity: {:.2f} %RH".format(humidity)) + print("Temperature: {:.2f} C".format(temperature)) + print("Free RAM: {} bytes".format(gc.mem_free())) + print("Measurement: {} ms".format(elapsed_ms)) print() - sensor.power_off() - sleep(10)