微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PI 控制器线程和奇怪的问题

如何解决PI 控制器线程和奇怪的问题

我将旋转编码器连接到直流电机轴上,希望在 PI4 上创建一个 python 脚本,在其中可以设置所需的角度,电机将以 10 的占空比顺时针移动,电机将停止并将位置保持在所需的角度,一旦设置的角度从旋转编码器读回代码(@每转 800 个脉冲 - 读出 0.45 度增量)。

理想情况下,PI 控制器将保持设定的角度(在代码中设置,但在以后的 GUI 中设置)并且无论轴上的外力如何都不会移动。

最后,我在我的 PI 控制信号“PI”进入占空比输出后使用 if 语句,从而控制电机在达到设定点时的速度(减速或加速 tp 到达设定点)与控制方向输出错误 PI 极性......如果可以做得更好,我会很感激任何建议

我只遇到了 1 个我无法弄清楚的错误,也无法在线找到解决方案...但我觉得我已经接近正确地获取代码了。欢迎任何批评。错误与 Pi 方程的“PI”输出有关:

“int 类型的值不可索引”

from RPi import GPIO
import time
import threading



#Encoder GPIO Pins

clk = 15 #  GRN/YLW Z+
dt = 11 # BLU/GRN Z-

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(clk,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(dt,pull_up_down=GPIO.PUD_DOWN)


#Motor GPIO Pins
PWMPin = 18 # PWM Pin connected to ENA.
Motor1 = 16 # Connected to Input 1.
Motor2 = 18 # Connected to Input 2.

GPIO.setup(PWMPin,GPIO.OUT) # We have set our pin mode to output
GPIO.setup(Motor1,GPIO.OUT)
GPIO.setup(Motor2,GPIO.OUT)

GPIO.output(Motor1,GPIO.LOW)# When program start then all Pins will be LOW.
GPIO.output(Motor2,GPIO.LOW)


def MotorClockwise():
    GPIO.output(Motor1,GPIO.LOW) # Motor will move in clockwise direction.
    GPIO.output(Motor2,GPIO.HIGH)
   
    
def MotorAntiClockwise():
    GPIO.output(Motor1,GPIO.HIGH) # Motor will move in anti-clockwise direction.
    GPIO.output(Motor2,GPIO.LOW)
   
#Sim Values

duty_c = 10 #duty Cycle
PwmValue = GPIO.PWM(PWMPin,10000) # We have set our PWM frequency to 5000.
PwmValue.start(duty_c) # That's the maximum value 100 %.

error = 0
Set_point = 1.8
encoder_counter = 0
encoder_angle = 0
Kp = 2
Ki = 1
PI = 0

#Sim Parameters
Ts = .1 #sampling time
Tstop = 200 #end simulation time
N = int(Tstop/Ts)#simulation length


def ReadEncoder():

    global encoder_counter
    global encoder_angle
    clkLastState = GPIO.input(clk)

    while True:
        clkState = GPIO.input(clk)
        dtState = GPIO.input(dt)
        encoder_angle = float(encoder_counter/800)*360
 
        if clkState != clkLastState:
            if dtState != clkState:
                encoder_counter += 1
            else:
                encoder_counter -= 1
                
            #print("encoder_counter",encoder_counter )
            print("encoder_angle",encoder_angle )
            time.sleep(1) 
            
        clkState = clkLastState
        # some delay needed in order to prevent too much cpu load,# however this will limit the max rotation speed detected
        time.sleep(.001)                           
                


def PI_function():
    
    global PI
    global duty_c
    global error
    global Kp
    global Ki
    global encoder_angle
    
    for k in range(N+1):
    
        error = int(Set_point) - encoder_angle
        print (f"{error} Error Detected")

        PI = PI[k-1] + KP*(error[k] - error[k-1]) + (Kp/Ki)*error[k] #PI equation
        print (f"{PI} PI value")
        
    if (PI > 0):
        MotorClockwise()
    else:
        MotorAntiClockwise()
        
    if ((PI > duty_c) & (duty_c <100)):
        duty_c += 1
    if ((PI < duty_c) & (duty_c > 10)):
        duty_c -= 1
        
    return()


def main_function():
    
    if (N != 0):
        
        encoder_thread = threading.Thread( target=ReadEncoder)
        encoder_thread.start()
        encoder_thread.join()

        PI_thread = threading.Thread( target=PI_function)
        PI_thread.start()
        PI_thread.join()
        
        PwmValue.ChangeDutyCycle(duty_c)
        
    else:
        
        PwmValue.ChangeDutyCycle(0)
        print(f"Motor Stopped & Holding at {encoder_angle} degrees")
        

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。