Hi, so from the forum here I read that I could use http://makeproto.com/ to convert a fuzzy logic i have created from matlab to arduino language. I gave it a shot and it seemed to have successfully converted it to an arduino compatible code however, i'm finding it hard to edit the code as for me it rather is too complex. I was wondering if anybody here has tried using this method and if you could help me. My fuzzy logic isn't that long it's just 1 input and 3 outpus[unripe,ripe,overripe]. I can share the matlab file as well as the arduino converted program as well. The variables and how it is coded is really just confusing for a beginner like me and I've been trying to find online resources to use as reference in translating it but to no avail.
Please share both sets of code, using code tags when you do
how do i use tags? I'm new in the forum so I don't understand what tags here are for or how to use it
Matlab Fuzzy.pdf (288.2 KB)
fisMelon.zip (9.0 KB)
I've added the following attachments pasting the code directly here might make it look really long and as well as it has an included header that i think is necessary for the arduino converted version to work. The pdf file includes the matlab coding format as well as some snippets of the fuzzy logic
To add more background to what I am doing. I want to be able to have an analog input - just 1. Then the output would be that it would display in an I2C lcd the current state of the fruit.
That is one of the reasons for using code tags when posting the code here as it is presented in a scrolling text box and can be copied with a single click
Please post the code here to make it as easy as possible to provide help
#include "fis_header.h"
// Number of inputs to the fuzzy inference system
const int fis_gcI = 1;
// Number of outputs to the fuzzy inference system
const int fis_gcO = 1;
// Number of rules to the fuzzy inference system
const int fis_gcR = 3;
FIS_TYPE g_fisInput[fis_gcI];
FIS_TYPE g_fisOutput[fis_gcO];
void setup()
{
Serial.begin(9600);
// initialize the Analog pins for input.
// Pin mode for Input: PPM_Level
pinMode(0 , INPUT);
// initialize the Analog pins for output.
// Pin mode for Output: Fruit_Status
pinMode(1 , OUTPUT);
}
// Loop routine runs over and over again forever:
void loop()
{
// Read Input: PPM_Level
g_fisInput[0] = analogRead(0);
g_fisOutput[0] = 0;
fis_evaluate();
// Set output vlaue: Fruit_Status
analogWrite(1 , g_fisOutput[0]);
}
//***********************************************************************
// Support functions for Fuzzy Inference System
//***********************************************************************
// Gaussian Member Function
FIS_TYPE fis_gaussmf(FIS_TYPE x, FIS_TYPE* p)
{
FIS_TYPE s = p[0], c = p[1];
FIS_TYPE t = (x - c) / s;
return exp(-(t * t) / 2);
}
// Triangular Member Function
FIS_TYPE fis_trimf(FIS_TYPE x, FIS_TYPE* p)
{
FIS_TYPE a = p[0], b = p[1], c = p[2];
FIS_TYPE t1 = (x - a) / (b - a);
FIS_TYPE t2 = (c - x) / (c - b);
if ((a == b) && (b == c)) return (FIS_TYPE) (x == a);
if (a == b) return (FIS_TYPE) (t2*(b <= x)*(x <= c));
if (b == c) return (FIS_TYPE) (t1*(a <= x)*(x <= b));
t1 = min(t1, t2);
return (FIS_TYPE) max(t1, 0);
}
FIS_TYPE fis_min(FIS_TYPE a, FIS_TYPE b)
{
return min(a, b);
}
FIS_TYPE fis_max(FIS_TYPE a, FIS_TYPE b)
{
return max(a, b);
}
FIS_TYPE fis_array_operation(FIS_TYPE *array, int size, _FIS_ARR_OP pfnOp)
{
int i;
FIS_TYPE ret = 0;
if (size == 0) return ret;
if (size == 1) return array[0];
ret = array[0];
for (i = 1; i < size; i++)
{
ret = (*pfnOp)(ret, array[i]);
}
return ret;
}
//***********************************************************************
// Data for Fuzzy Inference System
//***********************************************************************
// Pointers to the implementations of member functions
_FIS_MF fis_gMF[] =
{
fis_gaussmf, fis_trimf
};
// Count of member function for each Input
int fis_gIMFCount[] = { 3 };
// Count of member function for each Output
int fis_gOMFCount[] = { 3 };
// Coefficients for the Input Member Functions
FIS_TYPE fis_gMFI0Coeff1[] = { 49.5, 107 };
FIS_TYPE fis_gMFI0Coeff2[] = { 29.41, 234.5 };
FIS_TYPE fis_gMFI0Coeff3[] = { 63.6, 284.5 };
FIS_TYPE* fis_gMFI0Coeff[] = { fis_gMFI0Coeff1, fis_gMFI0Coeff2, fis_gMFI0Coeff3 };
FIS_TYPE** fis_gMFICoeff[] = { fis_gMFI0Coeff };
// Coefficients for the Output Member Functions
FIS_TYPE fis_gMFO0Coeff1[] = { 0, 107, 142 };
FIS_TYPE fis_gMFO0Coeff2[] = { 77, 234.5, 392 };
FIS_TYPE fis_gMFO0Coeff3[] = { 223, 284.5, 438 };
FIS_TYPE* fis_gMFO0Coeff[] = { fis_gMFO0Coeff1, fis_gMFO0Coeff2, fis_gMFO0Coeff3 };
FIS_TYPE** fis_gMFOCoeff[] = { fis_gMFO0Coeff };
// Input membership function set
int fis_gMFI0[] = { 0, 0, 0 };
int* fis_gMFI[] = { fis_gMFI0};
// Output membership function set
int fis_gMFO0[] = { 1, 1, 1 };
int* fis_gMFO[] = { fis_gMFO0};
// Rule Weights
FIS_TYPE fis_gRWeight[] = { 1, 1, 1 };
// Rule Type
int fis_gRType[] = { 1, 1, 1 };
// Rule Inputs
int fis_gRI0[] = { 1 };
int fis_gRI1[] = { 2 };
int fis_gRI2[] = { 3 };
int* fis_gRI[] = { fis_gRI0, fis_gRI1, fis_gRI2 };
// Rule Outputs
int fis_gRO0[] = { 1 };
int fis_gRO1[] = { 2 };
int fis_gRO2[] = { 3 };
int* fis_gRO[] = { fis_gRO0, fis_gRO1, fis_gRO2 };
// Input range Min
FIS_TYPE fis_gIMin[] = { 0 };
// Input range Max
FIS_TYPE fis_gIMax[] = { 500 };
// Output range Min
FIS_TYPE fis_gOMin[] = { 0 };
// Output range Max
FIS_TYPE fis_gOMax[] = { 500 };
//***********************************************************************
// Data dependent support functions for Fuzzy Inference System
//***********************************************************************
FIS_TYPE fis_MF_out(FIS_TYPE** fuzzyRuleSet, FIS_TYPE x, int o)
{
FIS_TYPE mfOut;
int r;
for (r = 0; r < fis_gcR; ++r)
{
int index = fis_gRO[r][o];
if (index > 0)
{
index = index - 1;
mfOut = (fis_gMF[fis_gMFO[o][index]])(x, fis_gMFOCoeff[o][index]);
}
else if (index < 0)
{
index = -index - 1;
mfOut = 1 - (fis_gMF[fis_gMFO[o][index]])(x, fis_gMFOCoeff[o][index]);
}
else
{
mfOut = 0;
}
fuzzyRuleSet[0][r] = fis_min(mfOut, fuzzyRuleSet[1][r]);
}
return fis_array_operation(fuzzyRuleSet[0], fis_gcR, fis_max);
}
FIS_TYPE fis_defuzz_centroid(FIS_TYPE** fuzzyRuleSet, int o)
{
FIS_TYPE step = (fis_gOMax[o] - fis_gOMin[o]) / (FIS_RESOLUSION - 1);
FIS_TYPE area = 0;
FIS_TYPE momentum = 0;
FIS_TYPE dist, slice;
int i;
// calculate the area under the curve formed by the MF outputs
for (i = 0; i < FIS_RESOLUSION; ++i){
dist = fis_gOMin[o] + (step * i);
slice = step * fis_MF_out(fuzzyRuleSet, dist, o);
area += slice;
momentum += slice*dist;
}
return ((area == 0) ? ((fis_gOMax[o] + fis_gOMin[o]) / 2) : (momentum / area));
}
//***********************************************************************
// Fuzzy Inference System
//***********************************************************************
void fis_evaluate()
{
FIS_TYPE fuzzyInput0[] = { 0, 0, 0 };
FIS_TYPE* fuzzyInput[fis_gcI] = { fuzzyInput0, };
FIS_TYPE fuzzyOutput0[] = { 0, 0, 0 };
FIS_TYPE* fuzzyOutput[fis_gcO] = { fuzzyOutput0, };
FIS_TYPE fuzzyRules[fis_gcR] = { 0 };
FIS_TYPE fuzzyFires[fis_gcR] = { 0 };
FIS_TYPE* fuzzyRuleSet[] = { fuzzyRules, fuzzyFires };
FIS_TYPE sW = 0;
// Transforming input to fuzzy Input
int i, j, r, o;
for (i = 0; i < fis_gcI; ++i)
{
for (j = 0; j < fis_gIMFCount[i]; ++j)
{
fuzzyInput[i][j] =
(fis_gMF[fis_gMFI[i][j]])(g_fisInput[i], fis_gMFICoeff[i][j]);
}
}
int index = 0;
for (r = 0; r < fis_gcR; ++r)
{
if (fis_gRType[r] == 1)
{
fuzzyFires[r] = FIS_MAX;
for (i = 0; i < fis_gcI; ++i)
{
index = fis_gRI[r][i];
if (index > 0)
fuzzyFires[r] = fis_min(fuzzyFires[r], fuzzyInput[i][index - 1]);
else if (index < 0)
fuzzyFires[r] = fis_min(fuzzyFires[r], 1 - fuzzyInput[i][-index - 1]);
else
fuzzyFires[r] = fis_min(fuzzyFires[r], 1);
}
}
else
{
fuzzyFires[r] = FIS_MIN;
for (i = 0; i < fis_gcI; ++i)
{
index = fis_gRI[r][i];
if (index > 0)
fuzzyFires[r] = fis_max(fuzzyFires[r], fuzzyInput[i][index - 1]);
else if (index < 0)
fuzzyFires[r] = fis_max(fuzzyFires[r], 1 - fuzzyInput[i][-index - 1]);
else
fuzzyFires[r] = fis_max(fuzzyFires[r], 0);
}
}
fuzzyFires[r] = fis_gRWeight[r] * fuzzyFires[r];
sW += fuzzyFires[r];
}
if (sW == 0)
{
for (o = 0; o < fis_gcO; ++o)
{
g_fisOutput[o] = ((fis_gOMax[o] + fis_gOMin[o]) / 2);
}
}
else
{
for (o = 0; o < fis_gcO; ++o)
{
g_fisOutput[o] = fis_defuzz_centroid(fuzzyRuleSet, o);
}
}
}
Above is the converted code.
Header file of the code contains as follows:
#define FIS_TYPE float
#define FIS_RESOLUSION 101
#define FIS_MIN -3.4028235E+38
#define FIS_MAX 3.4028235E+38
typedef FIS_TYPE(*_FIS_MF)(FIS_TYPE, FIS_TYPE*);
typedef FIS_TYPE(*_FIS_ARR_OP)(FIS_TYPE, FIS_TYPE);
typedef FIS_TYPE(*_FIS_ARR)(FIS_TYPE*, int, _FIS_ARR_OP);
Direct code from matlab is this:
[System]
Name='Melon'
Type='mamdani'
Version=2.0
NumInputs=1
NumOutputs=1
NumRules=3
AndMethod='min'
OrMethod='max'
ImpMethod='min'
AggMethod='max'
DefuzzMethod='centroid'
[Input1]
Name='PPM_Level'
Range=[0 500]
NumMFs=3
MF1='Level_1':'gaussmf',[49.5 107]
MF2='Level_2':'gaussmf',[29.41 234.5]
MF3='Level_3':'gaussmf',[63.6 284.5]
[Output1]
Name='Fruit_Status'
Range=[0 500]
NumMFs=3
MF1='Unripe':'trimf',[0 107 142]
MF2='Ripe':'trimf',[77 234.5 392]
MF3='Overripe':'trimf',[223 284.5 438]
[Rules]
1, 1 (1) : 1
2, 2 (1) : 1
3, 3 (1) : 1
// initialize the Analog pins for input.
// Pin mode for Input: PPM_Level
pinMode(0 , INPUT);
// initialize the Analog pins for output.
// Pin mode for Output: Fruit_Status
pinMode(1 , OUTPUT);
I don't profess to know what you want to do with the code but neither of these pinMode()s do what the comments say as they are operating on pins 0 and 1, which are shared with the Serial interface, rather than pins A0 and A1 which the comments would indicate
Can you help me identify the part where i could add in the actual input? as well as where the outputs of the rules are?
I just really need to know where i could insert my analog input as well as the code for the lcd where i could display whether it's ripe,unripe,overripe. the output pin the code provided is something i don't need
Sorry, but this is not something that I have any knowledge of
Okay thank you, hopefully someone could help me with it ![]()
When you have corrected the issue with the pins, use serial to see what you have in g_fisOutput[0] at the end of loop.
To my understanding the fisOutput represents an analog output [based on the code in the start] or am i seeing it wrong?
I don't know what it is yet, but from its name, I suspect that it's the result of the fuzzy calc, so it may be possible to deduce by experiment what it means.
okay thanks i'll try racking my brain again with it
// initialize the Analog pins for input.
// Pin mode for Input: PPM_Level
pinMode(0 , INPUT);
I guess they don't know that you don't use pinMode() on pins unless you use them for digitalRead() or digitalWrite(). Even if they got the pin number right (A0) this would be useless at best.
// Set output vlaue: Fruit_Status
analogWrite(1 , g_fisOutput[0]);
I guess they don't know that Pin 1 is NOT an analogWrite() pin. Try one of the PWM pins, like 5 or 6.
I was able to determine how to work through the code thanks to the creator of the converter itself. Thank you for everyone who tried to help. It was actually a very short solution as I just needed to change the output section of the g_fisOutput[0]!
