Đăng Ký
Kết quả 1 đến 1 của 1
  1. #1
    Thành viên cấp 4
    Ngày tham gia
    Oct 2011
    Bài viết
    300
    Thanks
    17
    89 lượt trong 75 bài viết

    Hàm xử lý tín hiêu điều khiển không tuyến tính theo phương trình đường thẳng

    Trước giờ chúng ta quen với việc điều khiển các tín hiệu tuyến tính theo 1 phương trình nào đó , . Làm thế nào để điều khiển nếu đầu ra tuyến tính không theo phương trình với tín hiệu đầu vào?
    Ví dụ ta có yêu cầu như sau: Dựa vào % mực nước trong bồn mà ta dk valve với góc mở tương ứng. Coi như ta biết trước 1 số điểm như sau:
    Level 10% -> góc mở valve 0%
    Level 20% -> góc mở valve 20%
    Level 40% -> góc mở valve 40%
    Level 60% -> góc mở valve 60%
    Level 70% -> góc mở valve 80%
    Level 90% > góc mở valve 100%

    Rõ ràng %level và độ mở của valve không tỉ lệ theo đường thẳng, nếu %level không nằm trong những điểm như trên thì góc mở valve là bao nhiêu? VD: %level =30 thì nên mở valve bao nhiêu % là hợp lý?
    Mình muốn share với các bạn hàm mình viết để giải quyết vấn đề này, vì trong điều khiển phức tạp chúng ta hay gặp, bạn nào gặp có thể tham khảo
    Để dễ hình dung các bạn xem trước giao diện của hàm
    4.png

    Bước 1: Tạo hàm FC với các input, output như hình:1.png

    Trogn đó: In_Y kiểu pointer : giá trị đặt trước của %level
    In_X kiểu pointer : giá trị đặt trước của %valve tương ứng với level
    In_X_Var real : giá trị %level thực tế nhận từ field
    In_Max_Y: max limit của Y
    In_Min_Y: min limit của Y
    In_Div : số điểm mà chúng ta biết trước
    Out_Y: Giá trị % tương ứng của Y sẽ dk (ở đây là % góc mở của valve)
    Và tạo các biến local:
    2.png

    Bước 2: Bắt đầu viết lệnh, mình sẽ cố gắng giải thích từng lệnh cho các bạn hiểu

    Nw1: Kiểm tra vùng nhớ ngõ vào, mình dùng vùng nhớ DB nên nếu khác không thực hiện
    L P##IN_X // Load nguồn pointer
    LAR1 // Load thanh ghi địa chỉ AR1
    L W [AR1,P#0.0] // lấy nguồn của địa chỉ DB
    T #TMP_X_DB
    L D [AR1,P#2.0] // offset đến word tiếp theo
    T #TMP_X_ADDR
    L B [AR1,P#2.0] // offset byte
    L B#16#85 // Load loại input code
    >I // nếu memory là L [local data]
    JC END // THEN jump to end
    TAK // đảo thanh ghi
    L B#16#84 // Load loại input code
    <I // nếu memory I or Q or M
    JC END // THEN jump to end
    Nw2: Tương tự với X, kiểm tra ngõ vào Y
    L P##IN_Y // Load nguồn pointer
    LAR1 // Load thanh ghi địa chỉ AR1
    L W [AR1,P#0.0] // lấy nguồn của địa chỉ DB
    T #TMP_Y_DB
    L D [AR1,P#2.0] // offset đến word tiếp theo
    T #TMP_Y_ADDR
    L B [AR1,P#2.0] // offset byte
    L B#16#85 // Load loại input code
    >I // nếu memory là L [local data]
    JC END // THEN jump to end
    TAK // đảo thanh ghi
    L B#16#84 // Load loại input code
    <I // nếu memory I or Q or M
    JC END // THEN jump to end
    Nw3: Lấy số điểm biết trước từ ngõ vào
    L #IN_DIV //load số điểm biết trươc
    L 1
    <I //so sanh với 1
    JC END // nếu nhỏ hơn jup tới end
    TAK // đảo thanh ghi
    L 1
    -I // trừ cho 1
    T #TMP_DIV //lưu tạm vào bộ nhớ local
    Nw4 : Lưu giá trị 2 điểm vào bô nhớ local
    OPN DB [#TMP_X_DB] // Open DB chứ dữ liệu của X
    L #TMP_X_ADDR
    T #TMP_X_PNT // tạo pointer vùng nhớ local
    L DBD [#TMP_X_PNT] // Load giá trị x1
    T #TMP_x1 // x1

    L #TMP_X_PNT
    L P#4.0
    +D
    T #TMP_X_PNT // trỏ tới Dword tiếp theo để lấy giá trị điểm thứ 2.

    L DBD [#TMP_X_PNT] // Load giá trịx2
    T #TMP_x2 // x2

    OPN DB [#TMP_Y_DB] // tương tự như X
    L #TMP_Y_ADDR
    T #TMP_Y_PNT

    L DBD [#TMP_Y_PNT] // Load gía trị y1
    T #TMP_y1 // y1

    L #TMP_Y_PNT
    L P#4.0
    +D
    T #TMP_Y_PNT // trỏ tới dword tiếp theo

    L DBD [#TMP_Y_PNT] // Load giá trị y2
    T #TMP_y2 // y2

    L #IN_X_Var // load actual %level từ cảm biến
    L #TMP_x1
    >=R
    JC NEXT //jump to NEXT nếu actual X > 1st x1
    L #TMP_y1
    T #TMP_OUT_Y // ghi giá trị ra Y nếu actual X < 1st x1
    JU YLIM // OUT_Y = y1 and goto Y limiting
    NEXT: NOP 0

    Nw5 Kiểm tra giá trị actual %lavel nằm trong khoảng nào
    L #TMP_DIV // load số điểm biết trước
    L 1
    <I
    JC NLP
    TAK
    CTRL: T #TMP_LOOP // loop counter
    L #IN_X_Var // Nếu actual X <= next x2
    L #TMP_x2
    <=R
    JC IPOL // jump tới IPOL
    // // ngược lại
    L #TMP_x2 // x2 = x1
    T #TMP_x1

    L #TMP_X_PNT
    L P#4.0
    +D
    T #TMP_X_PNT // X pointer updating (point to x kế tiếp)

    OPN DB [#TMP_X_DB]
    L DBD [#TMP_X_PNT] // Load next x value
    T #TMP_x2 // New x2 value

    L #TMP_y2 // y2 = y1
    T #TMP_y1

    L #TMP_Y_PNT
    L P#4.0
    +D
    T #TMP_Y_PNT // Y pointer updating (point to next y)

    OPN DB [#TMP_Y_DB]
    L DBD [#TMP_Y_PNT] // Load next y value
    T #TMP_y2 // y2
    L #TMP_LOOP
    LOOP CTRL // trở lại đầu vòng lặp
    NLP: NOP 0
    L #IN_X_Var // Nếu actual X <= next x2
    L #TMP_x2
    <=R
    JC IPOL // jump tới IPOL
    Nw6: nếu actual value X > giá trị điểm x cuối cùng  Y_out = last y
    L #TMP_y2
    T #TMP_OUT_Y \\ ghi giá trị ra Y_out
    SET
    SAVE
    CLR
    A BR
    JC YLIM
    Nw7 Tính hệ số k: K= (y2 - y1)/(x2 - x1)
    IPOL: O(
    L #TMP_x2
    L #TMP_x1
    -R
    T #TMP_X2X1
    AN OV
    SAVE
    CLR
    A BR
    )
    O(
    A(
    L #TMP_X2X1
    L 9.999999e-011
    <R
    )
    JNB _001
    L 9.999999e-011
    T #TMP_X2X1
    SET
    SAVE
    CLR
    _001: A BR
    )
    O(
    L #TMP_y2
    L #TMP_y1
    -R
    T #TMP_Y2Y1
    AN OV
    SAVE
    CLR
    A BR
    )
    O(
    L #TMP_Y2Y1
    L #TMP_X2X1
    /R
    T #TMP_K
    AN OV
    SAVE
    CLR
    A BR
    )
    = #connect
    Nw8 thực hiên phương trình đường thẳng Y = K * (X - x1) + y1 của 2 điểm gần nhau
    L #IN_X_Var
    L #TMP_x1
    -R
    T #TMP_AUX_REAL
    AN OV
    SAVE
    CLR
    A BR
    )
    O(
    L #TMP_AUX_REAL
    L #TMP_K
    *R
    T #TMP_AUX_REAL
    AN OV
    SAVE
    CLR
    A BR
    )
    O(
    L #TMP_AUX_REAL
    L #TMP_y1
    +R
    T #TMP_OUT_Y
    AN OV
    SAVE
    CLR
    A BR
    )
    = #connect
    Nw9 : maximum and minimum output limit -> ghi giá trị đầu ra
    YLIM: A(
    L #TMP_OUT_Y
    L #IN_MAX_Y
    >R
    )
    JNB _002
    L #IN_MAX_Y
    T #TMP_OUT_Y
    _002: NOP 0
    A(
    L #TMP_OUT_Y
    L #IN_MIN_Y
    <R
    )
    JNB _003
    L #IN_MIN_Y
    T #TMP_OUT_Y
    _003: NOP 0
    L #TMP_OUT_Y
    T #OUT_Y //giá trị đầu ra
    NOP 0


    Bước 3:Sau khi hoàn thành tạo địa chỉ chứa các điểm biết trước trong DB
    3.png
    Như hình trên mình chỉ dùng 6 điểm chia để vẽ nên đường curve, càng nhiều điểm thì dk càng chính xác. Sau khi gọi ra sẽ có giao diện như hình
    4.png


    ---> Tóm lại hàm này dùng xử lý mối quan hệ điều khiển không tuyến tính theo pt đường thẳng, function sẽ vẽ ra 1 phuong trình đường cong dựa vào các điểm đã xác định được tọa độ trước. Nếu dùng càng nhiều điểm thì đường cong càng mịn và càng chính xác.
    Lần sửa cuối bởi Mechatronic_Hieu, ngày 11-12-2015 lúc 08:57 AM.
    Nhận hợp tác lập trình các loại PLC và xử lý sự cố về hệ thống tự động hóa
    Gm: Hidden Content

  2. The Following 4 Users Say Thank You to Mechatronic_Hieu For This Useful Post:


Đánh dấu

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •  
Back to Top