Fuzzy Logic Controller

Hello Everybody

 

I want to design a Fuzzy logic controller to control two  DC motors of Rover robot  , actually I made a simulation for the controller in matlab/simulink and it worked successfully , now I want to design that controller in real world by using Arduino Uno board , actually I converted the MATLAB Fuzzy Inference System FIS to Arduino C by Converter in the "www.makeproto.com" website .

 

Now for example if one of rules base of fuzzy controller is 

 

if (HeadingAngle is Zero) and (Front_Sonser is Near) and (Right_Sonser is Near) and (Left_Sonser is Far) then (Wr is Turn_Small_Negative) and (Wl is Turn_Small_Positive) 

 

Wr=angular velocity of right wheel (Right motor) 

Wl=angular velocity of left wheel (left motor) 

the membership functions of Wr and Wl in the simulation range from (-100 to 100) 

 

Now if we supposed that the value of "Turn_Small_Negative" in the rule above is -20 and "Turn_Small_Positive" is 30 .

How Could I make the two motors to spin in the given values from fuzzy controller ? 

Are the two outputs (Wr,Wl) of fuzzy control connected to driver board  298 and then directly from driver board outputs to DC motors of robot  ?

 

Actually , While I am looking for the concerning websites I found out some terms related with such problem but I didn't completely understand that 

 

terms like :

 

"Need to PWM the mapped 0-255 value to the 298's EN pin with an analogWrite."

"Need to set the pair of outputs to hi/lo or lo/hi ".

First, you have to map the
First, you have to map the outputs into a linear function. It sounds like they are being mapped into -100 to 100.

I’m assuming that Turn_Small_Positive is mapped to perhaps 10, while Turn_Small_Negative is mapped to -10. Perhaps they are other numbers, but you didn’t say.

The call to set the PWM on the Arduino is analogWrite(pin, value).

Pin is the output pin, and value is between 0 to 255.

For a motor controller I’m also assuming that you have a pin set to control direction. So for negative you’ll set it to one state and positive another state.

Then you’ll have to convert the 0-100 value (call this fuzzyValue) to a 0-255 value (call this PWMValue), basically by multiplying fuzzyValue by 2.55.

Does this make sense?

.

thanks

** Thanks a lot**

 

Thanks a lot  DangerousThing 

Actually , after I have read your post I wrote this pseudo code and I don’t if it will goes right or not , so what do you think ?

 

</p><p>&nbsp;</p><p>int ENA=2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //connected to Arduino's port 2 &nbsp;speedPinA</p><p>int IN1=3; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //connected to Arduino's port 3</p><p>int IN2=4; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //connected to Arduino's port 4</p><p>int ENB=5; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//connected to Arduino's port 5 &nbsp;speedPinB</p><p>int IN3=6; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //connected to Arduino's port 6</p><p>int IN4=7; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//connected to Arduino's port 7</p><p>&nbsp;</p><p>&nbsp;</p><p>void setup()</p><p>{</p><p>&nbsp;pinMode(ENA,OUTPUT);</p><p>&nbsp;pinMode(ENB,OUTPUT);</p><p>&nbsp;pinMode(IN1,OUTPUT);</p><p>&nbsp;pinMode(IN2,OUTPUT);</p><p>&nbsp;pinMode(IN3,OUTPUT);</p><p>&nbsp;pinMode(IN4,OUTPUT);</p><p>&nbsp;digitalWrite(ENA,HIGH); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //enable motorA</p><p>&nbsp;digitalWrite(ENB,HIGH); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //enable motorB</p><p>}</p><p>&nbsp;</p><p>&nbsp;</p><p>void loop()</p><p>{</p><p>&nbsp;</p><p>&nbsp;</p><p>WL=g_fisOutput[0] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Where &nbsp;' g_fisOutput[0] ' is the output of the fuzzy control (FIS) for left angular velocity after conversion in &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"www.makeproto.com"</p><p>WR=g_fisOutput[1] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Where &nbsp;' g_fisOutput[1] ' is the output of the fuzzy control (FIS) for right angular velocity after conversion in &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"www.makeproto.com"</p><p>&nbsp;</p><p>&nbsp;</p><p>WL = map(WL, -100, 100, 0, 255); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// mapping &nbsp;from &nbsp;(-100 to 100) into (0 to 255)&nbsp;</p><p>&nbsp;</p><p>if (WL &lt; 1)</p><p>{</p><p>&nbsp; digitalWrite(IN1,high) &amp;&amp; digitalWrite(IN2, low) &nbsp; &nbsp; &nbsp; // IN1 goes directly to out1 in driver board 298</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // and IN2 goes directly to out2 in the driver board 298</p><p>&nbsp; analogWrite (ENA, WL); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</p><p>} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p><p>&nbsp;</p><p>else if (WL &gt; 1)&nbsp;</p><p>{</p><p>&nbsp; digitalWrite(IN1,low) &amp;&amp; digitalWrite(IN2, high)</p><p>&nbsp;</p><p>&nbsp; analogWrite (ENA, WL); &nbsp;</p><p>}</p><p>&nbsp;</p><p>&nbsp;</p><p>WR = map(WR, -100, 100, 0, 255); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // mapping &nbsp;from &nbsp;(-100 to 100) into (0 to 255)&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>if (WR &lt; 1)</p><p>&nbsp;</p><p>{</p><p>&nbsp; digitalWrite(IN3,high) &amp;&amp; digitalWrite(IN4, low) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // IN3 goes directly to out3 in driver board 298&nbsp;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // and IN4 goes directly to out4 in the driver board 298</p><p>&nbsp;analogWrite (ENB, WR); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</p><p>} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</p><p>else if (WR &gt; 1) &nbsp;</p><p>{</p><p>&nbsp; digitalWrite(IN3,low) &amp;&amp; digitalWrite(IN4, high)</p><p>&nbsp;</p><p>&nbsp;analogWrite (ENB, WR); &nbsp;&nbsp;</p><p>}</p><p>&nbsp;</p><p>&nbsp;</p><p>}</p><div>

Your map() function is off.
Your map() function is off. You are trying to map from the absolute value of the MatLab variable to 0-255.

int mappedWR = map(abs(WR), 0, 100, 0, 255);

Then you change the analogWrite functions to use mappedWR – and the same thing with mappedWL.

The other problem I see is that you need to handle the case where WL == 0. I would just make the positive case if (WL >= 0).

So far so good.

I have written a function just for this scenario.

http://pastebin.com/EXGjMNrz

Hopefully there are sufficient comments. If that is not the case please let me know.

Thanks a lot DangerousThing

Thanks a lot DangerousThing , actually I took these tips in consideration .

Map function still wrong
The PWM signal to the motor controller doesn’t matter if the motor is going forward or reverse. That is why you want to map the absolute value of WL or WR to the PWM signal, so you also have to map 0-100 to 0-255. Since you’ve already (correctly) special cased where WR == 0, your map should be

leftPWM = map(abs(WL), 1, 100, 1, 255);

Does this make sense?

thanks

thanks a lot birdmun .

I re-write that code as follow and I don’t if that wil be right .

 

 

int ENA=2;    // SpeedPinA connected to Arduino’s port 2  

int IN1=3;    // RightMotorWire1 connected to Arduino’s port 3

int IN2=4;    // RightMotorWire2 connected to Arduino’s port 4

int ENB=5;    // SpeedPinB connected to Arduino’s port 5  

int IN3=6;    // LeftMotorWire1 connected to Arduino’s port 6

int IN4=7;    // LeftMotorWire2 connected to Arduino’s port 7

void setup()

{

 pinMode(ENA,OUTPUT);

 pinMode(ENB,OUTPUT);

 pinMode(IN1,OUTPUT);

 pinMode(IN2,OUTPUT);

 pinMode(IN3,OUTPUT);

 pinMode(IN4,OUTPUT);

 digitalWrite(ENA,HIGH);    //enable motorA

 digitalWrite(ENB,HIGH);    //enable motorB

}

WL=g_fisOutput[0]     // Where  ’ g_fisOutput[0] ’ is the output of the fuzzy control (FIS)                        

                                   //for left angular velocity after conversion in "www.makeproto.com"

WR=g_fisOutput[1]     // Where  ’ g_fisOutput[1] ’ is the output of the fuzzy control (FIS)     

                                 //for right angular velocity after conversion in “www.makeproto.com

 

 

 

void roboMove(int WR, int WL, long dlay) {

 

  int rightPWM, leftPWM;

  if (WR > 0) {

    //forward

  digitalWrite(IN1,HIGH)

  digitalWrite(IN2,LOW)

 

  }  else if (WR < 0){

    //reverse

  digitalWrite(IN1,LOW)

  digitalWrite(IN2,HIGH)

  }

 

  if (WR == 0) {

   rightPWM = 0;

   analogWrite(ENA, rightPWM);

  } else {

    rightPWM = map(ABS(WR), -100, 100, 0, 255);

    analogWrite(ENA, rightPWM);

  }

 

 

//--------------------------||-----------------------------\

 

  if (WL > 0) {

     //forward

  digitalWrite(IN3,HIGH)

  digitalWrite(IN4,LOW)

  }  else if (WL < 0) {

     //reverse

  digitalWrite(IN3,LOW)

  digitalWrite(IN4,HIGH)

  }

 

  if (WL == 0) {

    leftPWM = 0;

    analogWrite(ENB, leftPWM);

  } else {

    leftPWM = map(ABS(WL), -100, 100, 0, 255);

    analogWrite(ENB, leftPWM);

  }

 

  delay(dlay);

}