Thông báo

Collapse
No announcement yet.

Lập trình GUI trong Matlab

Collapse
This is a sticky topic.
X
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Lập trình GUI trong Matlab

    Các bác ạ. Em xin mạn phép nói một chút về GUI sau một số chương trình em làm được.

    Một bạn điện tử đưa cho em chuyển giao diện từ Visual Basic 6.0 sang GUI( Graphic User Interface) trong Matlab. Em thấy được một số mặt như sau so với VB:

    - Do Matlab là công cụ tích hợp mạnh các công cụ tính toán nên trong Gui cũng được kế thừa rất là hay như tính toán với ma trận, vecto,.. Do đó dùng GUI ta không phải viết hàm con yêu cầu tính toán nhiều như tích phân, vi phân, tính toán với ma trận( với VB thì chịu thua, viết mã dài chết).
    Thứ nhất là thiết kế trực tiếp trên GUI( gõ lệnh gui trong Matlab) ta có thể nhúng các điều khiển ActiveX, biểu thị Simulink, các hệ trục,..Dùng mô phỏng như thật ấy, các bác có thể xem mấy cái Demo( nhớ cài JRE: Java Runtime
    Evironment nhé down load tại java.sun.com) :

    - Việc thiết kế các khung gắp thả như trong VB, lập trình cho các đối tượng cũng tương đối đơn giản với việc đặt tên cho các đối tượng trong thuộc tính Tag, tên hiển thị trên biểu mẫu với thuộc tính String, ngoài ra còn có nhiều thuộc tính cũng giống như VB như Position, Visiable,..Khi chúng ta tạo một đối tượng, thì sẽ có một hàm Callback được thêm tự động, ví dụ với đối tượng là Edit1 thì tương ứng sẽ có một hàm là Edit1_Callback được tạo ra đáp ứng sự kiện của đối tượng. Với Callback của đối tượng đó ta thao tác với đối tượng thông qua hObject và lấy thuộc tính dùng get, áp đặt thuộc tính thì dùng set:

    Ví dụ:

    Code:
      f=get(hObject,'String');% Lay sau nhap vao Edit1
       f=str2double(f);% chuyen sau thanh kieu Double
       set(hObject,'String','');
    Còn nếu muốn lấy thuộc tính của đối tượng khác thì dùng handles.nhan
    Ví dụ nếu muốn lấy thuộc tính của Edit2 trong hàm Edit1_callback thì dùng:
    Code:
    f2=get(handles.Edit2,'String');
            set(handles.Edit2,'String',' ');
    Để lấy kết quả từ một hàm nào đó bạn có thể dùng lệnh Save để lưu vào Mfile, hoặc dùng biến toàn cục nhưng nên dùng lệnh Save, sau đó muốn láy kết quả thì dùng Load. Cách này rất tốt cho cả các form khác nhau và các ứng dụng như giữa Simulink và GUI.

    Thứ nữa là nếu muốn lập trình cho menu thì tôi thấy là khi ta tạo lên một cái menu như là để mở một cái Form khác thì nếu dùng lệnh form với tên form là tên của form mà bạn cần mở ra. Nếu muốn cho form này luôn hiển thị trên các form khác thì dùng lệnh uiwait(form). Rất đơn giản phải không?Các bác có thể chạy được mấy cái đó trong môi trường Gui thôi( mở Gui và Open Browes đến file cần chạy). Hoặc là dùng lệnh trong command như trên.
    Thứ hai, thiết kế bằng tay: bạn chỉ cần phải thiết kế giao diện ban đầu hơi vất, sau đó là có thể cho thuộc tính Callback gọi một số hàm dưới dạng Mfile riêng rẽ( tức là viết riêng ra). Do đó khi minh gọi dùng cho Callback của các menu thì sẽ ổn thôi. Các bác khi thiết kế thì dùng cái thuộc tính mở Gui ra mà xem, còn thiết kế thì hoàn toàn trong Mfile: ví dụ như: edi1=uicontrol('style','radiobutton',..); Viết mã này cũng hơi dài yêu cầu phải kiên trì. Rất dễ báo lỗi.

    Trên đây là một số nhận xét của tôi không biết có ổn không nhưng chắc phần nào giải quyết cho các bác làm quen với Gui.

    Mình đã sửa lại bài viết cho đúng với thế mạnh của nó. Nếu viết sai thì chết. Thực ra chẳng khó nếu bạn tìm được giải pháp cho đúng. Nó có thể toàn diện ngang với VB có khi còn mạnh hơn về khả năng tính toán. Còn lập trình cấp thấp thì thua là cái chắc.
    Last edited by ngohaibac; 31-12-2005, 15:30.
    Technical sale at WT Microelectronics S'pore
    Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
    Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

  • #2
    PIDSystem

    Mình thấy các bạn mới học về Lý thuyết điều khiển tự động mà muốn hiểu rõ sự ảnh hưởng của các hệ số Kpid,Ti,Td với hệ thống chắc hẳn nếu dùng bằng Matlab khi thiết kế sẽ rất mất công thay thế các tham số.

    Mình chọn giải pháp là dùng GUI trong Matlab để thiết kế. Khi ta thay đổi các tham số của bộ điều khiển thì ấn vào Plot thì sẽ cho ngay đặc tính của hàm quá độ để biết xem hệ có đáp ứng chỉ tiêu chất lượng như có độ quá điều chỉnh phù hợp hay không? Mình nghĩ là cái này dùng rất là trực quan. các bạn down cái này giải nén các file vào thư mục /work trong thư mục cài đặt. Vào Matlab gõ lệnh PIDSystem thì bạn sẽ xem được chương trình. Hoặc mở GUI ra sau đó Open đến filel PIDSystem.fig.

    Lưu ý là tôi làm trên Matlab 7.0 nhưng mà trên bản 6.5 của bạn tôi thì không thể chạy được. Các bác cứ chạy trên bản 7 nhé.
    Attached Files
    Last edited by ngohaibac; 26-05-2006, 07:59.
    Technical sale at WT Microelectronics S'pore
    Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
    Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

    Comment


    • #3
      à tôi quên là nếu mà bạn lập trình GUI thì bạn có thể chạy nó bằng của sổ command của Matlab với tên giống như tên của m file đó.

      Với lại nếu mà lập trình menu thì bạn có thể dùng cái đó để lập trình tức là gọi các form khác ra.

      Ảnh minh họa của bài trên tôi không up lên được mong các bác thông cảm
      Last edited by ngohaibac; 31-12-2005, 15:36.
      Technical sale at WT Microelectronics S'pore
      Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
      Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

      Comment


      • #4
        tui cũng đang học matlab và thấy nó có các công cụ rất hay và cũng dễ sử dụng hơn các ngôn ngữ lập trình khác. Nhưng hình như tui nhe nói phần mềm viết trên matlab muốn đem bán thì phải có bản quyền nên tui cảm thấy như thế nào ấy!...

        Comment


        • #5
          Nguyên văn bởi ngohaibac
          à tôi quên là nếu mà bạn lập trình GUI thì bạn có thể chạy nó bằng của sổ command của Matlab với tên giống như tên của m file đó.
          Với lại nếu mà lập trình menu thì bạn có thể dùng cái đó để lập trình tức là gọi các form khác ra.
          Ảnh minh họa của bài trên tôi không up lên được mong các bác thông cảm
          Good job!,có gì hay hay nữa post lên cho anh em xem với

          Comment


          • #6
            OK thấy các bác hưởng ứng em vui lắm. Viết bài mãi mà chẳng thấy có ai đáp lại cả( sướng ca vô loài) tưởng các bác không quan tâm đến cái này. Tôi đã giúp cho một bạn ở K46 (bạn Hiền điện tử 10.. nếu vào thì cùng trao đổi ở đây nhé.) làm đề tài về mạng viễn thông tính tổn hao đường truyền của mạng. Mình đã thêm được một số kinh nghiệm về lập trình gui. Thực ra lập trình cái này cực kì đơn giản chỉ cần biết một vài cái về nó là xong.


            Tất nhiên về vấn đề bản quyền. Chương trình này phải chạy trên môi trường Matlab không dịch được ra file .exe cho nên không thể bán sản phẩm của bạn mà không có bản quyền của Matlab được( đau quá!) . Với lại nếu bạn cần phải tính toán rất nhiều liên quan đến ma trận, đồ thị thì mới nên dùng cái này ( như ngành của mình chẳng hạn). Còn không thì bạn có thể dùng bất kì phần mềm nào như VB, Visual C++, .. để viết ngon lành có điều những hàm tính toán đơn giản trong Matlab chuyển qua đây cũng tương đối phức tạp, dài dòng.

            Matlab là chương trình mô phỏng cực kì mạnh( Simulink,..) , có thể viết với mã C nhưng không thể giao tiếp với hệ thống được( không lập trình qua cổng Com được). Hay nói cách khác Matlab không phải là ngôn ngữ lập trình mà là một phần mềm ứng dụng cho phép ta dùng những từ đã định nghĩa sẵn trong Matlab để mô phỏng cái mà ta cần không thể lập trình được cấp thấp( low level).

            Mình sẽ viết tourial về cái này cho anh em ta và đặc biệt về ứng dụng trong các ngành về điều khiển tự động.
            Last edited by ngohaibac; 31-12-2005, 15:37.
            Technical sale at WT Microelectronics S'pore
            Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
            Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

            Comment


            • #7
              Cám ơn về các thông tin Matlab của bác ,mình cũng đang nghiên cứu vê món này.Mong được chỉ giáo.

              Comment


              • #8
                mình thấy lập trình GUI rất hay và trực quan,hình như nó dễ làm hơn bên VB
                trong phần Demos Matlab7.0,có 1 ví dụ về máy bay dưới dạng file f14ex.m;f14ex.fig và f14ex.mdl
                chúng ta phải save 3 file này vào thư mục Work để chạy thử
                Vd này tạo GUI cho mô hình Simulink,nhưng khi mình chạy thử thì có khi báo lỗi,có khi lại chay được,
                Các bạn thấy sao?

                Comment


                • #9
                  Lập trình GUI cho ứng dụng Simulink

                  Lần này tôi sẽ giới thiệu cho các bạn cách lập trình GUI cho ứng dụng Simulink: dùng GUI để thiết lập tham số cho các khối chức năng Function Block (FB), chạy mô phỏng hiển thị ra Scope.Lần tiếp theo tôi sẽ giới thiệu cách lấy dữ liệu đã mô phỏng sử dụng vào các mục đích khác như để ghi vào file hoặc là hiển thị ra một hệ trục tọa độ khác.

                  Còn đây là chi tiết về vấn đề hôm nay: Tôi dùng ví dụ điều chỉnh tốc độ của động cơ( có hàm truyền là bậc 1/bậc 2: là khâu dao động). Động cơ chính là đối tượng, còn ta sẽ bộ PID là bộ điều khiển để điều khiển tốc độ động cơ.

                  - Trước hết, muốn điều khiển được ứng dụng Simulink thì bạn phải tự thiết kế một modul .mdl trong Simulink bao gồm các khối chức năng, phải nối sẵn các khối đó với nhau( không cần điều chỉnh thông số cho các bộ đó). Lưu tên file vào trong thư mục Work với phần mở rộng là .mdl. Ở đây tôi chọn DCMotor. Sơ đồ các bạn có thể tham khảo ở dưới.


                  - Thứ hai, thiết lập trong GUI:

                  + Tạo giao diện như hình dưới bằng cách kéo thả. Đặt tên cho các đối tượng: nhấp đúp chuột, hiện Properties chọn thuộc tính Tag để đặt tên( tương ứng Caption trong VB). Các bạn nên đặt tên sao cho dễ nhớ( như nút bấm thì đặt có Button ở cuối,...). Có các edittext,statictext, plushbutton : ExitButton,SimulateButton, editP, editI,editD,..

                  + Viết chưong trình: Các bạn lưu ý ở đây tôi dùng bộ PID rất là đơn giản đạng : P+ I/s+ D*s thôi. Các bạn có thể dùng bộ PID khác phức tạp hơn như bộ nhân,.. Khi đó các tham số P,I,D có thể thay bằng Kp,Ki,.. Bạn hoàn toàn có thể chuyển hóa các cái này với nhau bằng cách lấy thuộc tính String của nó sau đó chuyển sang dạng Double để tính toán sau đó lại truyền tham số vào các khối PID,.. dùng str2double(string) chuyển str -> double, num2str(num) chuyển num->str. Thế là vấn đề về tham số là không có vấn đề gì.

                  ++ Với các nút bấm, edittext,.. bạn có các hàm Callback như Callback,CreateFcn,.. dùng CreateFcn để thiết lập tham số khi khởi tạo.
                  ---------------------------------
                  Mọi thứ râu ria đã xong bây giớ tôi sẽ giới thiệu cách thiết lập tham số cho bộ điều khiển. Để biết được tham số của các FB bạn vào Help theo chỉ dẫn của tôi ở dưới hình để biết chi tiết tham số. DCMotor.mdl có các khối tên là :
                  Sum,Scope,Transfer Fcn,PID Controller,Step.
                  Ở đây tôi dùng một hàm là model_open(handles) để thiết lập tham số và lấy thông tin từ các editP,editI,editD chuyển vào bộ PID, các khối khác cũng tương tự nếu cần;

                  Code:
                  % begin code
                  function model_open(handles)
                       open_system('DCMotor'); % mở bộ DCMotor phải đúng tên của file 
                                                        %nếu không thì chẳng làm được gì đâu
                       set_param('DCMotor/PID Controller','P',get(handles.editP,'String'),'I',get(handles.editI,'String')...
                           ,'D',get(handles.editD,'String'));
                       set_param('DCMotor/Transfer Fcn','Numerator','[15]','Denominator','[1 0.5 1]');
                       set_param('DCMotor/Sum','Inputs','|+-');
                       set_param('DCMotor/Step','Time','0');
                       set_param('DCMotor/Scope','Open','on','Decimation','1','NumInputPorts','1');
                      % mớ scope để xem mô phỏng.
                  **************
                  như các bạn thấy rất là đơn giản đúng không. Các khối chức năng như là một phần nhỏ của DCMotor do đó bạn dùng DCMotor/Sum để lấy tên của bộ Sum, tương tụ với các bộ khác, tham số thì tham khảo trong Help . Với khối PID lấy từ các edit.
                  --->thế là xong phần mở bộ điều khiển.

                  Phần tiếp theo là mô phỏng: khi ấn nút Simulate thì quá trình mô phỏng sẽ xảy ra. Thực hiện trong SimulateButton_Callback. có mấy cách để thực hiện có thể dùng hàm sim('DCMotor'), hoặc là set_param('DCMotor', 'SimulationCommand', 'start') để thiết lập tham số bắt đầu 'start', 'stop'. Từ đó bạn có thể cho thêm nút dừng mô phỏng trong GUI.
                  :
                  Code:
                  function SimulateButton_Callback(hObject, eventdata, handles)
                  % hObject    handle to SimulateButton (see GCBO)
                  % eventdata  reserved - to be defined in a future version of MATLAB
                  % handles    structure with handles and user data (see GUIDATA)
                      %Insert code
                      model_open(handles);
                      set_param('DCMotor', 'SimulationCommand', 'start')
                     % --- Executes during object creation, after setting all properties.
                  Còn với nút Exit đơn giản chỉ cần dùng hàm Close(' tên figure');
                  Code:
                  close(ControlDCMotor);
                  Xong! Các bạn thấy thế nào/.
                  Chúc thành công.

                  Ở dưới tôi upload cả mấy file minh họa và file chương trình . Các bác cho giải nén cho vào thư mục Work của Matlab. Gõ lệnh ControlDCMotor trong CommandWindow
                  Last edited by ngohaibac; 31-12-2005, 15:40.
                  Technical sale at WT Microelectronics S'pore
                  Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                  Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                  Comment


                  • #10
                    Nguyên văn bởi sonIC
                    mình thấy lập trình GUI rất hay và trực quan,hình như nó dễ làm hơn bên VB
                    chúng ta phải save 3 file này vào thư mục Work để chạy thử
                    Matlab mạnh hơn VB rất nhiều về mô phỏng lập trình GUI chỉ là phần nhỏ ứng dụng các hàm tính toán đã được lập sắn trong thư viện của nó. Nhưng bạn chẳng thể nào dịch file đó ra .exe mà chạy riêng đâu.
                    không cần save vào Work đâu. Bạn mở Guide ra Open đến file đó là được. Rồi Run nó sẽ hỏi có muốn chuyển cái đó thành thư mục Workspace không. Ok là xong. Chạy ngon.

                    Vd này tạo GUI cho mô hình Simulink,nhưng khi mình chạy thử thì có khi báo lỗi,có khi lại chay được,
                    Các bạn thấy sao?
                    Bạn phải xem xét lỗi của nó trong cửa sổ Command của Matlab ấy mà sửa lỗi. Ví dụ có lỗi chỉ xẩy ra khi bạn ấn vào nút nào đó thôi. Còn chưa ấn thì vô tư..
                    Technical sale at WT Microelectronics S'pore
                    Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                    Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                    Comment


                    • #11
                      ControlDCMotor V2.0

                      Các bạn thân mến hôm nay tôi sẽ giới thiệu cho các bạn cách hiển thị dữ liệu ra bằng Axes trên giao diện.

                      Hình minh hoạ bên dưới.

                      Giao diện này cho phép bạn có thể ấn vào Simulate để bắt đầu mô phỏng, ấn vào Plot để hiển thị ra đồ thị. Ấn vào Help để xem hướng dẫn. Ấn vào Exit để thoát. Nó sẽ hỏi bạn xem có muốn thoát không. Bạn đọc kĩ code để xem nhé.
                      Để làm được điều đó thì mình đã cho một Block: tofile vào khâu ra. Khi đó dữ liệu sẽ được ghi vào file do mình thiết lập trong model_open, sau đó dùng file này để lấy dữ liệu hiển thị lên đồ thị( dùng Plot): dùng command: load tênfile tếnbiến. Thế là xong.

                      Hi vọng là thỏa mãn sự đòi hỏi của các bạn về điều khiển chạy mô phỏng Simulink với các tham số tự cho, và đưa ra đồ thị.( lưu ý: các bạn nên đánh đúng tên file để chạy ứng dụng này: giải nén hết vào thư mục Work, đánh lệnh ControlDCMotor để chạy)

                      Ngoài ra các bạn có thể cải tiến thêm ứng dụng này cho phù hợp với bản thân mình.
                      Chúc thành công
                      Attached Files
                      Last edited by ngohaibac; 26-05-2006, 08:14.
                      Technical sale at WT Microelectronics S'pore
                      Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                      Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                      Comment


                      • #12
                        Cảm ơn Hải Bắc nha!!!!!!!
                        Dựa vào hướng dẫn của bạn,mình có thể mày mò làm phần bài tập của mình rùi
                        Mong bạn thường xuyên post bài cho anh em học hỏi

                        Comment


                        • #13
                          Cho em hỏi bác Hải Bắc tí nha
                          Ở cái ControlDCmotor.fig của bác,bây giờ em muốn thêm các nút editbutton để thay đổi thông số của hàm truyền động cơ thì phải thêm những hàm gì trong file soạn thảo
                          ControlDCmotor.m?
                          Còn nếu em muốn các đáp ứng ngõ ra của hệ thống được giữ lại trên ControlDCmotor.fig (ở cái chỗ figure mỗi khi nhấn plot thì có thể vẫn giữ lại hình ảnh đồ thị các ngõ ra của những lần trứơc,có nghĩa là khi thay đổi thông số PID thì mỗi khi plot vẫn còn lưu lại các đồ thị trên cùng 1 figure để em dễ dảng so sánh hơn) thì em phải làm sao? Có thể dùng lệnh Hold on được ko?
                          Mong bác giải quyết giúp em nha!!!!!!!!!!!!

                          Comment


                          • #14
                            Nhập thông số cho Transfer Fcn

                            Cho em hỏi bác Hải Bắc tí nha
                            Ở cái ControlDCmotor.fig của bác,bây giờ em muốn thêm các nút editbutton để thay đổi thông số của hàm truyền động cơ thì phải thêm những hàm gì trong file soạn thảo
                            ControlDCmotor.m?
                            Bạn sẽ phải thêm các editbox đó vào trong giao diện của mình rồi đặt thuộc tính tag cho nó. Sau đó lấy dữ liệu từ nó bằng hàm str2double. Bạn sửa trong model_open(handles). Vì hàm này được gọi trong SimulateButton_Callback(..). Khi ấn vào đó thì sẽ gọi hàm này lấy tham số từ các editbox để mô phỏng. Do vậy bạn cần thêm trong hàm model_open như sau: ví dụ bạn có các editbox có thuộc tính tag là a0: ứng với tử số, b0,b1,b2 ứng với mẫu số. Khi đó cần lấy giá trị của các cái này sau đó cho tham số vào block tên là Transfer Fcn:
                            Xóa dòng :
                            Code:
                            set_param('DCMotor/Transfer Fcn','Numerator','[15]','Denominator','[1 0.5 1]');
                            Thay bằng dòng sau:

                            Code:
                            a0= get(handles.a0,'String');
                             b0=get(handles.b0,'String'); % tương tự với các cái khác b1,b2
                            set_param('DCMotor/Transfer Fcn','Numerator','[15]','Denominator',['[',b2,' ',b1,' ',b0,']']);
                            // thế là xong
                            Bạn xem lại cách ghép sâu. Tham số cho Nummerator là kiểu string dạng [các số ] tức là có kiểu như vector nên dùng [] để liên kết dữ liệu. Nhớ trong '' phải có ít nhất một khoảng trắng.
                            Còn nếu em muốn các đáp ứng ngõ ra của hệ thống được giữ lại trên ControlDCmotor.fig (ở cái chỗ figure mỗi khi nhấn plot thì có thể vẫn giữ lại hình ảnh đồ thị các ngõ ra của những lần trứơc,có nghĩa là khi thay đổi thông số PID thì mỗi khi plot vẫn còn lưu lại các đồ thị trên cùng 1 figure để em dễ dảng so sánh hơn) thì em phải làm sao? Có thể dùng lệnh Hold on được ko?
                            Mong bác giải quyết giúp em nha!!!!!!!!!!!!
                            Đơn giản thôi. Bạn xem trong PlotButton_Callback bạn sẽ thấy là mình có dùng hold on( giữ lại đồ thị đã vẽ lần trước), hold off (bỏ đi đồ thị đã vẽ). Do đó mình dùng hold on sau khi vẽ xong plot(x,y1) để hiển thị tiếp plot(x,y2). Trước đó mình dùng hold off để xóa đi đồ thị trước. Nên bạn muốn giữ lại tất cả thì bỏ dòng lệnh:

                            Code:
                             hold off;
                            ở đầu đi.


                            Chúc thành công
                            Last edited by ngohaibac; 31-12-2005, 15:44.
                            Technical sale at WT Microelectronics S'pore
                            Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
                            Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

                            Comment


                            • #15
                              Tuyệt quá!!!!!!!!!
                              Em làm được rồi
                              Em cũng đã hiểu được phần nào rùi
                              Bác Hải Bắc có cái gì hay hay thì plot lên cho bọn em tìm hiểu nha!!
                              Lần sau chúng ta nói về cái gì nữa nhỉ?

                              Comment

                              Về tác giả

                              Collapse

                              ngohaibac Tìm hiểu thêm về ngohaibac

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X