Fuzzy Logic

MisterBill2

Joined Jan 23, 2018
27,522
So have you some known reason for implying that FL will have more errors in controlling a drone's flight as compared to PID?
Or are you just pontificating as usual?
According to Goggle AI:
Yes, drone software utilizes fuzzy logic to make robust, real-time navigational and control decisions. It is particularly valuable for handling dynamic, unpredictable environments—such as turbulent wind, sudden obstacles, or landing on a moving platform—without requiring highly complex mathematical models
My thinking has been that more precise might matter.
BUT the AI statement makes sense. I might not have considered everything involved, since I AM NOT a pilot, nor have I had any pilot training.
Was that critical remark really required??
 

cmartinez

Joined Jan 17, 2007
8,762
While the "precise" term might be debatable, I am under the impression that PID can be considerably faster than fuzzy logic. Is that debatable too?
 

crutschow

Joined Mar 14, 2008
38,508
I am under the impression that PID can be considerably faster than fuzzy logic. Is that debatable too?
Perhaps if PID is done in the analog domain, but Fuzzy Logic generally takes less digital processing power to do the series of IF-THEN-ELSE statements in the feedback-loop, than to do the high-precision, feedback-loop differentiation and integration PID mathematical calculations in the digital domain.

I don't think may mechanical system control loops are done in the analog domain anymore.
 
Last edited:

MisterBill2

Joined Jan 23, 2018
27,522
In the post that started this assault, I was hoping to suggest caution, including verification. I was NOT INTENDING to suggest inherent problems. Consider that in a lot of air-flight, many decisions are life-critical. That is, one COULD make a choice that is DEAD WRONG. THAT was the point of caution I wanted to present.
 

cmartinez

Joined Jan 17, 2007
8,762
Another issue I think could be important (at least for small drones) with PID is that, in general, it could be more power hungry than using MCU's. I think
 

MisterBill2

Joined Jan 23, 2018
27,522
The FAA has made quite a big deal about the hazards to humans from drone flying. That was not my statement, it was theirs. I think that the FAA knows all about flight hazards. Sorrythat I did not give the source for my opinion.

I have designed a few PID based control systems, and certainly some of tthem consumed power . In every case, adequate accurate control was the primary goal.
 
Last edited:

nsaspook

Joined Aug 27, 2009
16,325
https://github.com/nsaspook/mandm

https://github.com/nsaspook/mandm/blob/master/mandm/mandm8722.c
C:
int16_t track_motor(void)
{ // move motor feedback pot/encoder to setpoint
    static float deadband = 0.0;
    static int16_t was_running = FALSE, old_error = 0;
    uint8_t track_knob_to_pot, PERFECT = FALSE;
    uint8_t menu_pos;

    if (mode.free || mode.on_off_only || (mode.info_only)) return MERR_INV;

    track_knob_to_pot = knob_to_pot; // set the local version
    motordata[track_knob_to_pot].hunt_count = 0;
    checktime_track(TRACK_TIMEOUT, TRUE);
    if (motordata[track_knob_to_pot].pot.cal_failed) {
        if (!is_led_blinking(TEST_LED)) blink_led(TEST_LED, TRUE);
    } else {
        if (is_led_blinking(TEST_LED)) blink_led(TEST_LED, FALSE);
    }

    do { // move the assy/motor into the setting position
        check_cable(&menu_pos); // check DIPSW and set the menu_pos if needed
        if (menu_pos == cable_type) { // exit do loop if control cable is disconnected
            LED_3 = LOW;
            mode.free = TRUE;
            update_lcd_menu(menu_pos);
            return 2;
        }
        ADC_read();
        nav_menu();

        if (motordata[track_knob_to_pot].hunt_count > HUNT_MAX) { // adjust position deadband
            deadband = DEADB_HUNT;
        } else {
            if (motordata[track_knob_to_pot].run) {
                deadband = DEADB_RUN; // narrow deadband  when motor running
            } else {
                deadband = DEADB_STOP; // normal deadband when stopped
                if (knob2.movement != STOP) {
                    deadband = DEADB_KNOB;
                }
            }
        }

        if (mode.qei) { // shift gears in encoder mode
            if (ABSL(motordata[track_knob_to_pot].pot.error) > QEI_FAST) {
                if (DRIVE_V24 == LOW) {
                    POWER_X = LOW;
                    wdttime(RELAYRUNF); // wait for .5 seconds.
                    motordata[track_knob_to_pot].v24 = TRUE;
                    DRIVE_V24 = HIGH;
                    mode.v24 = TRUE;
                    if (TLOG) putrs2USART("\x1b[7m 24 volt drive \x1b[0m\r\n");
                    POWER_X = HIGH;
                }
            } else {
                if (DRIVE_V24 == HIGH) {
                    POWER_X = LOW;
                    wdttime(RELAYRUNF); // wait for .5 seconds.
                    motordata[track_knob_to_pot].v24 = FALSE;
                    DRIVE_V24 = LOW;
                    mode.v24 = FALSE;
                    if (TLOG) putrs2USART("\x1b[7m 5 volt drive \x1b[0m\r\n");
                    POWER_X = HIGH;
                }
            }
            if (ABSL(motordata[track_knob_to_pot].pot.error) > QEI_VERY_FAST) {
                if (POWER_S == LOW) {
                    if (DRIVE_V24 == HIGH) {
                        mode.slow_bypass = TRUE;
                        if (TLOG) putrs2USART("\x1b[7m Slowing resistor is off \x1b[0m\r\n");
                        POWER_S = HIGH;
                    }
                }
            } else {
                if (POWER_S == HIGH) {
                    if (DRIVE_V24 == HIGH) {
                        mode.slow_bypass = FALSE;
                        if (TLOG) putrs2USART("\x1b[7m Slowing resistor is on \x1b[0m\r\n");
                        POWER_S = LOW;
                    }
                }
            }
        }

        if ((motordata[track_knob_to_pot].pot.error > (int16_t) ((float) TRACK_DB_L / deadband)) && (motordata[track_knob_to_pot].pot.error < (int16_t) ((float) TRACK_DB_H / deadband))) {
            if (PERFECT && mode.qei) {
                if (was_running) {
                    deadband = DEADB_STOP; // normal deadband when stopped
                    if (TLOG) {
                        sprintf(bootstr2, " In QEI deadband, Error %3i, SLOW Flag %1i, SLOW Relay %i, Total Hunts %i \r\n", motordata[track_knob_to_pot].pot.error, motordata[track_knob_to_pot].slow, (int16_t) POWER_S, motordata[track_knob_to_pot].hunt_count);
                        puts2USART(bootstr2);
                    }
                }
                motor_control(&motordata[track_knob_to_pot]);
                if (qei1.movement == STOP) {
                    motordata[track_knob_to_pot].run = FALSE;
                    if (was_running) {
                        deadband = DEADB_STOP; // normal deadband when stopped, so adjust it now
                        if (knob2.movement != STOP) {
                            deadband = DEADB_KNOB;
                        }
                        if (TLOG) {
                            sprintf(bootstr2, " QEI stopped, Error %3i, SLOW Flag %1i, SLOW Relay &i, Total Hunts %i ", motordata[track_knob_to_pot].pot.error, motordata[track_knob_to_pot].slow, (int16_t) POWER_S, motordata[track_knob_to_pot].hunt_count);
                            puts2USART(bootstr2);
                            putrs2USART("\x1b[7m Motor Stopped. \x1b[0m\r\n");
                        }
                        was_running = FALSE;
                        LED_3 = LOW;
                    }
                }
            } else {
                motordata[track_knob_to_pot].run = FALSE;
                motor_control(&motordata[track_knob_to_pot]);
                if (was_running) {
                    deadband = DEADB_STOP; // normal deadband when stopped, so adjust it now
                    if (knob2.movement != STOP) {
                        deadband = DEADB_KNOB;
                    }
                    if (TLOG) {
                        sprintf(bootstr2, " %i Error %3i, SLOW Flag %1i, SLOW Relay %i, Total Hunts %i ", track_knob_to_pot, motordata[track_knob_to_pot].pot.error, motordata[track_knob_to_pot].slow, (int16_t) POWER_S, motordata[track_knob_to_pot].hunt_count);
                        puts2USART(bootstr2);
                        putrs2USART("\x1b[7m Motor Stopped. \x1b[0m\r\n");
                    }
                    was_running = FALSE;
                    LED_3 = LOW;
                }
            }
        }

        if (motordata[track_knob_to_pot].pot.error > (int16_t) ((float) TRACK_DB_H / deadband)) { // check knob position
            motordata[track_knob_to_pot].run = TRUE;
            was_running = TRUE;
            if (!motordata[track_knob_to_pot].cw) {
                motordata[track_knob_to_pot].hunt_count++;
                if (motordata[track_knob_to_pot].hunt_count > 1) V.hunt_count++;
            }
            motordata[track_knob_to_pot].cw = TRUE;
            LED_3 = HIGH;
            motor_control(&motordata[track_knob_to_pot]);
            if ((old_error != motordata[track_knob_to_pot].pot.error) && (ABSL(motordata[track_knob_to_pot].pot.error) > TRACK_DISPLAY)) {
                if (TLOG) {
                    sprintf(bootstr2, " %i Error %3i, SLOW Flag %1i, SLOW Relay %i, Hunts %i ", track_knob_to_pot, motordata[track_knob_to_pot].pot.error, motordata[track_knob_to_pot].slow, POWER_S, motordata[track_knob_to_pot].hunt_count);
                    puts2USART(bootstr2);
                    putrs2USART("\x1b[7m Motor CW. \x1b[0m\r\n");
                }
                old_error = motordata[track_knob_to_pot].pot.error;
            }
        }
        if (motordata[track_knob_to_pot].pot.error < (int16_t) ((float) TRACK_DB_L / deadband)) { // check knob position
            motordata[track_knob_to_pot].run = TRUE;
            was_running = TRUE;
            motordata[track_knob_to_pot].cw = FALSE;
            LED_3 = HIGH;
            motor_control(&motordata[track_knob_to_pot]);
            if ((old_error != motordata[track_knob_to_pot].pot.error) && (ABSL(motordata[track_knob_to_pot].pot.error) > TRACK_DISPLAY)) {
                if (TLOG) {
                    sprintf(bootstr2, " %i Error %3i, SLOW Flag %1i, SLOW Relay %i, Hunts %i ", track_knob_to_pot, motordata[track_knob_to_pot].pot.error, motordata[track_knob_to_pot].slow, POWER_S, motordata[track_knob_to_pot].hunt_count);
                    puts2USART(bootstr2);
                    putrs2USART("\x1b[7m Motor CCW. \x1b[0m\r\n");
                }
                old_error = motordata[track_knob_to_pot].pot.error;
            }
        }
        if (motordata[track_knob_to_pot].hunt_count > HUNT_LOW) motordata[track_knob_to_pot].slow = TRUE;
        if (motordata[track_knob_to_pot].hunt_count > HUNT_HIGH) motordata[track_knob_to_pot].slow_only = TRUE;
    } while (motordata[track_knob_to_pot].run && !button.B0 && !button.B1 && !button.B2 && !checktime_track(TRACK_TIMEOUT, FALSE));
    if (mode.qei) {
        mode.slow_bypass = FALSE;
        DRIVE_V24 = LOW;
        mode.v24 = FALSE;
    }
    if (checktime_track(TRACK_TIMEOUT, FALSE)) {
        if (TLOG) putrs2USART("\x1b[7m Motor movement TIMED OUT, setting knob position to motor position. \x1b[0m\r\n");
        if (mode.qei) knob2.c = qei1.c; // sync stopped position for timeout
        buzzer_ticks(1);
        return 4;
    }
    if (button.B0 || button.B1 || button.B2) {
        if (TLOG) putrs2USART("\x1b[7m Motor movement Button Interrupt, setting knob position to motor position. \x1b[0m\r\n");
        if (mode.qei) knob2.c = qei1.c; // sync stopped position for INTERRUPT
        if (button.B0) {
            button.B0 = LOW;
            mode.free = TRUE;
            LED_3 = LOW;
        }
        //        Clear_All_Buttons();
        return MERR_INT;
    }
    return MOK;
}
https://forum.allaboutcircuits.com/threads/mandm.75507/#post-531762
 
Last edited:

Irving

Joined Jan 30, 2016
5,123
Playing devil's advocate, I don't think PID precision is necessarily an issue. There are many PID implementations on low-end MCU using purely integer maths and they work fine.

I think the issue is more about dealing with exceptions, ie discontinuities in the 'normal' flow, which might need, for example, a different set of PID parameters to allow for a missing or out-of-range input from a sensor.
 

crutschow

Joined Mar 14, 2008
38,508
Another Fuzzy Logic demo showing the control of an inverted pendulum, which requires a non-linear control loop:

<iframe width="560" height="315" src="
" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
 
Last edited:

nsaspook

Joined Aug 27, 2009
16,325
I would assume that SpaceX uses fuzzy logic instead of PID for landing their rockets?
I'm sure they use everything in the right places. The trick is knowing where something isn't and calculating the deviance. Deviance is king but solid sensors and activation is the OG.
https://www.eng.cam.ac.uk/news/alumni-stories-meet-principal-rocket-landing-engineer-spacex

Why did you become an engineer?

I always loved building things, especially electronic devices, and I had really great teachers at school that encouraged this. Even my fellow students started to appreciate what I could do after I invented the ‘Teacher Detector’, which used a pressure pad to give advance warning of when a teacher was approaching.
 
Last edited:

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
30,661
I'm sure they use everything in the right places. The trick is knowing where something isn't and calculating the deviance. Deviance is king but solid sensors and activation is the OG.
https://www.eng.cam.ac.uk/news/alumni-stories-meet-principal-rocket-landing-engineer-spacex

Why did you become an engineer?

I always loved building things, especially electronic devices, and I had really great teachers at school
I think many start off young without really realizing it, IIRC, I was around 8yrs old when my journey & paasion into electrics started..!
Later my other developed passion was fine woodworking, which became a hobby that covered furniture to boat building.
 
Last edited:

MisterBill2

Joined Jan 23, 2018
27,522
I became an engineer because even from a very early age I was interested in how things worked. After I would take a toy apart to see how it worked, I would put it back together so that I could play with it, because a taken-apart toy is not any fun. And I learned early that snap-together assembly toys are intentionally made to break unless taken apart very carefully. That kind of thinking was engineering long before engineering school.
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
30,661
I too dismantled just about every toy I had, back in those days many kids toy items were made out of pressed tin sheet.
I recall a few that on the inside showed thet some were originally canned food containers!!
It was war time after all !! :oops:

Bit of a stray from 'Fuzzy Logic" ?:rolleyes:
 
Top