Ana Sayfa Arduino Arduino İle Bulanık Mantık Kontrol Uygulaması

Arduino İle Bulanık Mantık Kontrol Uygulaması

19 min read
3
7
6,092

Kontrol sistemlerinde karşılaşılan en büyük problemlerden biri denetim mekanizmasına ait matematiksel modelin oluşturulmasının zor olmasıdır. Bu model oluşturulsa bile geleneksel mantık ile uygulamayı gerçekleştirmek çok karmaşık problemlere yol açacaktır. Bulanık Mantık ise kontrol sistemine ait matematiksel modele ihtiyaç duymadan sadece dilsel değişkenler yardımıyla denetim mekanizmasını oluşturabilmektedir.

Bulanıklaştırma, giriş değişkenleri ile çıkış değişkenlerinin dilsel ifadelere dönüştürülme işlemidir. Bu nedenle ilk yapılacak olan giriş ve çıkış değişkenlerinin belirlenmesi, klima sistemi için giriş değişkenleri olarak; ortam sıcaklığı, hedef sıcaklık seçilmiştir ve çıkış değişkenleri olarak; klima çıkışı seçilmiştir. Daha sonra bulunan giriş ve çıkış değişkenlerine dilsel ifadeler verilmek suretiyle üyelik derecelerinin tespiti yapılır.

Projenin Çalışma Mantığı

Ortam sıcaklığı ve hedef(referans) sıcaklıkları bulanık mantık girişlerimizdir. Klimanın çıkışı ise bulanık mantık çıkışımızdır. Ortam ve hedef sıcaklığı dilsel ifadelere dönüştürerek üyelik fonksiyonu oluşturuyoruz. Bunları biz 5 tane üyelik fonksiyonlarıyla oluşturduk. Bunlar ÇSO (çok soğuk), SO(soğuk), I(ılık), SI(sıcak), ÇSI (çok sıcak) ve aynı şekilde çıkışımızı da 3 tane üyelik fonksiyonlarıyla ifade ediyoruz. Bunlar Soğut, DY (değişiklik yapma), Isıt.Daha sonra 2 girişimiz ve her biri 5 tane üyelik fonksiyonundan oluştuğu için 5*5=25 tane kuralımızın olması gerekiyor. Örnek olarak ortam sıcaklığımız ÇSO, hedef sıcaklığımız ÇSO ise klimanın çıkışı DY (değişiklik yapma olsun).

Çalışma mantığına gelince ortam ve hedef sıcaklıklar karşılaştırılıp bulanık mantık denetleyicisine gönderilir. Bulanık mantık denetleyicisi kural tabanına göre çıkarım yapar ve çıkışın bize ne olması gerektiğini bulur.

bulanık_mantık_kural

 

Üyelik Fonksiyonları

Ortam sıcaklığı Üyelik Fonksiyonu;

ÇSO= [-20 -10 0 5], SO= [0 5 15 20], I= [15 20 30 35], SI= [30 35 45 50], ÇSI= [45 50 60 70]

Ortam sıcaklığı Üyelik Fonksiyonu

 

Hedef sıcaklığı Üyelik Fonksiyonu;

 

ÇSO= [-20 -10 0 5], SO= [0 5 15 20], I= [15 20 30 35], SI= [30 35 45 50], ÇSI= [45 50 60 70]

 

Hedef sıcaklığı Üyelik Fonksiyonu

 

Klima çıkışı Pwm Üyelik Fonksiyonu;

SOĞUT= [50 100 150], DY= [100 150 200], ISIT= [150 200 255]

Klima çıkışı Pwm Üyelik Fonksiyonu

Uygulamanın kodları;


#include "fis_header.h"

const int fis_gcI = 2;

const int fis_gcO = 1;

const int fis_gcR = 25;

FIS_TYPE g_fisInput[fis_gcI];

FIS_TYPE g_fisOutput[fis_gcO];

void setup()

{

    pinMode(3 , INPUT);

    pinMode(7 , INPUT);

    Serial.begin(9600);

    pinMode(2 , OUTPUT);

}

void loop()

{

   g_fisInput[0] = analogRead(A3);

   g_fisInput[0]=map(g_fisInput[0],0,1023,0,60);

   g_fisInput[1] = analogRead(A7);

   g_fisInput[1]=map(g_fisInput[1],0,1023,0,60);

    g_fisOutput[0] = 0;

    fis_evaluate();

    analogWrite(2 , g_fisOutput[0]);

    Serial.print("ortam sicakligi: ");

    Serial.println(g_fisInput[0]);

    Serial.print("hedef sicakligi: ");

    Serial.println(g_fisInput[1]);

    Serial.print("klima cikisi PWM:");

    Serial.println(g_fisOutput[0]);

     Serial.println("");

    delay(1000);

}

FIS_TYPE fis_trapmf(FIS_TYPE x, FIS_TYPE* p)

{

    FIS_TYPE a = p[0], b = p[1], c = p[2], d = p[3];

    FIS_TYPE t1 = ((x <= c) ? 1 : ((d < x) ? 0 : ((c != d) ? ((d - x) / (d - c)) : 0)));

    FIS_TYPE t2 = ((b <= x) ? 1 : ((x < a) ? 0 : ((a != b) ? ((x - a) / (b - a)) : 0)));

    return (FIS_TYPE) min(t1, t2);

}

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;

}

_FIS_MF fis_gMF[] =

{    fis_trapmf, fis_trimf };

int fis_gIMFCount[] = { 5, 5 };

int fis_gOMFCount[] = { 3 };

FIS_TYPE fis_gMFI0Coeff1[] = { -20, -10, 0, 5 };

FIS_TYPE fis_gMFI0Coeff2[] = { 0, 5, 15, 20 };

FIS_TYPE fis_gMFI0Coeff3[] = { 15, 20, 30, 35 };

FIS_TYPE fis_gMFI0Coeff4[] = { 30, 35, 45, 50 };

FIS_TYPE fis_gMFI0Coeff5[] = { 45, 50, 60, 70 };

FIS_TYPE* fis_gMFI0Coeff[] = { fis_gMFI0Coeff1, fis_gMFI0Coeff2, fis_gMFI0Coeff3, fis_gMFI0Coeff4, fis_gMFI0Coeff5 };

FIS_TYPE fis_gMFI1Coeff1[] = { -20, -10, 0, 5 };

FIS_TYPE fis_gMFI1Coeff2[] = { 0, 5, 15, 20 };

FIS_TYPE fis_gMFI1Coeff3[] = { 15, 20, 30, 35 };

FIS_TYPE fis_gMFI1Coeff4[] = { 30, 35, 45, 50 };

FIS_TYPE fis_gMFI1Coeff5[] = { 45, 50, 60, 70 };

FIS_TYPE* fis_gMFI1Coeff[] = { fis_gMFI1Coeff1, fis_gMFI1Coeff2, fis_gMFI1Coeff3, fis_gMFI1Coeff4, fis_gMFI1Coeff5 };

FIS_TYPE** fis_gMFICoeff[] = { fis_gMFI0Coeff, fis_gMFI1Coeff };

FIS_TYPE fis_gMFO0Coeff1[] = { 50, 100, 150 };

FIS_TYPE fis_gMFO0Coeff2[] = { 100, 150, 200 };

FIS_TYPE fis_gMFO0Coeff3[] = { 150, 200, 255 };

FIS_TYPE* fis_gMFO0Coeff[] = { fis_gMFO0Coeff1, fis_gMFO0Coeff2, fis_gMFO0Coeff3 };

FIS_TYPE** fis_gMFOCoeff[] = { fis_gMFO0Coeff };

int fis_gMFI0[] = { 0, 0, 0, 0, 0 };

int fis_gMFI1[] = { 0, 0, 0, 0, 0 };

int* fis_gMFI[] = { fis_gMFI0, fis_gMFI1};

int fis_gMFO0[] = { 1, 1, 1 };

int* fis_gMFO[] = { fis_gMFO0};

FIS_TYPE fis_gRWeight[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };

int fis_gRType[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };

int fis_gRI0[] = { 1, 1 };

int fis_gRI1[] = { 1, 2 };

int fis_gRI2[] = { 1, 3 };

int fis_gRI3[] = { 1, 4 };

int fis_gRI4[] = { 1, 5 };

int fis_gRI5[] = { 2, 1 };

int fis_gRI6[] = { 2, 2 };

int fis_gRI7[] = { 2, 3 };

int fis_gRI8[] = { 2, 4 };

int fis_gRI9[] = { 2, 5 };

int fis_gRI10[] = { 3, 1 };

int fis_gRI11[] = { 3, 2 };

int fis_gRI12[] = { 3, 3 };

int fis_gRI13[] = { 3, 4 };

int fis_gRI14[] = { 3, 5 };

int fis_gRI15[] = { 4, 1 };

int fis_gRI16[] = { 4, 2 };

int fis_gRI17[] = { 4, 3 };

int fis_gRI18[] = { 4, 4 };

int fis_gRI19[] = { 4, 5 };

int fis_gRI20[] = { 5, 1 };

int fis_gRI21[] = { 5, 2 };

int fis_gRI22[] = { 5, 3 };

int fis_gRI23[] = { 5, 4 };

int fis_gRI24[] = { 5, 5 };

int* fis_gRI[] = { fis_gRI0, fis_gRI1, fis_gRI2, fis_gRI3, fis_gRI4, fis_gRI5, fis_gRI6, fis_gRI7, fis_gRI8, fis_gRI9, fis_gRI10, fis_gRI11, fis_gRI12, fis_gRI13, fis_gRI14, fis_gRI15, fis_gRI16, fis_gRI17, fis_gRI18, fis_gRI19, fis_gRI20, fis_gRI21, fis_gRI22, fis_gRI23, fis_gRI24 };

int fis_gRO0[] = { 2 };

int fis_gRO1[] = { 3 };

int fis_gRO2[] = { 3 };

int fis_gRO3[] = { 3 };

int fis_gRO4[] = { 3 };

int fis_gRO5[] = { 1 };

int fis_gRO6[] = { 2 };

int fis_gRO7[] = { 3 };

int fis_gRO8[] = { 3 };

int fis_gRO9[] = { 3 };

int fis_gRO10[] = { 1 };

int fis_gRO11[] = { 1 };

int fis_gRO12[] = { 2 };

int fis_gRO13[] = { 3 };

int fis_gRO14[] = { 3 };

int fis_gRO15[] = { 1 };

int fis_gRO16[] = { 1 };

int fis_gRO17[] = { 1 };

int fis_gRO18[] = { 2 };

int fis_gRO19[] = { 3 };

int fis_gRO20[] = { 1 };

int fis_gRO21[] = { 1 };

int fis_gRO22[] = { 1 };

int fis_gRO23[] = { 1 };

int fis_gRO24[] = { 2 };

int* fis_gRO[] = { fis_gRO0, fis_gRO1, fis_gRO2, fis_gRO3, fis_gRO4, fis_gRO5, fis_gRO6, fis_gRO7, fis_gRO8, fis_gRO9, fis_gRO10, fis_gRO11, fis_gRO12, fis_gRO13, fis_gRO14, fis_gRO15, fis_gRO16, fis_gRO17, fis_gRO18, fis_gRO19, fis_gRO20, fis_gRO21, fis_gRO22, fis_gRO23, fis_gRO24 };

FIS_TYPE fis_gIMin[] = { -10, -10 };

FIS_TYPE fis_gIMax[] = { 60, 60 };

FIS_TYPE fis_gOMin[] = { 50 };

FIS_TYPE fis_gOMax[] = { 255 };

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;

    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));

}

void fis_evaluate()

{

    FIS_TYPE fuzzyInput0[] = { 0, 0, 0, 0, 0 };

    FIS_TYPE fuzzyInput1[] = { 0, 0, 0, 0, 0 };

    FIS_TYPE* fuzzyInput[fis_gcI] = { fuzzyInput0, fuzzyInput1, };

    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;

    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);

        }    }}

Ortam sıcaklığı ve Hedef sıcaklığı için değişken çıkışları görebilmek için 2 adet potansiyometre kullanılmıştır. Çıkışa ise 12v dc fan kullanılmıştır.

ard_bulanık_mantık_app

 

Arduino Pwm çıkışı olarak bu değerler bulundu ve fan hızımız bu değerlerde dönüyor. Şimdi bunu Matlabda sanal olarak test edelim ve değerleri karşılaştıralım.

Matlab_bulanık_mantık_1

 

Matlab_bulanık_mantık_2

 

Matlab_bulanık_mantık_3

 

Testimiz başarıyla gerçekleştirilmiştir.

 

Ekrem KELEŞ

Karabük Üniversitesi Mekatronik Mühendisliği Yüksek Lisans Öğrencisi

Buna Benzer Yazılar Göster !
Daha Fazlasını Yükle - Ekrem Keleş
Daha Fazla Göster -  Arduino

3 Yorumlar

  1. abdurrahman ulusoy

    18 Ocak 2017 at 10:11

    çok güzel bir çalışma. ellerinize sağlık… videoda eklerseniz, güzel olur…

    Reply

    • Muhammet Özcan

      Muhammet Özcan

      18 Ocak 2017 at 10:15

      Teşekkür ederiz.Uygulamanın videosu eklenmiştir.

      Reply

  2. claudius

    4 Haziran 2017 at 11:22

    can you give me directory fis_header.h to my email Claudius_sina16@yahoo.com . Thanks

    Reply

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Bak Bakalım ?

Arduino Matlab Simulink Gerçek Zamanlı Dc Motor Pwm Kontrolü

  Herkese merhabalar. Bu uygulamada Arduino Mega ve MATLAB & Simulink üzerine bir…