Mamdani fuzzy inference system for rudder position control, implemented from scratch in MATLAB and interfaced with an Arduino-based physical balancing platform.
Built as part of the Neuro-Fuzzy Systems course at UPIITA, IPN.
The system reads two sensor inputs from an Arduino. The airspeed (simulated via potentiometer, 0–1000) and flight angle (potentiometer, -10° to +10°), and it uses a Mamdani FIS to infer a recommended rudder position (0–10). The result is sent back to the Arduino and displayed on a 16x2 LCD.
The FIS runs entirely in MATLAB without using the Fuzzy Logic Toolbox. Membership functions, rule evaluation, aggregation and centroid defuzzification are all implemented manually.
[Potentiometer: Speed] ──┐
├──> Arduino Mega → (UART/Serial) → MATLAB FIS → Centroid Defuzz → Arduino LCD Display
[Potentiometer: Angle] ──┘
Communication uses a handshake protocol over serial: Arduino confirms readiness, MATLAB requests data, Arduino sends both sensor values as a space-separated string, MATLAB returns the inferred position value character by character.
Inputs
| Variable | Universe | Sets |
|---|---|---|
| SPEED | [0, 1000] | LOW (trapezoid), MED (triangle), HIGH (trapezoid) |
| ANGLE | [-10, 10] | DOWN (trapezoid), LEVEL (triangle), UP (trapezoid) |
Output
| Variable | Universe | Sets |
|---|---|---|
| POSITION | [0, 10] | L, LM, M, HM, H (triangles) |
Rule base (9 rules)
| Speed: Low | Speed: OK | Speed: High | |
|---|---|---|---|
| Angle: Down | L | LM | H |
| Angle: Level | L | M | HM |
| Angle: Up | L | LM | H |
AND operator: minimum. Aggregation: maximum. Defuzzification: centroid.
| File | Description |
|---|---|
ProjectExample3.m |
Main MATLAB script-serial communication loop, FIS evaluation, defuzzification |
Triangular.m |
Triangular membership function implementation |
Trapezoidal.m |
Trapezoidal membership function implementation |
Connection3_1.ino |
Arduino firmware-sensor reading, serial protocol, LCD display |
- Arduino Mega
- 2× analog potentiometers (speed and angle inputs)
- Stepper motor (28BYJ-48) for physical balancing platform
- 16×2 LCD display
- DC motor for platform simulation
The physical platform was a balancing rig built to simulate a simplified aircraft attitude. The stepper tracked real-time angle changes from the sensor. The FIS output was computed and displayed; direct actuation via the inferred position was partially implemented.
This was a learning project focused on understanding Mamdani FIS from the ground up, writing the membership functions by hand rather than relying on toolbox implementations made the math much clearer. The rule base is simple by design: the course objective was to get the full inference pipeline working end-to-end, not to build a production controller.
If extended, the next step would be closing the control loop (feeding the FIS output directly to the stepper) and comparing Mamdani against a Takagi-Sugeno-Kang implementation for the same rule base.
The hardest part wasn't the FIS, because once the math clicked implementing the membership functions manually was straightforward. The real headache was getting everything to work together at the same time. The hardware had a habit of behaving fine in isolation and then refusing to cooperate the moment everything was connected. The delays scattered through the serial loop aren't elegant, but they're there because the potentiometer readings needed settling time before they were reliable and learned that the hard way.
I chose an aircraft because it made stability intuitive to explain. A robot or ground vehicle has too many edge cases to reason about quickly; a plane on a balancing rig has one obvious failure mode, it tips. There was also a bigger idea behind it: if the single-axis version worked, the same FIS approach could extend to full spherical stabilization (pitch, roll, yaw), which starts to look like a very simplified autopilot or turbulence compensation system. That ambition was probably too large for a course project, but it shaped how the rule base was designed.