diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 76d111f11ef3d..77a7637ed4025 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -181,19 +181,22 @@ Miscellaneous functions varies by hardware (so use substring of a full value if you expect a short ID). In some MicroPython ports, ID corresponds to the network MAC address. -.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000, /) +.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000, wait_opposite=false, /) Time a pulse on the given *pin*, and return the duration of the pulse in microseconds. The *pulse_level* argument should be 0 to time a low pulse or 1 to time a high pulse. - If the current input value of the pin is different to *pulse_level*, - the function first (*) waits until the pin input becomes equal to *pulse_level*, - then (**) times the duration that the pin is equal to *pulse_level*. + If *wait_opposite* is true, if the pin is initially equal to *pulse_level* then first + waits until the pin input becomes different from *pulse_level* (***). + Then if the current input value of the pin is different to *pulse_level*, + the function first (**) waits until the pin input becomes equal to *pulse_level*, + then (*) times the duration that the pin is equal to *pulse_level*. If the pin is already equal to *pulse_level* then timing starts straight away. + The function returns -3 if there was timeout waiting for condition marked (***) above. The function will return -2 if there was timeout waiting for condition marked - (*) above, and -1 if there was timeout during the main measurement, marked (**) + (**) above, and -1 if there was timeout during the main measurement, marked (*) above. The timeout is the same for both cases and given by *timeout_us* (which is in microseconds). diff --git a/drivers/dht/dht.c b/drivers/dht/dht.c index e6b71542dabc9..47d114fed784e 100644 --- a/drivers/dht/dht.c +++ b/drivers/dht/dht.c @@ -71,8 +71,9 @@ static mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { } } + #define WAIT_OPPOSITE false // time pulse, should be 80us - ticks = machine_time_pulse_us(pin, 1, 150); + ticks = machine_time_pulse_us(pin, 1, 150, WAIT_OPPOSITE); if ((mp_int_t)ticks < 0) { goto timeout; } @@ -80,7 +81,7 @@ static mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { // time 40 pulses for data (either 26us or 70us) uint8_t *buf = bufinfo.buf; for (int i = 0; i < 40; ++i) { - ticks = machine_time_pulse_us(pin, 1, 100); + ticks = machine_time_pulse_us(pin, 1, 100, WAIT_OPPOSITE); if ((mp_int_t)ticks < 0) { goto timeout; } diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c index 85dba86d9b5ad..60edc3ce9e4c4 100644 --- a/extmod/machine_pulse.c +++ b/extmod/machine_pulse.c @@ -30,8 +30,14 @@ #if MICROPY_PY_MACHINE_PULSE -MP_WEAK mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { +MP_WEAK mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us, bool wait_opposite) { mp_uint_t start = mp_hal_ticks_us(); + while (wait_opposite && (mp_hal_pin_read(pin) == pulse_level)) { + if ((uint64_t)(mp_hal_ticks_us() - start) >= (uint64_t)timeout_us) { + return (mp_uint_t)-3; + } + } + start = mp_hal_ticks_us(); while (mp_hal_pin_read(pin) != pulse_level) { if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) { return (mp_uint_t)-2; @@ -56,10 +62,14 @@ static mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) { if (n_args > 2) { timeout_us = mp_obj_get_int(args[2]); } - mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us); - // May return -1 or -2 in case of timeout + bool wait_opposite = false; + if (n_args > 3) { + wait_opposite = mp_obj_is_true(args[3]); + } + mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us, wait_opposite); + // May return -1 or -2 or -3 in case of timeout return mp_obj_new_int(us); } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 4, machine_time_pulse_us_); #endif diff --git a/extmod/modmachine.h b/extmod/modmachine.h index 7c16ed302ee2f..c3a1e61da4d4d 100644 --- a/extmod/modmachine.h +++ b/extmod/modmachine.h @@ -244,7 +244,7 @@ uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align); NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args); void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len); -mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us); +mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us, bool wait_opposite); MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj); MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj); diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index 23ccf8cebfb0d..b994bf813382e 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -329,7 +329,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); // Custom version of this function that feeds system WDT if necessary -mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { +mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us, bool wait_opposite) { int nchanges = 2; uint32_t start = system_get_time(); // in microseconds for (;;) { diff --git a/tests/extmod_hardware/machine_pwm.py b/tests/extmod_hardware/machine_pwm.py index e27da32548659..4010dbeccaca0 100644 --- a/tests/extmod_hardware/machine_pwm.py +++ b/tests/extmod_hardware/machine_pwm.py @@ -72,14 +72,11 @@ def _test_freq_duty(self, pulse_in, pwm, freq, duty_u16): expected_us = (expected_low_us, expected_high_us) timeout = 2 * expected_total_us - # Wait for output to settle. - time_pulse_us(pulse_in, 0, timeout) - time_pulse_us(pulse_in, 1, timeout) - if duty_u16 == 0 or duty_u16 == 65535: # Expect a constant output level. no_pulse = ( - time_pulse_us(pulse_in, 0, timeout) < 0 and time_pulse_us(pulse_in, 1, timeout) < 0 + time_pulse_us(pulse_in, 0, timeout, True) < 0 + and time_pulse_us(pulse_in, 1, timeout, True) < 0 ) self.assertTrue(no_pulse) if expected_high_us == 0: @@ -93,9 +90,8 @@ def _test_freq_duty(self, pulse_in, pwm, freq, duty_u16): n_averaging = 10 for level in (0, 1): t = 0 - time_pulse_us(pulse_in, level, timeout) for _ in range(n_averaging): - t += time_pulse_us(pulse_in, level, timeout) + t += time_pulse_us(pulse_in, level, timeout, True) t //= n_averaging expected = expected_us[level] print(" level={} timing_er={}".format(level, abs(t - expected)), end="")
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: