# Introducing the 68HC12 - Oakland University Example 20 Fuzzy Control Lecture L10.2 Fuzzy Control Design of a Fuzzy Controller Fuzzification of inputs MEM and fill_weights() Processing the Rules REV and fire_rules() Output Defuzzification WAV and calc_output() Fuzzy Control Inputs Map to Fuzzy Sets get_inputs(); Fuzzy Rules IF A AND B THEN L fire_rules(); * * Defuzzification Output find_output(); Plexiglas tube Ping-pong ball Problem: Maintain ping-pong ball floating at a specified height

Ultrasonic transducer Muffin fan Input membership functions for floating ping-pong ball neg_far 1 0 neg_close 50 neg_fast 1 0 zero_pos 100 neg_slow 50 ball_position pos_close 150 zero_speed

100 ball_speed pos_far 200 pos_slow 150 250 pos_fast 200 250 Output membership functions for floating ping-pong ball 1 neg_high 0 neg_low 50 zero_motor 100

motor_power pos_low 150 pos_high 200 250 Fuzzy K-map for floating ping-pong ball ball_speed pos_fast neg_far zero_m ball_position neg_close zero_p neg_low neg_high pos_close pos_far neg_high neg_high pos_slow pos_low

zero_m neg_low neg_high neg_high zero_s pos_high pos_low zero_m neg_low neg_high neg_slow pos_high pos_high pos_low zero_m neg_low pos_high pos_high pos_low

zero_m neg_fast pos_high Example 20: C function calls for a fuzzy controller C Function Call Meaning void fill_weights(unsigned char* weight, Given a crisp input x and membership unsigned char* membx, int num_mem_fncs, functions, membx, fill the corresponding weight char x); array. void fire_rules(unsigned char* inout_array, Given inout_array containing weight arrays and unsigned char* rules, unsigned char* out, a set of rules, fire all rules and fill the out array. int numout); unsigned char calc_output(unsigned char* Calculate crisp output given the out array and out, unsigned char* cent, int numout); the output membership singletons, cent. Fuzzy Control Design of a Fuzzy Controller Fuzzification of inputs MEM and fill_weights() Processing the Rules REV and fire_rules() Output Defuzzification WAV and calc_output()

A membership function is defined in terms of u1, u2, u3, and u4 wt 1 slope_2 slope_1 u1 u2 u3 u4 Data structure used by the HCS12 MEM instruction A xi weight(j) X --> point_1 point_2 slope_1 slope_2 Y --> Y + 1 --> X + 4 --> wt 1

point_1 u1 u2 point_2 slope_2 slope_1 u3 u4 static int maxsize = 20; void main(void) { // input membership functions const unsigned char ball_position[] = { 0, 0, 30, 60, // neg_far 40, 60, 80,110, // neg_close 90,120,135,165, // zero_pos 150,175,185,220, // pos_close 200,220,255,255 // pos_far }; unsigned char memb_pos;

neg_far 1 0 1 neg_close 50 zero_pos 100 ball_position pos_close 150 pos_far 200 get_slopes(ball_position,memb_pos,maxsize); neg_fast neg_slow zero_speed pos_slow 250 pos_fast

1 const unsigned char ball_speed[] = { neg_far0, zero_pos 0, neg_close 20, 60, // pos_close neg_fast 35, 60, 80,110, // neg_slow 80,130,130,180, // zero_speed 155,175,185,215, // pos_slow 195,220,255,255 // pos_fast }; 0 50 unsigned char neg_fast 1 0 100 ball_position memb_speed; neg_slow

50 150 zero_speed 100 ball_speed 200 pos_slow 150 get_slopes(ball_speed,memb_speed,maxsize); pos_far 250 pos_fast 200 250 void get_slopes(const unsigned char ball[],unsigned char memb[], int maxsize) { int j; unsigned char diff; for(j = 0; j < maxsize; j=j+4){ memb[j] = ball[j]; // point_1 memb[j+1] = ball[j+3];

// point_2 diff = (ball[j+1] - ball[j]); if(diff == 0) memb[j+2] = 0; else memb[j+2] = 255/diff; // slope_1 diff = (ball[j+3] - ball[j+2]); if(diff == 0) memb[j+3] = 0; else memb[j+3] = 255/diff; // slope_2 } } A xi wt 1 weight(j) X --> X + 4 --> point_1 point_2 slope_1 slope_2 Y --> Y + 1 --> slope_2

slope_1 u1 u2 u3 u4 Example 20: C function calls for a fuzzy controller C Function Call Meaning void fill_weights(unsigned char* weight, Given a crisp input x and membership unsigned char* membx, int num_mem_fncs, functions, membx, fill the corresponding weight char x); array. void fire_rules(unsigned char* inout_array, Given inout_array containing weight arrays and unsigned char* rules, unsigned char* out, a set of rules, fire all rules and fill the out array. int numout); unsigned char calc_output(unsigned char* Calculate crisp output given the out array and out, unsigned char* cent, int numout); the output membership singletons, cent. A xi weight(j) X --> point_1 point_2

slope_1 slope_2 Y --> Y + 1 --> // The fuzzy controller X + 4 --> while(1) { // x1 = get_position(); // (user defined) x1 = 100; // test case -- remove fill_weights(ptr_weight_pos,ptr_memb_pos,num_memb_pos,x1); // x2 = get_speed(); // (user defined) x2 = 150; // test case -- remove fill_weights(ptr_weight_speed,ptr_memb_speed,num_memb_speed,x2); Fuzzy Control Design of a Fuzzy Controller Fuzzification of inputs MEM and fill_weights() Processing the Rules REV and fire_rules() Output Defuzzification WAV and calc_output() Pseudocode for fire_rules() fire_rules() clear out array; for j = 1, num_rules {

min_wt = 1; for i = 1, num_inputs { wt = weighti[Aij] if wt < min_wt min_wt = wt; } out[Lj] = MAX(Out[Lj], min_wt); } The HCS12 REV Instruction Y neg_far 0 neg_close 1 zero_pos 2 pos_close 3 pos_far 4 neg_fast 5 neg_slow 6 zero_speed 7 pos_slow 8 pos_fast 9 neg_high 10 neg_low 11 zero_m 12 pos_low 13 pos_high 14 inout_array ----------0 0 0 0 0

weight_pos[] X weight_speed[] rules 0 5 FE 15 FE 0 6 FE 15 FE x1 is neg_far x2 is neg_fast y is pos_high x1 is neg_far x2 is neg_slow y is pos_high Out[] A = \$FF 11 FF end of rules if x1 is neg_far and x2 is neg_fast then y is pos_high

Fuzzy K-map inout_array[] indicies ball_speed pos_fast 9 pos_slow 8 zero_speed 7 neg_slow 6 neg_fast 5 neg_far 0 zero_motor 12 pos_low 13 pos_high 14 pos_high 14 pos_high 14 ball_position neg_close zero_p 1 2 neg_low neg_high

11 10 zero_motor neg_low 12 11 pos_low zero_motor 13 12 pos_high pos_low 14 13 pos_high pos_high 14 14 pos_close 3 neg_high 10 neg_high 10 neg_low 11 zero_motor 12 pos_low 13 pos_far 4 neg_high 10 neg_high

10 neg_high 10 neg_low 11 zero_motor 12 unsigned 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // 0, // }; char inout_array[] = { weight_pos[] 0 neg_far 1 neg_close Y neg_far 0 2 zero_pos neg_close 1 zero_pos 2 3 pos_close pos_close 3 4 pos_far

pos_far 4 neg_fast 5 weight_speed[] 5 neg_fast neg_slow 6 6 neg_slow zero_speed 7 pos_slow 8 7 zero_speed pos_fast 9 8 pos_slow neg_high 10 9 pos_fast neg_low 11 zero_m 12 out[] 10 neg_high pos_low 13 11 neg_low pos_high 14 12 zero_motor 13 pos_low 14 pos_high inout_array ----------0 0 0 0 0 weight_pos[] weight_speed[] Out[]

A= unsigned char rules[] = { 0,5,0xFE,14,0xFE, // if x1 is neg_far && x2 is neg_fast then y is pos_high 0,6,0xFE,14,0xFE, 0,7,0xFE,14,0xFE, 0,8,0xFE,13,0xFE, 0,9,0xFE,12,0xFE, 1,5,0xFE,14,0xFE, // if x1 is neg_close && x2 is neg_fast then y is pos_high 1,6,0xFE,14,0xFE, 1,7,0xFE,13,0xFE, 1,8,0xFE,12,0xFE, 1,9,0xFE,11,0xFE, 2,5,0xFE,14,0xFE, // if x1 is zero_pos && x2 is neg_fast then y is pos_high 2,6,0xFE,13,0xFE, 2,7,0xFE,12,0xFE, 2,8,0xFE,11,0xFE, 2,9,0xFE,10,0xFE, 3,5,0xFE,13,0xFE, // if x1 is pos_close && x2 is neg_fast then y is pos_low 3,6,0xFE,12,0xFE, 3,7,0xFE,11,0xFE, 3,8,0xFE,10,0xFE, 3,9,0xFE,10,0xFE, 4,5,0xFE,12,0xFE, // if x1 is pos_far && x2 is neg_fast then y is zero_motor 4,6,0xFE,11,0xFE, 4,7,0xFE,10,0xFE, 4,8,0xFE,10,0xFE, 4,9,0xFE,10,0xFF }; unsigned char* ptr_memb_pos;

unsigned char* ptr_memb_speed; unsigned char* ptr_weight_pos; unsigned char* ptr_weight_speed; unsigned char* ptr_inout_array; unsigned char* ptr_out; unsigned char* ptr_rules; unsigned char x1; // input x1 unsigned char x2; // input x2 unsigned char y; // output y ptr_memb_pos = memb_pos; ptr_memb_speed = memb_speed; ptr_weight_pos = inout_array; ptr_weight_speed = inout_array+num_memb_pos; ptr_inout_array = inout_array; ptr_out = inout_array+num_memb_pos+num_memb_speed; inout_array rules ptr_rules = rules; Y neg_far 0 -weight_pos[] X 0 neg_close 1 zero_pos 2 pos_close 3 pos_far 4 neg_fast 5 neg_slow 6 zero_speed 7 pos_slow 8 pos_fast 9 neg_high 10

neg_low 11 zero_m 12 pos_low 13 pos_high 14 ---------0 0 0 0 0 weight_speed[] 5 FE 15 FE 0 6 FE 15 FE x1 is neg_far x2 is neg_fast y is pos_high x1 is neg_far x2 is neg_slow y is pos_high Out[] A = \$FF 11 FF

end of rules Example 20: C function calls for a fuzzy controller C Function Call Meaning void fill_weights(unsigned char* weight, Given a crisp input x and membership unsigned char* membx, int num_mem_fncs, functions, membx, fill the corresponding weight char x); array. void fire_rules(unsigned char* inout_array, Given inout_array containing weight arrays and unsigned char* rules, unsigned char* out, a set of rules, fire all rules and fill the out array. int numout); unsigned char calc_output(unsigned char* Calculate crisp output given the out array and out, unsigned char* cent, int numout); the output membership singletons, cent. // The fuzzy controller while(1) { // x1 = get_position(); // (user defined) x1 = 100; // test case -- remove fill_weights(ptr_weight_pos,ptr_memb_pos,num_memb_pos,x1); // x2 = get_speed(); // (user defined) x2 = 150; // test case -- remove fill_weights(ptr_weight_speed,ptr_memb_speed,num_memb_speed,x2); fire_rules(ptr_inout_array,ptr_rules,ptr_out,num_memb_motor); Fuzzy Control

Design of a Fuzzy Controller Fuzzification of inputs MEM and fill_weights() Processing the Rules REV and fire_rules() Output Defuzzification WAV and calc_output() Pseudocode for find_output() find_output() numer = 0; denom = 0; for k = 1, Q if out[k] != 0 { numer = numer + out[k]*cent[k]; denom = denom + out[k]; } y0 = numer/denom; HCS12 WAV instruction computes numer and denom // output membership functions unsigned char cent[] = { 5,65,128,175,22 }; 1 neg_high 0 neg_low

50 zero_motor 100 motor_power unsigned char* ptr_cent; unsigned char y; ptr_cent = cent; pos_low 150 pos_high 200 250 // output y Example 20: C function calls for a fuzzy controller C Function Call Meaning void fill_weights(unsigned char* weight, Given a crisp input x and membership unsigned char* membx, int num_mem_fncs, functions, membx, fill the corresponding weight char x); array. void fire_rules(unsigned char* inout_array, Given inout_array containing weight arrays and unsigned char* rules, unsigned char* out,

a set of rules, fire all rules and fill the out array. int numout); unsigned char calc_output(unsigned char* Calculate crisp output given the out array and out, unsigned char* cent, int numout); the output membership singletons, cent. // The fuzzy controller while(1) { // x1 = get_position(); // (user defined) x1 = 100; // test case -- remove fill_weights(ptr_weight_pos,ptr_memb_pos,num_memb_pos,x1); // x2 = get_speed(); // (user defined) x2 = 150; // test case -- remove fill_weights(ptr_weight_speed,ptr_memb_speed,num_memb_speed,x2); fire_rules(ptr_inout_array,ptr_rules,ptr_out,num_memb_motor); y = calc_output(ptr_out,ptr_cent,num_memb_motor); // adjust_motor(y): // (user defined) } }