Skip to content

D7S earthquake sensor (RAK12027) integration ​

Status: experimental. The sensor path was hardware-tested on one board (RAK19007 + RAK4631 + RAK13302 + RAK12027 in slot A) in an earlier MeshCore-based build: telemetry was correct, repeater operation was normal, and stats requested while the unit was being shaken answered instantly. This Keymind-based Mesh America build is a port of that code and has not yet been tested on hardware. TX power has not been measured, so the IO2 and booster question below is open.

The Omron D7S is handled like the other environmental sensors: EnvironmentSensorManager finds a device at its I2C address (0x55) during the boot-time scan, polls it, and adds its readings to telemetry. ENV_INCLUDE_D7S=1 is set only in the Mesh America Quake Repeater environment (MeshAmerica_Quake_Repeater_RAK3401, defined in variants/meshamerica_quake/platformio.ini); every other Keymind environment is unchanged. A board adds support by defining ENV_INCLUDE_D7S=1 and handling a shared INT2 pin in src/helpers/sensors/D7SBoard.h.

The Quake Repeater image without a D7S attached carries one sensor-table entry that never matches; the I2C scan, telemetry and pin handling are unchanged. A D7S takes six consecutive sub-channels, so MAX_ACTIVE_SENSORS is 22 instead of 16 when it is compiled in.

Behavior ​

  • Detection happens once at boot: a device that ACKs address 0x55 is treated as a candidate. A sensor that is absent or busy at that moment is not picked up until the next reboot, and whether a D7S ACKs during its power-up calibration is not documented by Omron.
  • Nothing is read for the first 4 s after detection (RAK's library waits about 4 s after power-up; the Omron specification only says the sensor enters normal mode at power-on). Then it is polled every 250 ms, and retried every 5 s after a failed poll. A candidate that never returns a valid state register (0 to 4) is never confirmed, so a foreign device at 0x55 only wastes the six channels, reporting health 0.
  • Neither initialization nor telemetry writes calibration or clears stored history, and the firmware never commands self-test or offset acquisition. Reading the EVENT register is destructive (read-to-clear), so the driver keeps the flags itself.
  • Telemetry requests use cached results and require environmental-telemetry permission. Readings older than 2 s are reported as unavailable; the event-flag channel is the exception (see below).
  • The driver is portable (D7S.h/.cpp). D7SWireTransport.h adapts it to an Arduino TwoWire bus; reads use a repeated start (endTransmission(false)), as in the vendor library, but the on-wire result on the nRF52 core is unconfirmed without a bus capture.
  • Interrupts are not used by the firmware. The driver has a notify() entry for them, but no variant wires INT1/INT2; polling is the only path. The sensor latches EVENT flags until they are read, so polling at 250 ms loses nothing while polls succeed. If an EVENT read fails after the address ACK the flags may already have been cleared, which is what bit 128 below reports.

Telemetry ​

The D7S takes six consecutive channels, allocated after the sensors ahead of it, only when a candidate is present. Offsets are relative to its first channel.

Offset / LPP typeLabelMeaning
0 / digital inputSensor health1 = recent successful read; 0 = unavailable
0 / genericSensor state0 standby; 1 normal mode not in standby (primarily earthquake processing); 2 installation; 3 offset acquisition; 4 self-test. Omitted when unavailable.
1 / genericLive SIRaw / 10 = cm/s (unit inferred from the stored register). Only while fresh and processing.
2 / genericLive PGARaw counts; the live scale is unresolved (see the measurement contract).
3 / genericRecorded eventsPresent once the sensor has answered or a failed read may have lost flags. Flags retained since the first successful poll: 1 significant shaking (the sensor's shutoff signal), 2 tilt, 4 self-test error, 8 baseline error; a bit mask, not a count. Bit 128 means an EVENT read failed and may have discarded flags the firmware never saw. Nothing clears these in firmware, so they last until reboot. Not freshness-gated: check the health channel.
4 / genericStored SILatest stored record, raw / 10 = cm/s. May predate boot; cleared memory reads as zero.
5 / genericStored PGALatest stored record, raw / 10 = gal (raw / 9806.65 = g). May predate boot.

Stored values are fetched on the first successful standby poll and again after a non-standby state, a new shaking or tilt flag, or any failed poll. They are history, not a new-event notification: there is no age, event ID or timestamp. Offset 0 carries two records on one channel; a parser keyed by channel alone may keep only one. Apps need an agreed way to identify these channels; none exists yet. See measurement definitions. Do not label these values Richter magnitude, an epicenter or building damage.

Hardware notes (RAK19007 + RAK4631/RAK3401 + RAK13302 + RAK12027) ​

Slot A was recommended by RAK's WisMap pin mapper (a screenshot, not re-fetchable): RAK12027 at 0x55 on I2C1 (SDA P0.13, SCL P0.14), INT1 on IO1, INT2 on IO2 (P1.02, Arduino pin 34). RAK's RAK12027 product page lists slots C-F only, and the RAK13302 already uses IO3-IO6, so slot A is the only free one on this assembly. The driver does not detect the slot.

The sensor's supply rail is unresolved. WisMap and the module pin table show VDD on the plain 3V3 rail; RAK's RAK12027 page says the module is powered from 3V3_S, controlled via IO2. IO2 is the base board's EN for 3V3_S, and the RAK19007 page says IO2 cannot be used as a sensor interrupt when 3V3_S is used. INT2 is an open-drain output.

On a RAK3401 the stock firmware drives IO2 high. That would fight INT2, so once a D7S is confirmed (first valid state read, never on the scan ACK alone) d7sBoardOnConfirmed() in src/helpers/sensors/D7SBoard.h releases IO2 to an input with the internal pull-up; other builds, and images with no D7S attached, keep IO2 driven high. This applies to a D7S in any slot. It is a deliberate exception to the rule used elsewhere in this code base that IO2 (the shared 3V3_S rail enable) is never released. Low-voltage shutdown still drives IO2 low. Nothing in this repository shows what happens while INT2 is asserted (power-up offset acquisition, earthquake processing): the enable can be pulled low, which may cut the sensor's own supply if it is on 3V3_S, and may affect the RAK13302 booster. Whether IO2 gates the booster is also unresolved: the variant comment inherited from the base target says it does, WisMap shows the RAK13302 using no IO2 or 3V3_S, and RAK's RAK13302 datasheet lists pin 6 as 3V3_S without stating its function. An earlier diagnostic build ran with IO2 as a plain input and INT2 active and the sensor communicated, which is indirect evidence only. Measure TX power with the sensor fitted at idle and while INT2 is asserted, and the sensor's supply voltage during offset acquisition, before treating either as verified.

Limits ​

  • Wire on the nRF52 core has no timeout (unbounded waits, and the D7S has clock stretching enabled), so a device holding the I2C bus can stall the main loop, as with every other sensor on that bus. A bounded Wire in the core fork would fix this for all sensors and should be proposed separately.
  • No channel alerts, saved alert destination, app changes, GRP_DATA schema or automatic channel labelling exist yet.
  • Detection is boot-only; stored records have no provenance; the live PGA scale is unresolved.

Hardware check ​

  1. Record existing radio settings and confirm the companion matches them.
  2. Flash the Mesh America Quake Repeater build and confirm login, stats and telemetry at rest: after about 5 s the health channel should read 1 and the state 0.
  3. Move the enclosure: the live channels should appear while the state is 1; leave it still for over two minutes, then check that the stored channels show the record.
  4. Measure TX power against the stock build, and the sensor's supply voltage, as described above.

Files relative to Keymind Cascade ​

Added: D7S.h/.cpp, D7SWireTransport.h, D7SBoard.h, SeismicAlert.h/.cpp, ClockFloor.h/.cpp (in src/helpers/sensors/), examples/simple_repeater/MyMeshQuake.cpp (see earthquake-alerts.md), variants/meshamerica_quake/platformio.ini, the tests test/test_d7s*, and these documents. Changed (small, to keep merging Keymind updates easy): the D7S block, table entry and loop hook in EnvironmentSensorManager.cpp/.h, the shutdown pinMode in variants/rak3401/RAK3401Board.cpp, the D7S.cpp and SeismicAlert.cpp entries in the native test filter in platformio.ini, a SeismicReading accessor in SensorManager.h, the version line of the owner-info response in MyMesh.cpp, and ENV_INCLUDE_D7S-guarded hooks in examples/simple_repeater/MyMesh.cpp/.h (a group-text sender split out of sendRepeatersFloodText, the loop call and the CLI branch).

Brought to you by Mesh America. When the internet goes down, the mesh stays up.