Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MuShibo/Micro-Wheeled_leg-Robot/llms.txt

Use this file to discover all available pages before exploring further.

The firmware uses nine PIDController instances and three LowPassFilter instances, all provided by SimpleFOC. They form a cascade: the outer pitch/yaw/roll loops generate torque setpoints, a dead-band compensator handles the non-linear motor region near zero, and an adaptive integrator slowly trims the balance zero-point. Every controller is registered with the SimpleFOC Commander so its parameters can be adjusted over the Serial monitor at 115 200 baud without reflashing.

PID Controllers

All PIDController instances are declared with {.P, .I, .D, .ramp, .limit} initialiser syntax. The ramp field limits the rate of change of the output per second; all controllers use 100000 (effectively unlimited) to preserve control bandwidth.
CommanderVariablePIDRampLimitRole
Apid_angle1.000100 0008Pitch angle error → balance torque
Bpid_gyro0.0600100 0008Pitch rate (gyro Y) → balance torque
Cpid_distance0.500100 0008Wheel displacement error → balance torque
Dpid_speed0.7*00100 0008Wheel speed error → balance torque (*adaptive)
Epid_yaw_angle1.000100 0008Accumulated yaw angle error → differential torque
Fpid_yaw_gyro0.0400100 0008Yaw rate (gyro Z) → differential torque
Hpid_lqr_u1.0150100 0008Dead-band non-linearity compensation (PI)
Ipid_zeropoint0.00200100 0004Adaptive balance zero-point integrator
Kpid_roll_angle8.000100 000450Roll angle error → leg servo differential
pid_lqr_u is the only controller with a non-zero integral term (I = 15). It only activates inside the dead-band (|LQR_u| < 5, joystick idle, |distance_control| < 4, not jumping). Its integrator is explicitly cleared (pid_lqr_u.error_prev = 0) whenever the dead-band condition is not met, preventing wind-up.

Low-Pass Filters

SimpleFOC LowPassFilter instances are first-order IIR filters with time constant Tf (seconds). Smaller Tf = faster response but less smoothing.
CommanderVariableTf (s)Input Signal
Glpf_joyy0.2Joystick Y (wrobot.joyy) — smooths speed commands to the LQR speed term
Jlpf_zeropoint0.1distance_control — filters the signal driving the adaptive zero-point integrator
Llpf_roll0.3Roll angle (mpu6050.getAngleX() + 2.0) — smooths roll compensation before the servo PID

Motor Velocity PID

The SimpleFOC inner velocity loop for each wheel motor is configured directly in setup() and is not accessible via the Commander interface. These values act as an anti-cogging inner loop within the voltage torque controller.
motor1.PID_velocity.P = 0.05;
motor1.PID_velocity.I = 1.0;
motor1.PID_velocity.D = 0;

motor2.PID_velocity.P = 0.05;
motor2.PID_velocity.I = 1.0;
motor2.PID_velocity.D = 0;
Both motors use identical values. To change them you must edit the source and reflash.

Adaptive pid_speed Gain

pid_speed.P is overwritten every loop iteration in lqr_balance_loop() based on the current leg height. The Commander-set value for channel D will be overridden at runtime.
Leg Height (wrobot.height)pid_speed.P
< 500.7
50–630.6
≥ 640.5
A shorter leg stance produces faster inverted-pendulum dynamics and requires a higher speed gain. Taller stances are naturally slower and use a lower gain to avoid overshoot.

Commander Syntax Reference

The Commander reads single-character channel identifiers from Serial (115 200 baud). Each channel maps to a registered PID or LPF instance. The syntax follows the SimpleFOC Commander convention:
<Channel><Field><Value>

Fields:
  P = proportional gain
  I = integral gain
  D = derivative gain
  F = low-pass filter time constant (Tf)
  R = output ramp limit
  L = output limit

Examples:
  AP1.5      → pid_angle.P = 1.5
  BP0.08     → pid_gyro.P = 0.08
  HI20       → pid_lqr_u.I = 20
  GF0.15     → lpf_joyy.Tf = 0.15
  KL300      → pid_roll_angle.limit = 300
  DP0.55     → pid_speed.P = 0.55  (overridden by adaptive logic each loop)
Sending a channel letter alone (e.g. A) prints the current values of that controller to Serial.
Commander changes are volatile and are lost on reboot. When you find values that work well, copy them back into the corresponding PIDController or LowPassFilter initialisers in wl_pro_robot.ino before reflashing.
SimpleFOC Commander echoes the new parameter value back over Serial immediately after a write. Watch the Serial Monitor to confirm the value was parsed correctly — a malformed string (e.g. missing numeric digits) will leave the parameter unchanged and Commander will not print an acknowledgement.

Build docs developers (and LLMs) love