Make sure docs are updated / settings_md (push) Canceled after 0s
Build firmware / test (push) Canceled after 0s
Build firmware / build-SITL-Windows (push) Canceled after 0s
Build firmware / build-SITL-Mac (push) Canceled after 0s
Build firmware / build-SITL-Linux (push) Canceled after 0s
Build firmware / build-SITL-Linux-arm64 (push) Canceled after 0s
Build firmware / upload-artifacts (push) Canceled after 0s
Build firmware / build-single-target (push) Canceled after 0s
Build firmware / build (9) (push) Canceled after 0s
Build firmware / build (8) (push) Canceled after 0s
Build firmware / build (7) (push) Canceled after 0s
Build firmware / build (6) (push) Canceled after 0s
Build firmware / build (5) (push) Canceled after 0s
Build firmware / build (4) (push) Canceled after 0s
Build firmware / build (3) (push) Canceled after 0s
Build firmware / build (2) (push) Canceled after 0s
Build firmware / build (14) (push) Canceled after 0s
Build firmware / build (13) (push) Canceled after 0s
Build firmware / build (12) (push) Canceled after 0s
Build firmware / build (11) (push) Canceled after 0s
Build firmware / build (10) (push) Canceled after 0s
Build firmware / build (1) (push) Canceled after 0s
Build firmware / build (0) (push) Canceled after 0s
Build firmware / detect (push) Canceled after 0s
Build pre-release / build (push) Canceled after 0s
Build pre-release / Release (push) Canceled after 0s
6.9 KiB
6.9 KiB
timer() and whenChanged() Examples
timer() Examples
Example 1: Periodic VTX Power Boost
// Boost VTX power to maximum for 1 second every 5 seconds
inav.events.timer(1000, 5000, () => {
inav.override.vtx.power = 4;
});
Example 2: Flashing OSD Layout
// Alternate between OSD layout 0 and 1 every second
inav.events.timer(1000, 1000, () => {
inav.override.osdLayout = 1;
});
Example 3: Periodic Status Check
// Record battery voltage every 10 seconds for 100ms
inav.events.timer(100, 10000, () => {
inav.gvar[0] = inav.flight.vbat;
inav.gvar[1] = inav.flight.current;
});
Example 4: Warning Beep Pattern
// Beep pattern: 200ms on, 200ms off, 200ms on, 5s off
// (Would need multiple timers or different approach for complex patterns)
inav.events.timer(200, 200, () => {
inav.override.rcChannel(8, 2000); // Beeper channel
});
whenChanged() Examples
Example 1: Altitude Change Logger
// Log altitude whenever it changes by 50cm or more
inav.events.whenChanged(inav.flight.altitude, 50, () => {
inav.gvar[0] = inav.flight.altitude;
});
Example 2: RSSI Drop Detection
// Boost VTX power when RSSI drops by 10 or more
inav.events.whenChanged(inav.flight.rssi, 10, () => {
if (inav.flight.rssi < 50) {
inav.override.vtx.power = 4;
}
});
Example 3: Speed Change Tracker
// Track ground speed changes of 100cm/s or more
inav.events.whenChanged(inav.flight.groundSpeed, 100, () => {
inav.gvar[1] = inav.flight.groundSpeed;
});
Example 4: Battery Voltage Monitor
// Record voltage whenever it changes by 1 unit (0.1V)
inav.events.whenChanged(inav.flight.vbat, 1, () => {
inav.gvar[2] = inav.flight.vbat;
inav.gvar[3] = inav.flight.mahDrawn;
});
Example 5: Climb Rate Detection
// Detect rapid climbs (>50cm/s change in vertical speed)
inav.events.whenChanged(inav.flight.verticalSpeed, 50, () => {
if (inav.flight.verticalSpeed > 200) {
// Climbing fast - reduce throttle scale
inav.override.throttleScale = 80;
}
});
Combined Examples
Example 1: Timer + WhenChanged
// Periodic VTX boost
inav.events.timer(1000, 5000, () => {
inav.override.vtx.power = 4;
});
// Log altitude changes
inav.events.whenChanged(inav.flight.altitude, 100, () => {
inav.gvar[0] = inav.flight.altitude;
});
Example 2: Conditional Timer
// Only run timer when armed
if (inav.flight.isArmed) {
inav.events.timer(500, 500, () => {
inav.override.osdLayout = 2;
});
}
Example 3: Emergency Response System
// Monitor RSSI drops
inav.events.whenChanged(inav.flight.rssi, 5, () => {
if (inav.flight.rssi < 30) {
// RSSI critical - max VTX power
inav.override.vtx.power = 4;
inav.gvar[7] = 1; // Set emergency flag
}
});
// Monitor altitude changes
inav.events.whenChanged(inav.flight.altitude, 200, () => {
if (inav.flight.altitude > 10000) {
// Too high - warn
inav.gvar[6] = inav.flight.altitude;
}
});
Example 4: Data Logging System
// Periodic logging every 5 seconds
inav.events.timer(100, 5000, () => {
inav.gvar[0] = inav.flight.vbat;
inav.gvar[1] = inav.flight.current;
inav.gvar[2] = inav.flight.altitude;
});
// Event-based logging on significant changes
inav.events.whenChanged(inav.flight.altitude, 500, () => {
inav.gvar[3] = inav.flight.altitude;
inav.gvar[4] = inav.flight.verticalSpeed;
});
inav.events.whenChanged(inav.flight.groundSpeed, 200, () => {
inav.gvar[5] = inav.flight.groundSpeed;
});
Logic Condition Output Examples
timer() Output
inav.events.timer(1000, 2000, () => {
inav.gvar[0] = 1;
});
Generates:
logic 0 1 -1 49 0 1000 0 2000 0 # TIMER: 1000ms ON, 2000ms OFF
logic 1 1 0 18 0 0 0 0 1 0 # gvar[0] = 1
whenChanged() Output
inav.events.whenChanged(inav.flight.altitude, 50, () => {
inav.gvar[0] = inav.flight.altitude;
});
Generates:
logic 0 1 -1 50 2 12 0 50 0 # DELTA: altitude, threshold 50
logic 1 1 0 18 0 0 2 12 0 # gvar[0] = altitude
Use Cases
timer() Use Cases
- Periodic Tasks - Execute actions at regular intervals
- Flashing Indicators - Toggle states on/off
- Sampling - Collect data periodically
- Timeouts - Implement time-based state machines
- Warning Systems - Beep or flash warnings
whenChanged() Use Cases
- Event Detection - React to significant changes
- Data Logging - Record values when they change
- Thresholds - Trigger actions on large changes
- Rate Limiting - Avoid excessive updates (100ms window)
- Monitoring - Track important parameter changes
Best Practices
timer()
- ✅ Use for periodic, time-based actions
- ✅ Keep durations reasonable (>100ms)
- ✅ Avoid very short ON times (may miss cycles)
- ❌ Don't use for one-time delays (use delay() instead)
- ❌ Don't nest timers (creates complex behavior)
whenChanged()
- ✅ Use for event-driven responses
- ✅ Set thresholds appropriate to your data
- ✅ Monitor slowly-changing values
- ❌ Don't use for rapidly-changing values (may trigger constantly)
- ❌ Don't set threshold too low (noise will trigger it)
- ⚠️ Remember: 100ms detection window (built into DELTA operation)
Common Patterns
Pattern 1: Status Monitor
// Log key parameters when they change significantly
inav.events.whenChanged(inav.flight.vbat, 2, () => { inav.gvar[0] = inav.flight.vbat; });
inav.events.whenChanged(inav.flight.rssi, 10, () => { inav.gvar[1] = inav.flight.rssi; });
inav.events.whenChanged(inav.flight.altitude, 100, () => { inav.gvar[2] = inav.flight.altitude; });
Pattern 2: Periodic Beacon
// Boost VTX power briefly every 10 seconds
inav.events.timer(500, 10000, () => {
inav.override.vtx.power = 4;
});
Pattern 3: Adaptive Response
// React to rapid altitude changes
inav.events.whenChanged(inav.flight.altitude, 200, () => {
if (inav.flight.altitude < 1000) {
inav.override.throttleScale = 120; // Boost
} else {
inav.override.throttleScale = 80; // Reduce
}
});
Troubleshooting
timer() Issues
Problem: Timer doesn't seem to trigger
- Check that ON duration > 0
- Check that OFF duration > 0
- Verify actions are valid
Problem: Timer seems irregular
- INAV runs at different rates depending on mode
- Timer precision is limited by LC execution rate
whenChanged() Issues
Problem: Never triggers
- Check threshold isn't too high
- Verify value actually changes
- Remember: 100ms detection window
Problem: Triggers too often
- Increase threshold
- Value may be noisy
- Consider using timer() for periodic sampling instead
Problem: Doesn't track fast changes
- Built-in 100ms window
- Use timer() for faster sampling if needed