PID Control ลูปที่มีความผิดปกติขนาดใหญ่และคาดเดาไม่ได้


10

คำถามสั้น ๆ
มีวิธีการทั่วไปในการจัดการความผิดปกติที่มีขนาดใหญ่มาก (คำสั่งของขนาด) ภายในขอบเขตการควบคุมเป็นอย่างอื่นหรือไม่?

ความเป็นมา
ฉันกำลังทำงานเกี่ยวกับอัลกอริทึมการควบคุมที่ขับเคลื่อนมอเตอร์ข้ามเขตการควบคุมโดยทั่วไป ด้วยการโหลดแบบไม่มี / ขั้นต่ำตัวควบคุม PID ใช้งานได้ดี (การตอบสนองที่รวดเร็วไม่มากไปหรือน้อยไป) ปัญหาที่ฉันพบคือมักจะมีตำแหน่งโหลดสูงอย่างน้อยหนึ่งแห่ง ตำแหน่งจะถูกกำหนดโดยผู้ใช้ในระหว่างการติดตั้งดังนั้นจึงไม่มีวิธีที่สมเหตุสมผลสำหรับฉันที่จะรู้ว่าเมื่อไร / ที่ไหนที่จะคาดหวัง

เมื่อฉันปรับแต่ง PID เพื่อจัดการกับตำแหน่งโหลดสูงมันจะทำให้เกิดการยิงที่มีขนาดใหญ่กว่าในพื้นที่ที่ไม่ได้โหลด (ซึ่งฉันคาดไว้อย่างเต็มที่) ในขณะที่โอเคที่จะไปเกินระยะกลางการเดินทางจะไม่มีการหยุดแบบกลไกเชิงกลบนกล่องหุ้ม การไม่มีฮาร์ดสต็อปหมายถึงการที่เกินพิกัดที่สำคัญสามารถ / ทำให้แขนควบคุมถูกตัดการเชื่อมต่อจากมอเตอร์ (ทำให้เกิดยูนิตที่ตายแล้ว)

สิ่งที่ฉันสร้างต้นแบบ

  • PID ที่ซ้อนกัน (ก้าวร้าวมากเมื่ออยู่ห่างจากเป้าหมายอนุรักษ์เมื่ออยู่ใกล้)
  • แก้ไขกำไรเมื่ออยู่ห่างไกล, PID เมื่อปิด
  • Conservative PID (ทำงานโดยไม่มีการโหลด) + ตัวควบคุมภายนอกที่มองหา PID เพื่อหยุดการทำงานและใช้พลังงานเพิ่มเติมจนกระทั่งทั้งคู่: บรรลุเป้าหมายหรือตรวจพบอัตราการเปลี่ยนแปลงอย่างรวดเร็ว (เช่นออกจากพื้นที่โหลดสูง)

ข้อ จำกัด

  • กำหนดเดินทางเต็มรูปแบบ
  • ไม่สามารถเพิ่ม Hardstops (ณ เวลานี้)
  • ข้อผิดพลาดจะไม่เป็นศูนย์
  • สามารถรับภาระสูงจากการเดินทางน้อยกว่า 10% (หมายถึงไม่มี "การเริ่มต้นทำงาน")

คำตอบ:


2

การคำนวณข้อผิดพลาดของคุณดูเหมือนจะไม่สะสมข้อผิดพลาดเมื่อทำงานกับคำที่เป็นอนุพันธ์และคุณอาจต้องการแก้ไขสิ่งนี้เนื่องจากมีเพียงคำอนุพันธ์ที่สามารถตอบสนองต่อการเปลี่ยนแปลงอย่างรวดเร็วในกระบวนการ

ถ้าฉันทำให้ถูกต้องรหัสของคุณ

// Determine the error delta
dE = abs(last_error - new_error);
last_error = new_error;

จะคำนวณคำควบคุมเสมอตามข้อผิดพลาดปัจจุบันซึ่งเป็นวิธีดั้งเดิมที่ใช้กับ PID มันดีเพราะคำว่าฉันควรจะดูแลข้อผิดพลาดสะสมอยู่ดี

อย่างไรก็ตามฉันมีลูกค้าที่มาพร้อมกับแนวคิดต่อไปนี้ที่คุณอาจต้องการลอง เนื่องจากคุณมีส่วนหนึ่งของเส้นโค้งกระบวนการที่ต้องการการเปลี่ยนแปลงเชิงรุกมากขึ้นคุณสามารถปล่อยให้แม้แต่ความผิดพลาดของส่วน D ที่จะสะสม:

if(TD)                                                 // Calculate D term
{  
   Last_C += (Error - Last_C) / TD;                    // D term simulates
   Dterm = (Error - Last_C) * KD;                      // capacitor discharging
}
else    
   Dterm = 0;                                          // D term is OFF (TD is 0)

มีสองสิ่งที่น่าสนใจที่ควรทราบที่นี่:

  • ค่า TD ไม่ใช่กำไรจากอนุพันธ์ (ซึ่งคือ KD) แต่เวลาอนุพันธ์ซึ่งเป็นค่าคงที่ของผู้ใช้ซึ่งควบคุมเวลาสำหรับข้อผิดพลาดในการสะสม หากตั้งค่าเป็นศูนย์ส่วน D ของ PID จะถูกปิดใช้งานโดยไม่คำนึงถึงชุดค่าเกนของ KD

  • โปรดทราบว่าข้อผิดพลาดปัจจุบันถูกใช้เพื่อ 'เรียกเก็บเงิน' ค่า Last_C ก่อนนำไปคำนวณในส่วน D ตัวแปร Last_C ทำหน้าที่เหมือนตัวเก็บประจุมันจะสร้างขึ้นในขณะที่ข้อผิดพลาดมีขนาดใหญ่เพื่อให้ส่วนอนุพันธ์ของคุณจะทำหน้าที่ตาม 'ประวัติ' ข้อผิดพลาดล่าสุดและหลังจากนั้น (เมื่อมีข้อผิดพลาดเล็ก) ประวัติศาสตร์นี้ จะคายประจุเหมือนตัวเก็บประจุ

แน่นอนคุณควร จำกัด เอาต์พุตรวมในแบบที่คุณอาจจะทำอยู่แล้ว (การตั้งค่าการป้องกันวินด์อัปอัตโนมัติ bumpless auto ไปเป็น manual transfer และสิ่งอื่น ๆ ตามปกติ)

ฉันสามารถโพสต์รายละเอียดเพิ่มเติมเกี่ยวกับเงื่อนไขอื่น ๆ ของอัลกอริทึม PID ของฉันหากคุณพบว่ามีประโยชน์ แต่คุณอาจต้องการลองนี้และดูว่าเกิดอะไรขึ้น มันให้บริการลูกค้าของฉันดีมาหลายปี


ขอบคุณสำหรับการป้อนข้อมูล ฉันจะลองดูนะ ได้อย่างรวดเร็วดูเหมือนว่าเหมาะสม
Adam Lewis

ฉันเข้าใจแล้วคุณมีส่วนร่วมระยะ D ใน PID 'หลัก' ของคุณบวกกับการตรวจจับคอกใด ๆ ที่นำไปสู่การคำนวณ
Drazen Cika

1
ถูกต้อง. Dterm ของ PID ถูกใช้แม้ว่าจะไม่ก้าวร้าวมากนักในระหว่างการจูน สิ่งที่ทำให้ปัญหานี้ยิ่งยากคือว่าโหลดสามารถทำลายฟรีในมากในช่วงเวลาสั้น ๆ IE เชื่อมโยงถูกปลด การกำจัดแรงอย่างฉับพลันนี้ทำให้เกิดการระเบิดขนาดใหญ่เมื่อมีฟังก์ชั่นการปรับให้เรียบ (ผลรวม) ที่ใช้กับกองกำลังแผงลอย
Adam Lewis

ปัญหาที่ชั่วร้ายมันน่าสนใจที่จะรู้ว่าอัลกอริทึมฟัซซีบางตัวจะจัดการกับปัญหานี้ได้ดีเพียงใด อย่างน้อยคุณก็สามารถสร้างประสบการณ์ที่เกี่ยวข้องกับปัญหาของคุณให้กับอัลกอริทึมมากกว่าที่จะ จำกัด อยู่ภายในโซลูชันมาตรฐาน อย่างไรก็ตามโชคดีกับสิ่งนี้ :-)
Drazen Cika

1

วิธีแก้ปัญหาเบื้องต้น

stalled_pwm_output = PWM / | |E |

PWM = ค่า PWM สูงสุด
ΔE = last_error - new_error

ความสัมพันธ์เริ่มต้นประสบความสำเร็จในการเพิ่มผลผลิต PWM ขึ้นอยู่กับการขาดการเปลี่ยนแปลงของมอเตอร์ ดูกราฟด้านล่างสำหรับผลลัพธ์ตัวอย่าง

วิธีการนี้ใช้สำหรับสถานการณ์ที่ PID ที่ไม่ก้าวร้าวหยุดชะงัก อย่างไรก็ตามมีปัญหาที่โชคร้าย (และชัดเจน) ว่าเมื่อ PID ที่ไม่ก้าวร้าวสามารถบรรลุเป้าหมายได้และพยายามที่จะทำให้ช้าลง ทางลาดนี้ทำให้เกิดการโอเวอร์โหลดขนาดใหญ่เมื่อเดินทางไปยังตำแหน่งที่ไม่ได้โหลด

1 / ΔEเทียบกับΔE

ทางออกปัจจุบัน

ทฤษฎี

stalled_pwm_output = (kE * PID_PWM) / | |E |

kE = การปรับค่าคงที่
PID_PWM = การร้องขอ PWM ปัจจุบันจาก PID ที่ไม่
รุกรานΔE = last_error - new_error

ความสัมพันธ์ปัจจุบันของฉันยังคงใช้แนวคิด 1 / ΔE แต่ใช้เอาต์พุต PID PWM ที่ไม่ก้าวร้าวเพื่อกำหนด stall_pwm_output สิ่งนี้จะช่วยให้ PID เค้นกลับมาที่คอกม้า _pwm_output เมื่อเริ่มเข้าใกล้เป้าหมายที่ตั้งไว้ แต่ยังยอมให้เอาต์พุต PWM 100% เมื่อหยุดทำงาน ต้องการค่าคงที่ kE เพื่อให้แน่ใจว่า PWM เข้าสู่จุดอิ่มตัว (มากกว่า 10,000 ในกราฟด้านล่าง)

รหัสหลอก

โปรดทราบว่าผลลัพธ์จาก cal_stall_pwm ถูกเพิ่มไปยังเอาต์พุต PID PWM ในตรรกะควบคุมปัจจุบันของฉัน

int calc_stall_pwm(int pid_pwm, int new_error)
{
    int ret = 0;
    int dE = 0;
    static int last_error = 0;
    const int kE = 1;

    // Allow the stall_control until the setpoint is achived
    if( FALSE == motor_has_reached_target())
    {
        // Determine the error delta
        dE = abs(last_error - new_error);
        last_error = new_error;

        // Protect from divide by zeros
        dE = (dE == 0) ? 1 : dE;

        // Determine the stall_pwm_output
        ret = (kE * pid_pwm) / dE;
    }

    return ret;
}

ข้อมูลส่งออก

เอาท์พุท PWM แผงลอย เอาท์พุท PWM แผงลอย

โปรดทราบว่าในกราฟเอาต์พุต PWM ที่หยุดทำงานการลดลงของ PWM กระทันหันที่ ~ 3400 เป็นคุณลักษณะด้านความปลอดภัยในตัวที่เปิดใช้งานเนื่องจากมอเตอร์ไม่สามารถไปถึงตำแหน่งได้ภายในเวลาที่กำหนด

เอาต์พุต PWM ที่ไม่โหลด ไม่โหลดเอาต์พุต PWM


1

คุณไม่ได้พูดว่าคุณควบคุมความเร็วมอเตอร์ ... ตำแหน่ง? ไม่ว่ามันจะเป็นอะไรขั้นตอนแรกคือการกำหนดสิ่งที่ผิดพลาดที่ยอมรับได้ ตัวอย่างเช่นหากการควบคุมมีไว้สำหรับความเร็วข้อผิดพลาดสูงสุดที่อยู่ภายใน 1% ของเป้าหมายสามารถตั้งค่าได้ คุณจะไม่สามารถระบุจำนวนความละเอียดที่คุณต้องการสำหรับการนับ ADC หรือ PWM หากไม่มีสิ่งนั้นการชดเชย PID อาจสมบูรณ์แบบ แต่ก็ยังคงมีการ จำกัด วงรอบการแกว่ง

จากนั้นคุณต้องรู้พลวัตของระบบวงเปิด หากปราศจากสิ่งนั้นคุณจะไม่สามารถรู้ได้ว่าอะไรจะเป็นประโยชน์สำหรับส่วนที่เป็นสัดส่วน (P), อินทิกรัล (I), และอนุพันธ์ (D) ของลูป คุณสามารถวัดไดนามิกได้ด้วยขั้นตอนอินพุต (การเปลี่ยนแปลงขั้นตอนในระดับไดรฟ์หรือ PWM) หรือการเปลี่ยนแปลงขั้นตอนในการโหลด (ดูเหมือนว่านี่จะเกี่ยวข้องกับคุณ)

การใช้การเปลี่ยนแปลงข้อผิดพลาดแบบวนไปสู่รอบในส่วนของ algo ส่วนควบคุมของคุณเพื่อแก้ไขค่า PWM ทำให้แน่ใจได้ว่าลูปจะไม่มีการแก้ไข สิ่งนี้ทำให้มั่นใจได้ถึงความผันผวนของรอบการ จำกัด ในการควบคุม ลูกค้าส่วนใหญ่คงไม่ยอมแพ้

ส่วน P ของลูปจะดูแลข้อผิดพลาดทันที (ตอบสนองต่อข้อผิดพลาดทันที) แต่มันจะมีจำนวน จำกัด ดังนั้นข้อผิดพลาดบางอย่างจะถูกทิ้งไว้ ส่วนที่ฉันของวงตอบสนองช้าในช่วงเวลาที่จะใช้กำไรไม่มีที่สิ้นสุด (เวลาที่ไม่มีที่สิ้นสุดสำหรับผลกำไรที่ไม่สิ้นสุด) เพื่อแก้ไขข้อผิดพลาดที่ถูกทิ้งไว้โดยส่วน P

เนื่องจากส่วนของฉันช้ามันอาจหลุดออกจากขั้นตอนการแก้ไขที่จำเป็นสำหรับการลดข้อผิดพลาดแม้ว่าคุณจะได้รับการตั้งค่าที่เหมาะสมแล้วก็ตาม ดังนั้นมันจึงถูกทำให้บาดแผลใช้เวลานานในการฟื้นฟู หรือมันถูกทิ้งไว้ในการต่อต้านส่วน P

วิธีที่ดีที่สุดในการจัดการไขลมคือการ จำกัด ค่าสูงสุดที่เก็บไว้ในตัวรวมเพียงเล็กน้อยเกินกว่าที่จำเป็นในการแก้ไขข้อผิดพลาดตามสัดส่วนในกรณีที่แย่ที่สุด ถ้าผู้รวบรวมออกจากการแข่งขันและคัดค้าน P ออกจากกันสิ่งที่ดีที่สุดที่ต้องทำคือการตั้งค่าตัวรวมเป็นศูนย์ อัลโกสามารถออกแบบให้รู้สึกถึงสิ่งนี้และรีเซ็ตผู้รวมระบบเมื่อจำเป็น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.