Skip to main content
Kinematrix provides three complete fuzzy logic implementations for control systems that handle imprecise or linguistic variables. Each system uses different inference and defuzzification methods suited to specific applications.

Fuzzy Logic Systems

Mamdani

Traditional fuzzy logic with linguistic rules and centroid defuzzification

Sugeno

Linear consequent functions with weighted average output

Tsukamoto

Monotonic membership functions with height defuzzification

Mamdani Fuzzy System

The Mamdani system is the most intuitive fuzzy logic implementation, using linguistic rules and producing fuzzy outputs that are defuzzified.

Basic Setup

#define ENABLE_MODULE_FUZZY_MAMDANI
#include "Kinematrix.h"

// FuzzyMamdani(max_inputs, max_outputs, max_rules, max_sets_per_variable)
FuzzyMamdani fuzzy(2, 1, 4, 3);

void setup() {
  Serial.begin(115200);
  
  // Add input variables
  fuzzy.addInputVariable("temperature", 15, 35);  // 15-35°C
  fuzzy.addInputVariable("humidity", 20, 90);     // 20-90%
  
  // Add output variable
  fuzzy.addOutputVariable("fan_speed", 0, 100);   // 0-100%
  
  // Define membership functions
  defineMembershipFunctions();
  
  // Add fuzzy rules
  addFuzzyRules();
  
  // Set defuzzification method
  fuzzy.setDefuzzificationMethod(CENTROID);
}

Membership Functions

Mamdani supports multiple membership function types:
// Triangular: [start, peak, end]
float coolParams[3] = {15, 15, 25};
fuzzy.addFuzzySet(0, true, "cool", TRIANGULAR, coolParams);

float warmParams[3] = {20, 25, 30};
fuzzy.addFuzzySet(0, true, "warm", TRIANGULAR, warmParams);

float hotParams[3] = {25, 35, 35};
fuzzy.addFuzzySet(0, true, "hot", TRIANGULAR, hotParams);

Defining Rules

void addFuzzyRules() {
  // Rule 1: IF temp is cool AND humidity is dry THEN fan_speed is low
  int vars1[2] = {0, 1};      // Variable indices
  int sets1[2] = {0, 0};      // Set indices (cool, dry)
  fuzzy.addRule(vars1, sets1, 2, 0, 0, true);  // output_var=0, output_set=0, AND
  
  // Rule 2: IF temp is hot THEN fan_speed is high
  int vars2[1] = {0};
  int sets2[1] = {2};         // hot
  fuzzy.addRule(vars2, sets2, 1, 0, 2, true);  // fan_speed = high
  
  // Rule 3: IF humidity is humid THEN fan_speed is high
  int vars3[1] = {1};
  int sets3[1] = {2};         // humid
  fuzzy.addRule(vars3, sets3, 1, 0, 2, true);
  
  // Rule 4: IF temp is warm OR humidity is moderate THEN fan_speed is medium
  int vars4[2] = {0, 1};
  int sets4[2] = {1, 1};      // warm, moderate
  fuzzy.addRule(vars4, sets4, 2, 0, 1, false); // OR operator
}

Evaluation

void loop() {
  float temperature = readTemperature();
  float humidity = readHumidity();
  
  // Prepare inputs
  float inputs[2] = {temperature, humidity};
  
  // Evaluate fuzzy system
  float* outputs = fuzzy.evaluate(inputs);
  
  if (outputs != nullptr) {
    float fanSpeed = outputs[0];
    setFanSpeed(fanSpeed);
    
    Serial.print("Temp: ");
    Serial.print(temperature);
    Serial.print("°C, Humidity: ");
    Serial.print(humidity);
    Serial.print("%, Fan: ");
    Serial.print(fanSpeed);
    Serial.println("%");
    
    delete[] outputs;  // Free memory
  } else {
    Serial.print("Error: ");
    Serial.println(fuzzy.getErrorMessage());
  }
  
  delay(1000);
}

Defuzzification Methods

// Set defuzzification method
fuzzy.setDefuzzificationMethod(CENTROID);  // Default, most common
// fuzzy.setDefuzzificationMethod(BISECTOR);  // Middle of area
// fuzzy.setDefuzzificationMethod(MOM);       // Mean of Maximum
// fuzzy.setDefuzzificationMethod(SOM);       // Smallest of Maximum
// fuzzy.setDefuzzificationMethod(LOM);       // Largest of Maximum

Sugeno Fuzzy System

Sugeno systems use linear functions in the consequent part, making them computationally efficient and suitable for adaptive control.

Basic Setup

#define ENABLE_MODULE_FUZZY_SUGENO
#include "Kinematrix.h"

FuzzySugeno fuzzy(2, 1, 4, 3);

void setup() {
  // Add variables (same as Mamdani)
  fuzzy.addInputVariable("error", -10, 10);
  fuzzy.addInputVariable("change", -5, 5);
  fuzzy.addOutputVariable("control", -100, 100);
  
  // Define input membership functions
  defineInputSets();
  
  // Define output functions (linear)
  defineOutputFunctions();
  
  // Add rules
  addSugenoRules();
}

Linear Output Functions

void defineOutputFunctions() {
  // Sugeno uses linear functions: output = p0 + p1*x1 + p2*x2 + ...
  
  // Constant function (zero-order Sugeno)
  float zeroParams[1] = {0.0};
  fuzzy.addOutputFunction(0, "zero", CONSTANT, zeroParams);
  
  // Linear function (first-order Sugeno)
  // output = 10 + 2*error + 1*change
  float linearParams[3] = {10.0, 2.0, 1.0};
  fuzzy.addOutputFunction(0, "positive", LINEAR, linearParams);
  
  // Another linear function
  // output = -10 - 2*error - 1*change
  float negativeParams[3] = {-10.0, -2.0, -1.0};
  fuzzy.addOutputFunction(0, "negative", LINEAR, negativeParams);
}

Sugeno Evaluation

void loop() {
  float error = getError();
  float changeRate = getChangeRate();
  
  float inputs[2] = {error, changeRate};
  float* outputs = fuzzy.evaluate(inputs);
  
  if (outputs != nullptr) {
    float controlSignal = outputs[0];
    applyControl(controlSignal);
    delete[] outputs;
  }
}

Tsukamoto Fuzzy System

Tsukamoto systems use monotonic membership functions, allowing direct calculation of crisp outputs.

Basic Setup

#define ENABLE_MODULE_FUZZY_TSUKAMOTO
#include "Kinematrix.h"

FuzzyTsukamoto fuzzy(2, 1, 4, 3);

void setup() {
  fuzzy.addInputVariable("water_level", 0, 100);
  fuzzy.addInputVariable("flow_rate", 0, 50);
  fuzzy.addOutputVariable("valve_position", 0, 100);
  
  // Define monotonic membership functions
  defineMonotonicSets();
  addTsukamotoRules();
}

Monotonic Membership Functions

void defineMonotonicSets() {
  // Input: water_level
  float lowParams[3] = {0, 0, 50};
  fuzzy.addFuzzySet(0, true, "low", TRIANGULAR, lowParams);
  
  float highParams[3] = {50, 100, 100};
  fuzzy.addFuzzySet(0, true, "high", TRIANGULAR, highParams);
  
  // Output: valve_position (must be monotonic)
  float closeParams[3] = {0, 0, 50};
  fuzzy.addFuzzySet(0, false, "close", MONOTONIC_INCREASING, closeParams);
  
  float openParams[3] = {50, 100, 100};
  fuzzy.addFuzzySet(0, false, "open", MONOTONIC_INCREASING, openParams);
}

Complete Example: HVAC Control

#define ENABLE_MODULE_FUZZY_MAMDANI
#include "Kinematrix.h"

const int TEMP_PIN = 34;
const int HUMIDITY_PIN = 35;
const int FAN_PIN = 9;
const int HEATER_PIN = 10;

FuzzyMamdani hvac(2, 2, 9, 3);

void setup() {
  Serial.begin(115200);
  pinMode(FAN_PIN, OUTPUT);
  pinMode(HEATER_PIN, OUTPUT);
  
  // Input variables
  hvac.addInputVariable("temperature", 15, 35);
  hvac.addInputVariable("humidity", 20, 90);
  
  // Output variables
  hvac.addOutputVariable("fan_speed", 0, 100);
  hvac.addOutputVariable("heater_power", 0, 100);
  
  // Temperature sets
  float coldParams[3] = {15, 15, 22};
  float comfortParams[3] = {20, 23, 26};
  float hotParams[3] = {24, 35, 35};
  
  hvac.addFuzzySet(0, true, "cold", TRIANGULAR, coldParams);
  hvac.addFuzzySet(0, true, "comfort", TRIANGULAR, comfortParams);
  hvac.addFuzzySet(0, true, "hot", TRIANGULAR, hotParams);
  
  // Humidity sets
  float dryParams[3] = {20, 20, 45};
  float normalParams[3] = {40, 55, 70};
  float humidParams[3] = {65, 90, 90};
  
  hvac.addFuzzySet(1, true, "dry", TRIANGULAR, dryParams);
  hvac.addFuzzySet(1, true, "normal", TRIANGULAR, normalParams);
  hvac.addFuzzySet(1, true, "humid", TRIANGULAR, humidParams);
  
  // Fan speed sets
  float fanLowParams[3] = {0, 0, 40};
  float fanMedParams[3] = {30, 50, 70};
  float fanHighParams[3] = {60, 100, 100};
  
  hvac.addFuzzySet(0, false, "low", TRIANGULAR, fanLowParams);
  hvac.addFuzzySet(0, false, "medium", TRIANGULAR, fanMedParams);
  hvac.addFuzzySet(0, false, "high", TRIANGULAR, fanHighParams);
  
  // Heater power sets
  float heatOffParams[3] = {0, 0, 20};
  float heatLowParams[3] = {10, 30, 50};
  float heatHighParams[3] = {40, 100, 100};
  
  hvac.addFuzzySet(1, false, "off", TRIANGULAR, heatOffParams);
  hvac.addFuzzySet(1, false, "low", TRIANGULAR, heatLowParams);
  hvac.addFuzzySet(1, false, "high", TRIANGULAR, heatHighParams);
  
  // Define rules
  defineHVACRules();
  
  hvac.setDefuzzificationMethod(CENTROID);
  Serial.println("HVAC Fuzzy Controller Ready");
}

void defineHVACRules() {
  // Rule: IF cold THEN heater high, fan low
  int v1[1] = {0}; int s1[1] = {0};
  hvac.addRule(v1, s1, 1, 0, 0, true);  // fan = low
  hvac.addRule(v1, s1, 1, 1, 2, true);  // heater = high
  
  // Rule: IF hot THEN heater off, fan high
  int v2[1] = {0}; int s2[1] = {2};
  hvac.addRule(v2, s2, 1, 0, 2, true);  // fan = high
  hvac.addRule(v2, s2, 1, 1, 0, true);  // heater = off
  
  // Rule: IF comfort THEN heater low, fan medium
  int v3[1] = {0}; int s3[1] = {1};
  hvac.addRule(v3, s3, 1, 0, 1, true);  // fan = medium
  hvac.addRule(v3, s3, 1, 1, 1, true);  // heater = low
  
  // Rule: IF humid THEN fan high
  int v4[1] = {1}; int s4[1] = {2};
  hvac.addRule(v4, s4, 1, 0, 2, true);  // fan = high
}

void loop() {
  float temp = readTemperature();
  float humidity = readHumidity();
  
  float inputs[2] = {temp, humidity};
  float* outputs = hvac.evaluate(inputs);
  
  if (outputs != nullptr) {
    analogWrite(FAN_PIN, (int)(outputs[0] * 2.55));
    analogWrite(HEATER_PIN, (int)(outputs[1] * 2.55));
    
    Serial.print("T:");
    Serial.print(temp);
    Serial.print("°C H:");
    Serial.print(humidity);
    Serial.print("% Fan:");
    Serial.print(outputs[0]);
    Serial.print("% Heat:");
    Serial.print(outputs[1]);
    Serial.println("%");
    
    delete[] outputs;
  }
  
  delay(2000);
}

float readTemperature() {
  // Implementation for your sensor
  return analogRead(TEMP_PIN) * 0.05 + 15;
}

float readHumidity() {
  // Implementation for your sensor
  return analogRead(HUMIDITY_PIN) * 0.07 + 20;
}

API Reference

Common Methods (All Fuzzy Systems)

MethodDescription
addInputVariable(name, min, max)Define input variable
addOutputVariable(name, min, max)Define output variable
addFuzzySet(varIndex, isInput, name, type, params)Add membership function
addRule(vars, sets, count, outVar, outSet, useAND)Add fuzzy rule
evaluate(inputs)Process inputs and get outputs
setDefuzzificationMethod(method)Set defuzzification type
setDebugMode(enable)Enable/disable debug output
clearVariables()Remove all variables
clearRules()Remove all rules
hasError()Check for errors
getErrorMessage()Get error description

Membership Function Types

  • TRIANGULAR - Three parameters: [start, peak, end]
  • TRAPEZOIDAL - Four parameters: [start, left_peak, right_peak, end]
  • GAUSSIAN - Two parameters: [mean, sigma]
  • SINGLETON - One parameter: [value]
  • MONOTONIC_INCREASING - For Tsukamoto output
  • MONOTONIC_DECREASING - For Tsukamoto output

Defuzzification Methods

  • CENTROID - Center of gravity (most common)
  • BISECTOR - Value that divides area in half
  • MOM - Mean of Maximum values
  • SOM - Smallest of Maximum
  • LOM - Largest of Maximum
For most applications, start with Mamdani fuzzy logic and CENTROID defuzzification. It’s the most intuitive and widely used approach.
Always delete the output array returned by evaluate() to prevent memory leaks:
float* outputs = fuzzy.evaluate(inputs);
// Use outputs...
delete[] outputs;

Model Persistence (ESP32)

#ifdef ESP32
void saveModel() {
  if (fuzzy.saveModel("/fuzzy_model.dat")) {
    Serial.println("Model saved to SPIFFS");
  }
}

void loadModel() {
  if (fuzzy.loadModel("/fuzzy_model.dat")) {
    Serial.println("Model loaded from SPIFFS");
  }
}
#endif

Build docs developers (and LLMs) love