Kontrol PID Putaran dengan anomali besar dan tidak terduga

10

Pertanyaan Singkat
Apakah ada cara umum untuk menangani anomali yang sangat besar (urutan besarnya) dalam wilayah kontrol yang seragam?

Latar Belakang
Saya sedang mengerjakan algoritma kontrol yang menggerakkan motor melintasi wilayah kontrol yang umumnya seragam. Dengan tanpa / pemuatan minimal, kontrol PID bekerja sangat baik (respon cepat, sedikit atau tidak ada overshoot). Masalah yang saya hadapi adalah biasanya ada setidaknya satu lokasi beban tinggi. Posisi ditentukan oleh pengguna selama instalasi, jadi tidak ada cara yang masuk akal bagi saya untuk mengetahui kapan / di mana mengharapkannya.

Ketika saya menyetel PID untuk menangani lokasi muatan tinggi, ini menyebabkan pucuk besar di area yang tidak dimuat (yang saya harapkan sepenuhnya). Sementara itu OK untuk perjalanan overshoot pertengahan, tidak ada berhenti keras mekanik di kandang. Kurangnya hardstop berarti bahwa overshoot yang signifikan dapat / tidak menyebabkan kelompok kontrol terputus dari motor (menghasilkan unit mati).

Hal-hal yang Saya Prototipe

  • PID bersarang (sangat agresif ketika jauh dari target, konservatif saat dekat)
  • Memperbaiki gain saat jauh, PID saat dekat
  • PID konservatif (berfungsi tanpa beban) + kontrol eksternal yang mencari PID untuk berhenti dan menerapkan energi tambahan hingga: target tercapai atau laju perubahan cepat terdeteksi (yaitu meninggalkan area muatan tinggi)

Keterbatasan

  • Perjalanan penuh ditentukan
  • Hardstops tidak dapat ditambahkan (pada saat ini)
  • Kesalahan kemungkinan tidak akan pernah hilang
  • Beban tinggi dapat diperoleh dari perjalanan kurang dari 10% (yang berarti tidak ada "mulai berjalan")
Adam Lewis
sumber

Jawaban:

2

Perhitungan kesalahan Anda tampaknya tidak menumpuk kesalahan ketika bekerja dengan istilah turunan, dan Anda mungkin ingin memodifikasi ini karena hanya istilah turunan yang mampu bereaksi terhadap perubahan cepat dalam proses.

Jika saya sudah benar kode Anda

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

akan selalu menghitung istilah kontrol berdasarkan kesalahan saat ini, yang merupakan cara tradisional bagaimana PID diimplementasikan. Tidak apa-apa karena istilah I seharusnya menjaga akumulasi kesalahan.

Namun, saya punya pelanggan yang datang dengan ide berikut yang mungkin ingin Anda coba. Karena Anda memiliki bagian dari kurva proses di mana perubahan yang lebih agresif diperlukan, Anda dapat membiarkan kesalahan bagian D menumpuk:

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)

Ada dua hal menarik yang perlu diperhatikan di sini:

  • Nilai TD bukan keuntungan turunan (yaitu KD) tetapi waktu turunan, konstanta pengguna yang mengontrol waktu kesalahan terakumulasi. Jika disetel ke nol, bagian D dari PID dinonaktifkan tanpa mengeset nilai perolehan KD.

  • Perhatikan bagaimana kesalahan saat ini digunakan untuk 'menagih' nilai Last_C sebelum membawanya ke perhitungan bagian D. Variabel Last_C bertindak seperti kapasitor, itu akan menumpuk sementara kesalahannya besar, sehingga bagian turunan Anda akan bertindak berdasarkan juga pada 'riwayat' kesalahan baru-baru ini, dan setelah itu (ketika kesalahan lebih kecil) ini 'riwayat' 'Akan keluar seperti kapasitor.

Tentu saja, Anda harus membatasi total output dengan cara yang mungkin sudah Anda lakukan (anti windup reset, auto bumpless ke transfer manual, dan hal-hal biasa lainnya).

Saya dapat memposting rincian lebih lanjut tentang istilah lain dari algoritma PID saya jika Anda merasa berguna, tetapi Anda mungkin ingin mencoba ini dan melihat apa yang terjadi. Ini melayani pelanggan saya dengan baik selama bertahun-tahun.

Drazen Cika
sumber
Terima kasih atas masukannya. Saya harus mencoba ini. Sekilas tampaknya masuk akal.
Adam Lewis
Saya mengerti, jadi Anda memiliki kontribusi istilah D dalam PID 'utama' Anda ditambah deteksi kios apa pun yang diperhitungkan.
Drazen Cika
1
Itu benar. Dterm PID digunakan, yang tidak terlalu agresif, selama penyetelan. Apa yang membuat masalah ini lebih sulit adalah bahwa beban dapat membebaskan dalam rentang waktu yang sangat singkat. Yaitu hubungan yang sedang dilepaskan. Penghapusan gaya secara tiba-tiba ini menyebabkan overshoot besar ketika ada fungsi penghalusan (penjumlahan) yang diterapkan pada gaya gerai.
Adam Lewis
Masalah jahat, akan menarik untuk mengetahui seberapa baik beberapa algoritma logika fuzzy menangani ini. Setidaknya Anda bisa membangun lebih banyak pengalaman terkait masalah Anda ke dalam algoritma, alih-alih tetap terkurung dalam solusi standar. Bagaimanapun, semoga sukses dengan ini :-)
Drazen Cika
1

Solusi Awal

stalled_pwm_output = PWM / | ΔE |

PWM = Nilai PWM maks
ΔE = last_error - new_error

Hubungan awal berhasil meningkatkan output PWM berdasarkan kurangnya perubahan pada motor. Lihat grafik di bawah ini untuk output sampel.

Pendekatan ini membuat karena untuk situasi di mana PID non-agresif terhenti. Namun, ada masalah yang disayangkan (dan jelas) bahwa ketika PID non-agresif mampu mencapai setpoint dan upaya untuk memperlambat, stalled_pwm_output macet. Ramp up ini menyebabkan overshoot besar saat bepergian ke posisi tidak dimuat.

1 / ΔE vs ΔE

Solusi Saat Ini

Teori

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

kE = Scaling Constant
PID_PWM = Permintaan PWM saat ini dari PID yang tidak agresif
ΔE = last_error - new_error

Hubungan saya saat ini masih menggunakan konsep 1 / ΔE, tetapi menggunakan output PID PWM yang tidak agresif untuk menentukan stall_pwm_output. Ini memungkinkan PID untuk menutup kembali stall_pwm_output ketika mulai mendekati setpoint target, namun memungkinkan 100% output PWM saat terhenti. Konstanta penskalaan kE diperlukan untuk memastikan PWM masuk ke titik saturasi (di atas 10.000 dalam grafik di bawah).

Kode semu

Perhatikan bahwa hasil dari cal_stall_pwm ditambahkan ke output PID PWM dalam logika kontrol saya saat ini.

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;
}

Output Data

Output PWM terhenti Output PWM terhenti

Perhatikan bahwa dalam grafik keluaran PWM yang macet, penurunan PWM tiba-tiba pada ~ 3400 adalah fitur keselamatan bawaan yang diaktifkan karena motor tidak dapat mencapai posisi dalam waktu tertentu.

Output PWM Tidak Dimuat Output PWM Tanpa Beban

Adam Lewis
sumber
1

Anda tidak mengatakan apa yang Anda kendalikan ... kecepatan motor? posisi? Apa pun itu, langkah pertama adalah menentukan kesalahan apa yang bisa diterima. Misalnya jika kontrol untuk kecepatan kesalahan maksimum dalam 1% dari target dapat diatur. Tanpa mendefinisikan kesalahan yang dapat diterima, Anda tidak dapat menentukan berapa banyak resolusi yang Anda butuhkan untuk jumlah ADC atau PWM. Tanpa itu, kompensasi PID bisa sempurna, tetapi masih memiliki osilasi siklus batas.

Maka Anda perlu mengetahui dinamika sistem loop terbuka. Tanpa itu Anda tidak dapat mengetahui keuntungan apa yang diperlukan untuk bagian proporsional (P), integral (I), dan turunan (D) dari loop. Anda dapat mengukur dinamika dengan langkah input (perubahan langkah dalam level drive atau PWM), atau perubahan langkah dalam beban (sepertinya ini akan relevan bagi Anda).

Menggunakan perubahan kesalahan siklus-ke-siklus, dalam penyebut algo kontrol Anda, untuk mengubah nilai PWM memastikan bahwa loop tidak akan pernah menyelesaikan. Ini memastikan osilasi siklus batas dalam kontrol. Sebagian besar pelanggan tidak akan tahan dengan itu.

Bagian P dari loop menangani kesalahan segera (merespons kesalahan dengan segera). Tetapi itu akan memiliki keuntungan yang terbatas sehingga beberapa kesalahan akan ditinggalkan. Bagian I dari loop bereaksi lambat dari waktu ke waktu untuk menerapkan gain tak terbatas (waktu tak terbatas untuk gain tak terbatas) untuk memperbaiki kesalahan yang ditinggalkan oleh bagian P.

Karena bagian I lambat, bisa keluar dari fase dengan koreksi yang diperlukan untuk meminimalkan kesalahan, bahkan jika Anda memiliki gain yang tepat untuk itu. Jadi, itu berakhir, butuh waktu lama untuk pulih. Atau, itu dibiarkan bertentangan dengan bagian P.

Cara terbaik untuk menangani angin adalah dengan membatasi nilai maksimum yang tersimpan dalam integrator menjadi hanya sedikit lebih dari yang diperlukan untuk memperbaiki kesalahan proporsional dalam kasus terburuk. Jika integrator keluar dari fase dan bertentangan dengan P terpisah, hal terbaik untuk dilakukan adalah menetapkan nilai integrator ke nol. Algo dapat dirancang untuk merasakan ini dan mengatur ulang integrator bila perlu.

gsills
sumber