LambLisp 01 Red Fox Alpha
From AI to Actuator
Loading...
Searching...
No Matches
Ultrasonic Sonar (HC-SR04)

Macros

#define LL_SONAR_NO_DEVICE_GUARD   0
#define SONAR_REQUIRE_DEVICE()

Functions

void IRAM_ATTR sonar_echo_isr (void *arg)
Sexpr_t Sonar_mop3_begin (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_start (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_result (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_ping (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_poke (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_us_to_distance (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_set_timeout_us (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_set_min_interval_us (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_set_rest_after_echo_us (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_mop3_defaults (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)
Sexpr_t Sonar_install_mop3 (Lamb &lamb, Sexpr_t sexpr, Sexpr_t env_exec)

Variables

Sonar * sonar = 0

Detailed Description

Copyright 2026 by Frobenius Norm LLC 2026-04-23 00:00:00.

< esp_timer_get_time(): the IRAM-resident clock the ISR needs

LambLisp Ultrasonic Sonar (HC-SR04) builtins.

Macro Definition Documentation

◆ LL_SONAR_NO_DEVICE_GUARD

#define LL_SONAR_NO_DEVICE_GUARD   0

Return #f from a sonar procedure when the device is absent or not yet begun. #f is already these procedures' "no reading", so a caller that handles a timeout handles a missing sensor.

◆ SONAR_REQUIRE_DEVICE

#define SONAR_REQUIRE_DEVICE ( )
Value:
do { if (!sonar || !sonar->begun) return HASHF; } while (0)
Sonar * sonar
Sonar singleton.
Definition ll_xmop3_Sonar.cpp:362

Function Documentation

◆ sonar_echo_isr()

void IRAM_ATTR sonar_echo_isr ( void * arg)

FALLING-edge ISR: ECHO pin went LOW – echo received (or timeout on sensor side).

esp_timer_get_time() AND NOT micros(), AND THE FUNCTION BEING IRAM_ATTR IS WHY THAT MATTERS RATHER THAN WHY IT DOES NOT. An ISR marked IRAM_ATTR is placed in IRAM so it can run while the flash cache is disabled – but the marking covers THIS function only, not what it calls. Arduino's micros() lives in FLASH on this core (esp32-hal-misc.c; measured at 0x40170ba4 against esp_timer_get_time at 0x4008393c), so calling it from here jumped out of IRAM the moment a flash operation had the cache off, and the core panicked:

Guru Meditation Error: Core 1 panic'ed (Cache error).
Cache disabled but cached memory region accessed

The backtrace comes out CORRUPTED, so the panic names neither this file nor the sonar – the only clue is the GPIO number sitting in A2/A4. Reproduced by (sd-mount) with a floating echo pin: esp_vfs_fat_sdmmc_mount disables the cache and the floating input supplies the edge. Any flash write will do it – LittleFS, NVS, OTA – so this is not SD-specific, and a board that has never mounted a filesystem can carry the fault indefinitely without showing it.

micros() is itself just (unsigned long) esp_timer_get_time(), so this is the same number with the same 32-bit wrap, and result()'s arithmetic is unchanged.

THE GENERAL FORM, worth carrying to any other ISR here: IRAM_ATTR places THIS function in IRAM and says nothing about its callees. An ISR is only as interrupt-safe as the deepest thing it calls.

< IRAM-safe; micros() is not

◆ Sonar_mop3_begin()

Sexpr_t Sonar_mop3_begin ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

Initialize the Sonar singleton with trigger and echo pin numbers.

◆ Sonar_mop3_start()

Sexpr_t Sonar_mop3_start ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

Start a ping. On ESP32: non-blocking. On other platforms: blocks on pulseIn.

◆ Sonar_mop3_result()

Sexpr_t Sonar_mop3_result ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

Returns: #f – echo not yet received (still within timeout window) 0 – timed out, no echo; caller should re-arm with Sonar.start integer – elapsed microseconds; caller should convert and re-arm

◆ Sonar_mop3_ping()

Sexpr_t Sonar_mop3_ping ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

Blocking ping: fire trigger, wait for echo, return elapsed microseconds or #f on timeout.

◆ Sonar_mop3_poke()

Sexpr_t Sonar_mop3_poke ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

Blocking ping converted to distance in meters; returns #f on timeout.

◆ Sonar_mop3_us_to_distance()

Sexpr_t Sonar_mop3_us_to_distance ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

Convert elapsed microseconds to distance in meters; optional Celsius temperature arg.

◆ Sonar_mop3_set_timeout_us()

Sexpr_t Sonar_mop3_set_timeout_us ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

(Sonar.timeout-us! <us>) – set the no-echo timeout at runtime; returns the effective (clamped-to-range-floor) value so the caller can confirm it.

◆ Sonar_mop3_set_min_interval_us()

Sexpr_t Sonar_mop3_set_min_interval_us ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

(Sonar.min-interval-us! <us>) – set the HC-SR04 inter-ping settle gap at runtime; returns the effective value. Larger = steadier readings, lower max ping rate.

◆ Sonar_mop3_set_rest_after_echo_us()

Sexpr_t Sonar_mop3_set_rest_after_echo_us ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

(Sonar.rest-after-echo-us! <us>) – set the required REST measured from the ECHO (or from a declared timeout) to the next SEND; returns the effective value. 0 DISABLES it, leaving min-interval-us! the only gate. The default is NOT 0 – this gate is on; the value is SONAR_REST_AFTER_ECHO_DEFAULT_US. Never shortens min-interval-us!: both gates must pass, so this can only make the driver wait longer.

◆ Sonar_mop3_defaults()

Sexpr_t Sonar_mop3_defaults ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

(Sonar.defaults!) – restore every runtime tunable to its compiled default. Returns the three effective values as (timeout-us min-interval-us rest-after-echo-us), so a caller can assert the reset rather than trusting it.

◆ Sonar_install_mop3()

Sexpr_t Sonar_install_mop3 ( Lamb & lamb,
Sexpr_t sexpr,
Sexpr_t env_exec )

Install all Sonar symbols in base environment.

Variable Documentation

◆ sonar

Sonar* sonar = 0

Sonar singleton.