Objective
Configure a fixed-interval control loop that runs deterministically. The loop should execute at a consistent sampling rate (for example, every 10 ms). All sensing, PID computation, and actuator updates must occur inside this timed loop.
Implementation Guidance
- Use a non-blocking timing method (such as
millis()or a hardware timer) to maintain a constant loop interval - Store the loop interval in seconds for proper integral and derivative calculation
- Ensure that sensor readings are filtered before entering the PID equation
- Print loop timing and position values to Serial during early testing
const unsigned long LOOP_INTERVAL_MS = 10; // 10ms = 100Hzconst float dt = LOOP_INTERVAL_MS / 1000.0; // Convert to secondsunsigned long previousTime = 0;void setup() { Serial.begin(115200); initSensor(); initMotor();}
void loop() { unsigned long currentTime = millis(); if (currentTime - previousTime >= LOOP_INTERVAL_MS) { previousTime = currentTime; // 1. Read and filter sensor float position = readFilteredPosition(); // 2. Compute PID output float output = computePID(setpoint, position, dt); // 3. Update actuator setMotorOutput(output); // Debug output Serial.print("Pos: "); Serial.print(position); Serial.print(" Out: "); Serial.println(output); }}
Key Requirements
- Loop must run at consistent intervals (10ms recommended)
- All control code inside the timed section
- dt stored in seconds for PID calculations
- Sensor filtering before PID computation
Key Takeaways
- Use non-blocking timing with millis()
- 10ms loop interval = 100Hz sampling rate
- Store dt in seconds for PID math
- Filter sensor readings before PID