Repository navigation
Android SBeacon Framework Calibration
Calibration ensures accurate driving behavior detection by establishing a baseline reference for the beacon's accelerometer. This is a required step before using driving behavior features.
The SBeacon's accelerometer measures G-forces in three axes (X, Y, Z) following the ISO8855 vehicle axis system. Without calibration:
- Gravity may be incorrectly attributed to movement
- Event detection thresholds will be inaccurate
- False positives/negatives will occur
Calibration fundamentally changes how incident thresholds are calculated:
Uncalibrated Mode:
- Threshold compared against: √(x² + y² + z²)
- Includes the Z-axis gravity component (~1g when stationary)
- Results in inaccurate detection as gravity interferes with motion detection
Calibrated Mode:
- Threshold compared against: √(x² + y²)
- Excludes the Z-axis gravity component
- Only horizontal plane motion (actual vehicle movement) is measured
- Significantly more accurate event detection
Calibration establishes:
- The orientation of the beacon in the vehicle
- The baseline gravity vector (typically Z-axis = 1g when stationary)
- Proper axis mapping for driving events
- A rotation matrix for correct force vector interpretation
Before calibrating:
- Beacon must be paired - See Beacon Pairing
- Beacon must be connected - Ensure active BLE connection
- Vehicle must be stationary - Park on a level surface (critical for accurate calibration)
- Beacon must be properly mounted - Install in final position following mounting guidelines below
The SBeacon MUST be mounted vertically for proper calibration:
Standard Mounting (Button Facing Up):
- Mount beacon vertically with button facing up
- Adhesive pad should face toward the vehicle front
- This is the default orientation requiring no post-processing
Logo Beacon Mounting (Button Facing Down):
- For beacons with logo markings, mount with button facing down (logo upright)
- Adhesive pad should face toward the vehicle front
- Important: This orientation requires X/Y axis inversion in post-processing
- Consult with support if using logo beacons
Why Vertical Mounting Matters:
- Ensures Z-axis aligns with gravity (perpendicular to ground)
- Allows calibration to establish proper baseline (Z ≈ 1g when stationary)
- Enables accurate horizontal plane motion detection (X/Y axes)
val bleManager = BLEManager.retrieveInstance(context)
// Request calibration state
bleManager.requestAccelerometerConfig(beaconMac)
// Handle response via EventsReceiver
private val eventsReceiver = object : IBFHelper.EventsReceiver() {
override fun onUpdateBeaconCalibrationStateReceived(mac: String, isCalibrated: Boolean) {
if (isCalibrated) {
Log.d("Calibration", "Beacon is already calibrated")
} else {
Log.d("Calibration", "Beacon needs calibration")
}
}
}
// Register in onResume
override fun onResume() {
super.onResume()
IBFHelper.registerEventsReceiver(requireContext(), eventsReceiver)
}You can also check the beacon's local state:
lifecycleScope.launch {
val beacon = bleManager.getBeacon(beaconMac)
val isCalibrated = beacon?.isCalibrated ?: false
Log.d("Calibration", "Local state: calibrated = $isCalibrated")
}// Ensure vehicle is stationary and beacon is in final position
bleManager.requestAccelerometerCalibration(beaconMac)The calibration process:
- Enables the rotation bit (internal prerequisite)
- Initiates auto-calibration (command 10 11)
- Beacon measures baseline accelerometer values
- Calculates rotation angles
- Stores calibration data and rotation angles in flash memory
private val eventsReceiver = object : IBFHelper.EventsReceiver() {
override fun onAutoCalibrationReceived(mac: String) {
Log.d("Calibration", "Calibration successful for $mac")
// Beacon is now ready for driving behavior detection
// Calibration data is stored in beacon's flash memory
}
}After calibration completes, you can verify proper calibration by checking accelerometer readings when the vehicle is stationary:
Expected Values (Vehicle Stationary, Level Surface):
- X-axis: ≈ 0g (lateral - left/right motion)
- Y-axis: ≈ 0g (longitudinal - forward/backward motion)
- Z-axis: ≈ 1g (vertical - gravity)
If values significantly deviate from this (e.g., Z-axis reads 0.5g or X/Y axes show constant non-zero values), the beacon may not be mounted vertically or calibration failed. In this case:
- Verify beacon is mounted vertically (not tilted)
- Check vehicle is on level surface
- Recalibrate
If the beacon position changes or calibration seems incorrect:
// This is an internal method - typically not exposed via BLEManager
// Contact support if recalibration is needed after initial setupAfter reset, the beacon's isCalibrated flag will be set to false, and you must perform calibration again.
| State | Description |
|---|---|
| Not Calibrated |
isCalibrated = false - Calibration required |
| Calibrated |
isCalibrated = true - Ready for use |
The calibration state is:
- Stored in the beacon's flash memory (persists across power cycles)
- Cached locally in the app's database
- Updated automatically when calibration completes or resets
The SBeacon accelerometer axes can be configured to align with the ISO8855:2011 Vehicle Axis System standard. This standard defines X (lateral), Y (longitudinal), and Z (vertical) axes relative to the vehicle body frame.
When properly calibrated and mounted vertically:
- Z-axis aligns with gravity (~1g when stationary)
- X and Y axes measure horizontal plane motion
- Horizontal plane forces √(x² + y²) are isolated from gravitational effects
Note: The SBeacon default axes align with Android's Automotive Sensor implementation. A configuration bit can enable ISO8855:2011 alignment if required.
During calibration, the beacon:
- Enables the rotation bit (Bit 4 in accelerometer configuration)
- Triggers auto-calibration (command 10 11)
- Calculates rotation angles (alpha, beta, gamma) for X, Y, Z axes
- Persists the rotation angles and calibration flag to flash memory
When rotation is enabled, all accelerometer values are rotated by the configured angles before being used for event detection.
Button-Down Mounting (Logo Beacons):
- For beacons with logos, button faces down (logo upright)
- X and Y axis values will be inverted after calibration
- Correction must be applied in post-processing: x_corrected = -x, y_corrected = -y, z_corrected = z
- This corresponds to a rotation matrix with -1 multipliers on X and Y axes
- Mount the beacon vertically - Button facing up (or down for logo beacons), adhesive toward vehicle front
- Ensure firm mounting - Beacon must not wobble or move; use proper adhesive surface
- Park on level ground - Vehicle must be on a completely level surface, not on a slope
- Stop the engine - Minimize vibration during calibration
- Verify BLE connection - Beacon must be connected before starting calibration
Critical Requirement: The beacon must be mounted to the windshield in a vertical orientation (button up/down) for proper calibration.
Mounting requirements:
- Vertical orientation - Beacon must be perpendicular to ground (not tilted or horizontal)
- Windshield mounting - Use adhesive to attach to windshield
- Button orientation - Button facing up (standard) or down (logo beacons)
- Adhesive pad direction - Should face toward vehicle front
- Stable surface - Ensure beacon is firmly attached and will not wobble or move
Important: Any location requiring horizontal mounting is not suitable. The beacon requires a vertical mounting surface on the windshield for proper accelerometer calibration.
- Verify with a test drive - Confirm events are detected correctly
- Check threshold sensitivity - Adjust if too many/few events
- Recalibrate if moved - Any position change requires recalibration
Problem: requestAccelerometerCalibration doesn't respond
Solutions:
- Verify beacon is connected (
isBeaconConnected(beacon)) - Check Bluetooth permissions are granted
- Ensure beacon firmware is up to date
- Try disconnecting and reconnecting
Problem: No completion event received
Solutions:
- Ensure vehicle is completely stationary
- Check for excessive vibration (engine running, nearby traffic)
- Wait longer (calibration can take several seconds)
- Verify event subscription is active before starting calibration
Problem: False positives or missed events
Solutions:
- Verify vertical mounting - Beacon must be mounted vertically (button up/down), not horizontally
- Check accelerometer readings when stationary (X≈0, Y≈0, Z≈1)
- Recalibrate with vehicle on level surface
- Check if beacon has moved since calibration
- Verify beacon is firmly mounted (no wobble)
- Adjust detection thresholds (see Driving Behavior)
Problem: Z-axis doesn't read ~1g when stationary, or X/Y axes show constant non-zero values
Solutions:
- Check mounting orientation - Beacon likely not mounted vertically
- Verify vehicle is on level surface during calibration
- Remount beacon in vertical orientation (button up/down)
- Recalibrate after correcting mounting position
Problem: State not updating
Solutions:
- Request calibration state explicitly:
requestAccelerometerConfig(beaconMac) - Check local database sync
- Verify completion event was received
class CalibrationFragment : Fragment() {
private val bleManager by lazy { BLEManager.retrieveInstance(requireContext()) }
private var beaconMac: String? = null
sealed class CalibrationState {
object Unknown : CalibrationState()
object NotCalibrated : CalibrationState()
object InProgress : CalibrationState()
object Calibrated : CalibrationState()
}
private var calibrationState: CalibrationState = CalibrationState.Unknown
set(value) {
field = value
updateUI(value)
}
private val eventsReceiver = object : IBFHelper.EventsReceiver() {
override fun onUpdateBeaconCalibrationStateReceived(
mac: String,
isCalibrated: Boolean
) {
if (mac == beaconMac) {
calibrationState = if (isCalibrated) {
CalibrationState.Calibrated
} else {
CalibrationState.NotCalibrated
}
}
}
override fun onAutoCalibrationReceived(mac: String) {
if (mac == beaconMac) {
calibrationState = CalibrationState.Calibrated
}
}
}
override fun onResume() {
super.onResume()
IBFHelper.registerEventsReceiver(requireContext(), eventsReceiver)
checkCalibrationStatus()
}
override fun onPause() {
super.onPause()
IBFHelper.unregisterEventsReceiver(requireContext(), eventsReceiver)
}
fun checkCalibrationStatus() {
calibrationState = CalibrationState.Unknown
beaconMac?.let { bleManager.requestAccelerometerConfig(it) }
}
fun startCalibration() {
calibrationState = CalibrationState.InProgress
beaconMac?.let { bleManager.requestAccelerometerCalibration(it) }
}
private fun updateUI(state: CalibrationState) {
// Update your UI based on state
}
}@Composable
fun CalibrationScreen(
calibrationManager: CalibrationManager,
beaconMac: String
) {
val state by calibrationManager.calibrationState.collectAsState()
Column(modifier = Modifier.padding(16.dp)) {
Text("Calibration Status", style = MaterialTheme.typography.h6)
when (state) {
is CalibrationState.Unknown -> {
Text("Checking calibration status...")
LaunchedEffect(beaconMac) {
calibrationManager.checkCalibrationStatus(beaconMac)
}
}
is CalibrationState.NotCalibrated -> {
Text("Beacon needs calibration")
Text("1. Park on level ground")
Text("2. Turn off engine")
Text("3. Ensure beacon is mounted")
Button(onClick = { calibrationManager.startCalibration(beaconMac) }) {
Text("Start Calibration")
}
}
is CalibrationState.InProgress -> {
CircularProgressIndicator()
Text("Calibrating... Keep vehicle stationary")
}
is CalibrationState.Calibrated -> {
Icon(Icons.Default.Check, "Calibrated", tint = Color.Green)
Text("Beacon is calibrated and ready")
}
is CalibrationState.Error -> {
Text("Error: ${(state as CalibrationState.Error).message}", color = Color.Red)
}
}
}
}- Beacon Pairing - Pair beacon before calibration
- Driving Behavior - Configure after calibration
Consolidated SDK
SmartDrive
PortalApiBase
PortalApiClient
Wellness
SBeacon
- Overview
- Installation
- Initialization
- Beacon Scanning
- Beacon Pairing
- Trip Management
- Driving Behavior
- Calibration
- Event Handling
- Data Models
- API Reference
Consolidated SPM
SDApiManager
CCFrameworkOpen
SmartDrive
SBeacon