To create a vibration monitoring and protection system using RAK12033 (6-axis accelerometer + gyroscope module) on the WisBlock platform. The system detects excessive vibrations/oscillations, sends alerts, and (optionally) initiates a safe braking/winding action to protect the equipment and extend its service life.
How does it work?RAK12033 :A 6-axis accelerometer is a sensor that measures two important things:Linear acceleration along three axes (X, Y, Z). This gives you an idea of how an object is moving forward/backward, up/down, and sideways.Angular velocity (rotation) around the same three axes. This shows how fast an object is rotating around its axis.The combination of these two types of measurements gives you a complete three-dimensional picture of any object's movement and vibrations in space.
The logic of protection against increased vibration using a 6-axis accelerometer operates in several stages:Normal state determination (Calibration).Continuous monitoring and data analysis.When the monitored data deviates from the norm, the system recognizes this as an anomaly and sends a message.
Gateway: Setup and ConfigurationTo avoid damage to the gateway, make sure to connect the antenna before turning it on!
This step is thoroughly explained in the guide - IoT Education Kit - Setup the Gateway RAK7268V2 - that can be found on https://www.hackster.io/520073/iot-education-kit-setup-the-gateway-rak7268v2-6b222f
Mounting the WisBlock ComponentsPlace the microprocessor (RAK11300) in the dedicated slot on the motherboard, aligning the pins and holes correctly.
- Press lightly until you hear a click, then secure it using the screws and screwdriver in the kit.
- Carefully connect the LoRa 863-870MHz antenna to its designated location.
Assemble the RAK12033 a 6-axis Accelerometer sensor module by mounting on SENSOR SLOT A of motherboard.
Install Arduino IDE/PlatformIO and support for the RAK11300 board. Install the necessary libraries for the sensors.
Uploading the program code:
#include <Arduino.h>
#include "LoRaWan-Arduino.h"
#include <SPI.h>
#include <Wire.h>
#include "RAK12033-IIM42652.h"
#include "LoRaWan-Arduino.h"
#include <Wire.h>
IIM42652 IMU;
// ============================
// LoRaWAN Settings
// ============================
bool doOTAA = true;
#define LORAWAN_APP_PORT 2
#define LORAWAN_APP_INTERVAL 10000 // Minimalus intervalas tarp LoRa siuntimų ms
DeviceClass_t g_CurrentClass = CLASS_A;
LoRaMacRegion_t g_CurrentRegion = LORAMAC_REGION_EU868;
// OTAA keys (pakeisk savo! Change it to your own)
uint8_t nodeDeviceEUI[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t nodeAppEUI[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t nodeAppKey[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x66,0x61,0x91,0xB9,0xDC,0xDD,0x4A,0x53,0xDD};
// ============================
// LoRa Buffers
// ============================
#define LORAWAN_APP_DATA_BUFF_SIZE 64
static uint8_t m_lora_app_data_buffer[LORAWAN_APP_DATA_BUFF_SIZE];
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0};
// ============================
// LoRa callbacks
// ============================
static void lorawan_has_joined_handler(void) { Serial.println("OTAA Network Joined!"); }
static void lorawan_rx_handler(lmh_app_data_t *app_data) { /* Downlink nereikalingas */ }
static lmh_callback_t g_lora_callbacks = {
BoardGetBatteryLevel,
BoardGetUniqueId,
BoardGetRandomSeed,
lorawan_rx_handler,
lorawan_has_joined_handler,
nullptr,
nullptr,
nullptr,
nullptr
};
// ============================
// Vibration Thresholds
// ============================
const float ACC_THRESHOLD = 0.5; // g
const float GYRO_THRESHOLD = 10.0; // deg/s
float lastAccX = 0, lastAccY = 0, lastAccZ = 0;
float lastGyroX = 0, lastGyroY = 0, lastGyroZ = 0;
// ============================
// Timing
// ============================
unsigned long lastSendTime = 0;
// ============================
// Send LoRa message
// ============================
void send_lora_message(const char* msg) {
if (lmh_join_status_get() != LMH_SET) return;
uint8_t len = strlen(msg);
if(len > LORAWAN_APP_DATA_BUFF_SIZE) len = LORAWAN_APP_DATA_BUFF_SIZE;
memcpy(m_lora_app_data.buffer, msg, len);
m_lora_app_data.port = LORAWAN_APP_PORT;
m_lora_app_data.buffsize = len;
if(lmh_send(&m_lora_app_data, LMH_UNCONFIRMED_MSG) == LMH_SUCCESS){
Serial.print("TTN uplink sent: ");
Serial.println(msg);
} else {
Serial.println("LoRa send failed!");
}
}
// ============================
// Setup
// ============================
void setup() {
Serial.begin(115200);
while(!Serial) delay(100);
Wire.begin();
Serial.println("RAK12033 vibration detection with TTN uplink");
if (!IMU.begin()) {
while (1) {
Serial.println("IIM-42652 is not connected.");
delay(5000);
}
}
// Enable sensors once
IMU.ex_idle();
IMU.accelerometer_enable();
IMU.gyroscope_enable();
IMU.temperature_enable();
// LoRa init
lora_rak11300_init();
if(doOTAA){
lmh_setDevEui(nodeDeviceEUI);
lmh_setAppEui(nodeAppEUI);
lmh_setAppKey(nodeAppKey);
}
lmh_param_t lora_params = {LORAWAN_ADR_ON, DR_0, LORAWAN_PUBLIC_NETWORK, 3, TX_POWER_5, LORAWAN_DUTYCYCLE_OFF};
if(lmh_init(&g_lora_callbacks, lora_params, doOTAA, g_CurrentClass, g_CurrentRegion) != 0){
Serial.println("LMH init failed");
while(1) delay(1000);
}
lmh_join();
}
// ============================
// Loop
// ============================
void loop() {
IIM42652_axis_t accel_data, gyro_data;
float accX, accY, accZ, gyroX, gyroY, gyroZ;
IMU.get_accel_data(&accel_data);
IMU.get_gyro_data(&gyro_data);
accX = (float)accel_data.x / 2048.0;
accY = (float)accel_data.y / 2048.0;
accZ = (float)accel_data.z / 2048.0;
gyroX = (float)gyro_data.x / 16.4;
gyroY = (float)gyro_data.y / 16.4;
gyroZ = (float)gyro_data.z / 16.4;
float accMag = sqrt(accX*accX + accY*accY + accZ*accZ);
float lastAccMag = sqrt(lastAccX*lastAccX + lastAccY*lastAccY + lastAccZ*lastAccZ);
float gyroMag = sqrt(gyroX*gyroX + gyroY*gyroY + gyroZ*gyroZ);
float lastGyroMag = sqrt(lastGyroX*lastGyroX + lastGyroY*lastGyroY + lastGyroZ*lastGyroZ);
bool vibrationDetected = false;
if(abs(accMag - lastAccMag) > ACC_THRESHOLD || abs(gyroMag - lastGyroMag) > GYRO_THRESHOLD){
vibrationDetected = true;
}
if(vibrationDetected){
char msg[64];
snprintf(msg, sizeof(msg), "Vibration detected: %.2f g, Gyro: %.2f deg/s", accMag, gyroMag);
Serial.println(msg);
unsigned long now = millis();
if(now - lastSendTime > LORAWAN_APP_INTERVAL){
send_lora_message(msg);
lastSendTime = now;
}
}
lastAccX = accX; lastAccY = accY; lastAccZ = accZ;
lastGyroX = gyroX; lastGyroY = gyroY; lastGyroZ = gyroZ;
delay(200); // ~5 Hz matavimai, stabilu core
}Write code to initialize and read data from 6-axis Accelerometer sensor.
// TTN V3 payload decoder for vibration sensor
// Input: bytes array from LoRaWAN uplink
// Output: JSON object
function Decoder(bytes, port) {
// bytes = Uint8Array
// port = fPort
// Čia mes dekoduojame tekstinę žinutę (kaip ją siuntėm: "Vibration detected: x.xx g, Gyro: y.yy deg/s")
let payload = String.fromCharCode.apply(null, bytes);
let acc = null;
let gyro = null;
// Regex ištraukti skaičius
const match = payload.match(/Vibration detected:\s*([0-9.]+)\s*g,\s*Gyro:\s*([0-9.]+)\s*deg\/s/i);
if(match){
acc = parseFloat(match[1]);
gyro = parseFloat(match[2]);
}
return {
acc_g: acc,
gyro_dps: gyro,
raw_message: payload
};
}
// Example usage in TTN console
// decoder function: DecoderTwo lines are used to adjust the sensor sensitivity: const float ACC_THRESHOLD = 0.5; // gconst float GYRO_THRESHOLD = 10.0; // deg/s
Here the change is indicated from which it is considered a vibration. After properly adjusting these parameters, the sensor does not respond to normal vibrations.A message is sent to the LoRa app only when the vibrations go beyond the limits, and it is known what changes have occurred.This can be interpreted as whether something simply fell to the side (then the vibration does not repeat) or whether the device is already failing and the vibration will be cyclical.
Check how it works.Checking sensor readings.








Comments