A Garmin Connect IQ Data Field app that calculates and records virtual speed based on power and cadence data from an indoor bike trainer. This app is particularly useful for indoor cycling sessions where GPS speed is not available.
- Physics-Based Speed Calculation: Uses power and cadence to simulate realistic cycling speed
- Advanced Physics Model: Includes air resistance, rolling resistance, gradient effects, and bike/rider characteristics
- Automatic Profile Sync: Pulls rider weight and height from Garmin Connect profile
- Multiple Bike Profiles: Road, TT (Time Trial), and MTB (Mountain Bike) with different aerodynamic characteristics
- GPS-Aware: Automatically disables simulation when GPS is active to prevent data conflicts
- Configurable Settings: Bike weight, wheelset type, gradient, and ascent rate
- FIT File Recording: Records speed and distance to your activity file (only when GPS is disabled)
- Optimized Performance: Reduced battery consumption through efficient algorithms and optional debug logging
- Compatible Garmin Edge devices (540, 840, 1040, 1050, Edge Explore 2)
- ANT+ power meter or smart trainer providing power and cadence data
- Garmin Connect IQ SDK 4.1.0 or higher
- Download the app from the Garmin Connect IQ Store (coming soon)
- Transfer to your Edge device using Garmin Express or Garmin Connect Mobile
- Add the data field to one of your indoor cycling activity profiles
- Configure your bike and rider settings in the data field settings menu
The following settings can be configured through the Garmin Connect IQ app or on your device:
- Rider Weight (kg): Auto-populated from Garmin Connect profile, range: 30-150 kg
- Rider Height (cm): Auto-populated from Garmin Connect profile, range: 120-220 cm
- Bike Type: Road (0.7 Cd), TT (0.6 Cd), or MTB (0.9 Cd)
- Bike Weight (kg): Range: 5-20 kg
- Wheelset Type: Light (0.9x), Medium (1.0x), or Heavy (1.1x)
- Gradient (%): Simulated hill gradient, range: -25% to +25%
- Ascent Rate (m/hour): Simulated climbing rate for varied terrain, range: 0-2000 m/hour
The app uses physics-based calculations to simulate realistic cycling speed:
- Force Calculation: Calculates air resistance, rolling resistance, and gravity forces
- Power Balance: Finds equilibrium speed where power output equals resistance forces
- Speed Smoothing: Applies exponential smoothing for realistic acceleration/deceleration
- GPS Detection: Checks if GPS is active and only simulates speed when GPS is disabled
- FIT Recording: Records simulated speed and distance to native FIT fields (when GPS is off)
- Air Resistance: F = 0.5 × ρ × Cd × A × v²
- Rolling Resistance: F = Crr × m × g × cos(θ)
- Gravity Force: F = m × g × sin(θ)
- Frontal Area: Calculated from rider height and weight using Du Bois formula
The app follows a modular, testable architecture:
source/
├── models/ # Data models (BikeProfile, RiderProfile, PhysicsConstants)
├── physics/ # Physics calculations (PhysicsEngine, ForceCalculator, SpeedSmoother)
├── services/ # Business services (SettingsManager, FitRecorder, GpsDetector)
├── utils/ # Utilities (Validators, Logger)
├── ui/ # User interface (SpeedSimulatorView)
└── GarminSpeedSimulatorApp.mc # Application entry point
test/ # Unit tests for core business logic
- Separation of Concerns: UI, business logic, and data models are separate
- Performance Optimization: Cached bike profiles, pre-computed values, reduced iterations
- GPS Safety: Native FIT fields only written when GPS is disabled
- Battery Efficiency: Conditional debug logging, optimized compute cycle
- Install the Garmin Connect IQ SDK
- Install Visual Studio Code and the Monkey C extension
- Clone this repository:
git clone https://github.com/yourusername/garmin-speed-simulator.git
- Open the project in VS Code
- Build and test using the Garmin simulator
Important: Before building for release, disable debug logging:
- Open
source/utils/Logger.mc - Change
const DEBUG = false;(ensure it's set tofalse) - Build the release version
This will remove all debug logging output, improving battery life and performance.
Unit tests are located in the test/ directory. To run tests:
- Use the Monkey C: Test command in VS Code
- Select the test file to run
- View test results in the output panel
Test coverage includes:
- Physics engine calculations
- Force calculations (air, rolling, gravity)
- Bike profile caching
- Rider profile calculations
- Input validation
- Speed and gradient clamping
This app is optimized for Garmin Connect IQ performance best practices:
- Cached Profiles: Bike profiles and wheelset factors are cached at initialization (no dictionary lookups per compute)
- Reduced Iterations: Physics calculations use 3 iterations instead of 5 for faster execution
- Pre-computed Values: Rider profile calculations (frontal area, total mass) are done once at initialization
- Conditional Logging: Debug logging is disabled in production builds to save battery
- Efficient Compute Cycle: The
compute()method runs once per second and is optimized to complete quickly
- Check your rider weight and height in Garmin Connect profile
- Verify bike type matches your actual bike
- Adjust gradient setting if simulating hills
- Ensure GPS is disabled in your activity profile
- Check that power meter and cadence sensor are connected
- Verify the data field is added to your activity screen
- The app automatically disables simulation when GPS is on
- This prevents conflicts with native GPS speed data
- To use the simulator, disable GPS in your activity profile settings
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch
- Write unit tests for new functionality
- Ensure all tests pass
- Follow the existing code style and architecture
- Submit a pull request
- Use camelCase for variables and methods
- Use PascalCase for classes
- Add documentation comments to public APIs
- Keep methods focused and under 50 lines
- Follow the single responsibility principle
MIT License - see LICENSE file for details
- Physics calculations based on standard cycling aerodynamics models
- Thanks to the Garmin Connect IQ developer community
- Built with assistance from Claude.ai
For issues and feature requests, please use the GitHub issues page.
- Complete architecture refactor for maintainability and testability
- Performance optimizations (cached profiles, reduced iterations)
- GPS-aware FIT recording (prevents data conflicts)
- Conditional debug logging for battery efficiency
- Comprehensive unit test suite
- Improved code organization and documentation
- Initial release
- Basic speed simulation from power and cadence
- Multiple bike profiles
- FIT file recording