How To Build a Seismic Sensor with WisBlock

KHM-024-00.png

Earthquakes can be dangerous and are often unpredictable. One of the mitigation efforts is to deploy seismic stations around the globe, which aid in measuring the movement of the ground.

With this, Omron created an affordable sensor - the D7S module - that can detect earthquakes and measure their intensity as SI values. The SI values have a high correlation with the seismic intensity scale, indicating the magnitude of an earthquake.

While this product cannot predict earthquakes, it is a good solution to send warnings and protect sensitive machinery in case an earthquake occurs. Besides measuring the strength, it generates a warning signal if the SI level is higher than 5 that can be used to shut down machinery. It also detects if the horizontal position of the sensor changes, which points towards a collapse of the structure where the sensor was deployed.

Check out the following Omrons documentation for the D7S module:

Using the small-sized RAK12027 Seismic Sensor together with the WisBlock Core and WisBlock Base modules makes it very easy to build up the earthquake warning system.

This example can be used as a starting point in building a low-power consumption seismic alarm system. It can be powered by a battery and solar panel. The consumption in sleep mode is ~90 uA.

The code is completely interrupt-based to keep the MCU as much as possible in sleep mode to save battery. The collected data of an earthquake is sent over LoRaWAN, but it can also be used with LoRa P2P. It sends data packets after the D7S has finished its data processing with the information on the SI level, PGA, shutdown alert, and collapse alert signal.

RAK Products Used

This project uses the following RAK products:

  • RAK19007 Base Board
  • RAK12027 Seismic Sensor
  • RAK1901 Temperature and Humidity Sensor (optional)
    • In case the firmware is built with the RAK-nRF52 Arduino BSP, it uses the RAK4631 Core Module.
    • In case the RAK RUI3 API is used for the firmware, it uses the RAK4631-R Core Module.

Assembly

Place the WisBlock Core and WisBlock Sensor module in the following slots of the RAK19007 Base Board (Core slot and Sensor slot D, respectively):

KHM-024-01.gif

Make sure to fix the modules with the screws coming with the WisBlock modules. In case of an intense earthquake, they might fall off the Base Board if not secured with the screws.

For the enclosure, the Unify Enclosure RAKBox-UO100x75x38 is used.

Assemble the WisBlock Base board on the mounting plate.

KHM-024-02.jpg

Depending on the size of the battery used, there are two mounting options:

    • For a small and thin battery (lwh: 55 x 30 x 6 mm), place the battery below the mounting plate.
      KHM-024-03.jpg
    • Then fix the mounting plate inside the enclosure.
      KHM-024-04.jpg
  • For a large battery, use stand-offs and a battery carrier like the one from the Awesome WisBlock repo to fix the battery above the WisBlock.
    KHM-024-05.jpg
    KHM-024-06.jpg

How It Works

Both the RUI3 and the Arduino code are based on interrupts and timers. After joining the LoRaWAN network, the MCU goes into sleep mode until it wakes up from the following:

  • From an interrupt coming from the D7S sensor.
  • From a timer to send a frequent "I am Alive" message.

On wake up, the code then checks for the wake up reason and handles the situation. There are four (4) different interrupt events:

  • (1) Earthquake start detected (INT2 falling edge of the D7S)
  • (2) Earthquake analysis finished (INT2 raising edge of the D7S)
  • (3) Shutoff alert (INT1 falling edge of the D7S)
  • (4) Collapse alert (INT1 falling edge of the D7S)

(1) just sets a flag as a reminder that an earthquake was detected. (2) reads out the detected SI and PGA level and sends a packet to the LoRaWAN server. (3) and (4) set a flag whether a shutoff alert or collapse alert was set.

After sending the data packet in (2), a timer will start sending a second packet with the alert flags cleared.

The frequent send timer is just sending a small packet to signal the LoRaWAN server that the sensor is still alive. This packet contains the battery level and, if assembled, the temperature and humidity values measured with the RAK1901.

Libraries Used

Both the Arduino and the RUI3 code use the D7S library provided by Alessandro Pasqualini. I couldn't find the library in the Arduino Library Manager, so you have to download the repo as a .zip file and install it manually.

For the encoding of the data packets, the CayenneLPP library is used. For the RAK1901 sensor, the SparkFun SHTC3 Humidity and Temperature Sensor Library is used. These two libraries can be installed with the Arduino Library Manager.

The Arduino version uses in addition the WisBlock-API, which can be installed with the Arduino Library Manager as well.

Source Code

Seismic Sensor Code for RAK4631 Using the RAK-nRF52 BSP for Arduino

The Arduino code is based on the WisBlock-API, an event-driven framework that handles all communication tasks in the background and just waits for a timer or external interrupt to wake up. The provided code is for PlatformIO, but can easily be changed to work in the Arduino IDE.

Depending on the Sensor Slot used, the D7S interrupts INT1 and INT2 and must be assigned to the correct GPIOs. This can be done in the platformio.ini files with the build_flags option:

build_flags =
  -DRAK12027_SLOT=2 ; 0 = Slot A, 1 = Slot B, 2 = Slot C, 3 = Slot D, 4 = Slot E, 5 = Slot F

If using the Arduino IDE, the correct assignment has to be done in the RAK12027_seismic.cpp file.

The Arduino-based firmware has an AT command interface. The available AT commands can be found in the AT Command Manual.

The complete source code is located in the PlatformIO source code folder of the repository.

Seismic Sensor Code for RAK4631-R and RAK3172 Using the RAK RUI3 API

The RUI3-based code is working on the RAK4631-R and RAK3172 modules without any change in the code. The assignment of the D7S interrupts INT1 and INT2 and must be assigned in the RAK12027_seismic.cpp file.

The complete source code is located in the RUI3 source code folder of the repository.

RAK12027 Seismic Sensor Setup

The functions to set up the sensor and handle the sensor interrupts are nearly the same for Arduino and RUI3. The main difference is how the interrupt handlers wake up the MCU to check the source of the interrupts.

In the `init_rak120271() function, the sensor is initialized and calibrated. The calibration is necessary as the sensor will determine its horizontal position. It is required for both earthquake detection and collapse alert. The function assigns as well the interrupt handlers for the two interrupt sources from the D7S sensor.

For Arduino, the two interrupt handlers wake up the loop by releasing a semaphore with the api_wake_loop() call. They set as well the reason for the wake up so that it can be handled in the application.

/**
 * @brief Callback for INT 1
 * Wakes up application with signal SEISMIC_ALERT
 * Activated on Collapse and Shutoff signals
 *
 */
void d7s_int1_handler(void)
{
  api_wake_loop(STATUS | SEISMIC_ALERT);
}

/**
 * @brief Callback for INT 2
 * Wakes up application with signal SEISMIC_EVENT
 * Activated on Earthquake start and end
 *
 */
void d7s_int2_handler(void)
{
  if (digitalRead(INT2_PIN) == LOW)
  {
    digitalWrite(LED_BLUE, HIGH);
  }
  else
  {
    digitalWrite(LED_BLUE, LOW);
  }
  api_wake_loop(STATUS | SEISMIC_EVENT);
}

Since RUI3 doesn't support semaphores and tasks, the interrupt handlers call directly the sensor_handler() function.

/**
 * @brief Callback for INT 1
 * Wakes up application with signal SEISMIC_ALERT
 * Activated on Collapse and Shutoff signals
 *
 */
void d7s_int1_handler(void)
{
  g_task_event_type = SEISMIC_ALERT;
  sensor_handler(NULL);
}

/**
 * @brief Callback for INT 2
 * Wakes up application with signal SEISMIC_EVENT
 * Activated on Earthquake start and end
 *
 */
void d7s_int2_handler(void)
{
  if (digitalRead(INT2_PIN) == LOW)
  {
    digitalWrite(LED_BLUE, HIGH);
  }
  else
  {
    digitalWrite(LED_BLUE, LOW);
  }
  g_task_event_type = SEISMIC_EVENT;
  sensor_handler(NULL);
}

Data Packet Format

The data packet is encoded in an extended CayenneLPP format based on the CayenneLPP format provided by ElectronicCats. This format is supported by most LoRaWAN network servers and integrations. But as an extended version is used here, it will need a custom payload decoder. A set of payload decoders for different LoRaWAN network servers and integrations are in the decoders folder of the code repository.

The channel IDs used for the different values are:

Channel Name Channel ID Type Value
LPP_CHANNEL_BATT 1 Voltage Battery voltage in V
LPP_CHANNEL_HUMID 2 Relative Humidity RAK1901 Humidity in %RH
LPP_CHANNEL_TEMP 3 Temperature RAK1901 Temperature in °C
LPP_CHANNEL_EQ_EVENT 43 Presence RAK12027 Earthquake active, a boolean value, true if an earthquake is active
LPP_CHANNEL_EQ_SI 44 Analog RAK12027 Detected SI value, analog value 1/10th in m/s
LPP_CHANNEL_EQ_PGA 45 Analog RAK12027 Detected PGA value, analog 10 * value in m/s^2
LPP_CHANNEL_EQ_SHUTOFF 46 Presence RAK12027 Shutoff alert, a boolean value, true if an alert is raised
LPP_CHANNEL_EQ_COLLAPSE 47 Presence RAK12027 Collapse alert, a boolean value, true if an alert is raised

To get higher precision, the SI and PGA values are multiplied by 10 before sending them. The Cayenne LPP format supports only 0.01 precision. The values must be divided by 10 to get the real values.

The packet sent out is displayed as hex values, which look like this:

**0x2b 0x66 0x01 0x2c 0x02 0x00 0xab 0x2d 0x02 0x19 0x28 0x2e 0x66 0x01 0x2f 0x66 0x00 0x01 0x74 0x01 0x9b 0x02 0x68 0x77 0x03 0x67 0x01 0x81**

Bytes Meaning Value in Hex Value
1 Channel ID 43 for EQ event 0x2b  
2 Channel type for presence 0x66  
3 Status of presence 0 = off, 1 = on 0x01 ON
4 Channel ID 44 for SI value 0x2c  
5 Channel type for analog value 0x02  
6, 7 SI value 0x00 0xab 1.71 = 0.171 m/s
8 Channel ID 44 for PGA value 0x2d  
9 Channel type for analog value 0x02  
10, 11 PGA value 0x19 0x28 64.4 = 6.44 m/s^2
12 Channel ID 46 for Shutoff event 0x2e  
13 Channel type for presence 0x66  
14 Status of presence 0 = off, 1 = on 0x01 ON
15 Channel ID 47 for Collapse event 0x2f  
16 Channel type for presence 0x66  
17 Status of presence 0 = off, 1 = on 0x00 OFF
18 Channel ID 1 for battery voltage 0x01  
19 Channel type for voltage 0x74  
20, 21 Voltage level 0x01 0x9b 4.11 V
22 Channel ID 2 for humidity 0x02  
23 Channel type for analog value 0x68  
24 Humidity value 0x77 59.5 %RH
25 Channel ID 3 for temperature 0x03  
26 Channel type for temperature 0x67  
27, 28 temperature value 0x01 0x81 38.5° C

Example for Visualization and Alert Message

As a simple example to visualize the earthquake data and send an alert, I created a device in Datacake. Datacake is an easy-to-use Low Code IoT platform. In my Datacake account, I set up the device with the matching payload decoder, visualization, and creation of an email alert.

Datacake Payload Decoder

In the device configuration, the Datacake decoder from the decoders folder is used.

Datacake Fields

As the SI and PGA values are sent as 10 times the value, besides the data fields, a formula feed is required to transform the received values into the real values.

Field Name Identifier Type
Earthquake warning PRESENCE_43 Boolean
Earthquake SI value 100 ANALOG_IN_44 Float
Earthquake PGA 100 ANALOG_IN_45 Float
Battery VOLTAGE_1 Float
Humidity HUMIDITY_2 Float
Temperature TEMPERATURE_3 Float
Shutoff alert PRESENCE_46 Boolean
Collapse alert PRESENCE_47 Boolean
Earthquake SI value EARTHQUAKE_SI_VALUE Float
Earthquake PGA EARTHQUAKE_PGA Float
Lora Datarate LORA_DATARATE String
Lora RSSI LORA_RSSI Integer
Lora SNR LORA_SNR Integer

Datacake Rule

To send a warning email when an earthquake occurs, a Datacake rule is used to send the email. The rule is triggered by the Earthquake warning field.

KHM-024-07.png

Datacake Visualization

In the dashboard, you can show the current status and the latest SI and PGA levels.

KHM-024-08.png

bernd-giesecke.png

Bernd Giesecke

Electronics Engineer, 23 years of experience in industrial and automotive HW and SW R&D. Supporting Arduino open-source community since 2014.

Updated