![](/img/trans.png)
[英]Using a C-Mex Function in an M-File S-Function in Simulink Real-Time
[英]Real-time update of values inside a call_back function[the values are from external function(of another .m file)]
我有一個外部函數說“ external_func”(單獨的.m文件)
在此函數中,調用了while循環,該while循環更新了一個名為“ update_prog”的變量
現在,我將使用
assignin('base', 'update_prog', update_prog); % passing to workspace
我正在做這個
將“ update_prog”作為全局變量並將其調用到GUIDE .m文件中
function pb1_Callback(hObject, eventdata, handles)
global update_prog
% hObject handle to pb1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% else
% set(handles.pb1,'enable','on');
% end
% update_prog first value prints, but it wont updates as the loop in external_func goes on.
drawnow;
set(handles.slider1,'Value',update_prog)
external_func;
所以在GUIDE .m文件中,我可以獲得值
“ update_prog”,但它不會跟上while循環。 我用過“ drawedow”,但是沒有用。
當“ external_func”中的while循環經歷多次迭代時,如何優化該值“ update_prog”。 [注意:更新的值在GUIDE的回調函數中,但是除非有回調,否則回調函數將不會更新“ update_prog”],因此如何在call_back函數中實現此實時更新。
[注意:在我的情況下,無法通過函數輸入傳遞變量,因此我正在尋找替代方法]
Edit1:請考慮此鏈接,其中包含一個示例,該示例可以闡明您我要達到的目標
我在這里做的是
問題是什么? 1. GUI回調中的變量(考慮到我將按下一個按鈕,然后使用while循環調用該函數)會將更新后的值放入set(handles.slider,'Value',variable)
通過這樣做,我無法移動滑塊。
為什么?
我不建議您通過一個中間工作區(外部->基礎工作區-> GUI)分三步傳遞變量。 我寧願建議直接傳遞變量(external-> GUI)。
每個Matlab圖形都有一個空間來存儲任何類型的變量(應用程序數據)。 我建議閱讀文章“ 在回調之間共享數據”,並閱讀3個功能的文檔:
這種方式將為您提供對變量范圍的更多控制,並且您不需要任何global
聲明。
下面是一個簡單gui的示例。 gui在用戶空間(使用setappdata
)中聲明該變量,然后使用計時器定期讀取該變量(使用getappdata
)。
外部函數可以執行您想執行的任何操作(在示例中只是一個隨機數),然后使用相同的setappdata
來更新變量。 您唯一需要的就是主GUI圖形的句柄,因此在示例中,我將其作為外部函數的輸入。
GUI還具有兩個按鈕來啟動和停止更新。
主要示例GUI'theGui.m'的代碼為:
function h = theGui
%// basic GUI with 2 buttons and 1 slider
h.fig = figure('Position',[433 434 500 100],'Menubar','none','CloseRequestFcn',@my_closefcn) ;
h.sld = uicontrol('Style','Slider','Position',[20 20 460 20]) ;
h.btnStart = uicontrol('Style','pushbutton','String','Start updating','Callback',@btnStart_callback,'Position',[20 50 200 30]);
h.btnStop = uicontrol('Style','pushbutton','String','Stop updating','Callback',@btnStop_callback,'Position',[280 50 200 30],'Max',1,'Min',0);
%// Define the timer
h.t = timer ;
h.t.Period = 0.1 ; %// 0.1s refresh interval
h.t.TimerFcn = {@timer_callback,h.fig} ;
h.t.ExecutionMode = 'fixedSpacing' ;
%// initialise the variable to update in the GUI appdata
update_prog = 0 ;
setappdata( h.fig , 'update_prog' , update_prog ) ;
%// save handles
guidata( h.fig , h );
function btnStart_callback(hobj,~)
h = guidata( hobj ) ; %// retrieve handles
if strcmp('off',h.t.Running) %// Start timer (only if not already running)
start(h.t)
end
function btnStop_callback(hobj,~)
h = guidata( hobj ) ; %// retrieve handles
stop(h.t) %// Stop timer
function timer_callback(~,~,hfig)
update_prog = getappdata( hfig , 'update_prog' ) ; %// retrieve the 'update_prog' variable value
h = guidata( hfig ) ; %// retrieve handles
set(h.sld , 'Value' , update_prog) ; %// update the slider object with the retrieved value
function my_closefcn(hobj,~)
%// this function is only to clean up when the GUI will be closed.
%// It is recommended to delete the timer manually
h = guidata( hobj ) ; %// retrieve handles
stop(h.t) %// Stop timer (in case it is still running)
delete(h.t) ; %// delete the timer
delete(h.fig) ; %// destroy the figure
以及用於external_func.m
的代碼
function external_func( guiMainFigureHandle )
%// This function will only generate random numbers and push them into the
%// variable 'update_prog' contained in the GUI appdata.
%// This is why this function NEEDS the handle of the gui to be able to
%// access the Application Data space of the gui.
for k = 1:100
randomValue = rand(1) ; %// generate a random value
hfig = ancestor( guiMainFigureHandle , 'figure' ) ; %// make sure the handle provided is the top level figure
setappdata( hfig , 'update_prog' , randomValue) ; %// update the variable value
pause(0.1) ;
end
編輯:我將其置於編輯狀態,而不是更改上面的代碼,因為如果您不需要,我不建議您將root
對象弄亂。 但就您而言,這可能是解決問題的一種方法。
如果您的外部功能無法訪問GUI,則它始終可以更新一部分內存,該內存可用於給定Matlab會話中運行的所有程序,即root
對象。 它的句柄是保留的,並且對於任何程序都是相同的: 0
(盡管自v2014b以來,還有另一種調用它的方法: groot ,但對於所有Matlab來說,它始終是相同的句柄)。
因此,在上面的示例中,在theGui.m
,改用:
setappdata( 0 , 'update_prog' , update_prog ) ;
在主例程中,然后在子函數function timer_callback(~,~,hfig)
,使用:
update_prog = getappdata( 0 , 'update_prog' ) ; %// retrieve the 'update_prog' variable
而且您的函數external_func()
不需要任何額外的參數,更新只需要一行:
setappdata( 0 , 'update_prog' , update_prog) ; %// update the variable value
我“懷疑”基本工作空間中的update_prog
變量不是全局變量(必須將其定義為在要使用它的每個工作空間中都是全局變量)。
由於您使用的是全局變量(有許多更好的方法可以執行此操作-但這不是您的問題)-為什么不簡單地將update_prog
變量定義為external_func
函數中的全局變量(替換assign調用)。
編輯在您的external_func
函數中放置一個drawow。 這樣,當您單擊按鈕時,它將更新。
編輯3
我想我知道您想做什么,請嘗試以下示例並查看它是否滿足您的要求-更新以顯示如何在代碼中找到滑塊對象並在循環內進行更新:
function mygui
% create a figure
f = figure;
% create a uicontrol slider - note that I give it a tag.
uicontrol ( 'style', 'slider', 'Position', [0 200 200 40], 'tag', 'MYSLIDER', 'backgroundcolor', 'white', 'parent', f );
% create a push button which we can press to update
uicontrol ( 'string', 'Press 2 start', 'callback', @(a,b)myLoop(), 'Position', [0 0 200 50] )
end
% This replicates your "external_func" function.
function myLoop()
% since you cant pass in any var -> you need to find the slider object
% you can do this by using findobj and search for the tag of the item
uic = findobj ( 0, 'tag', 'MYSLIDER' );
% find the figure handle (only needed for this demo)
f = ancestor ( uic, 'figure' );
% initialise the value which will be used to update the slider
count = 0;
% create your loop
while ishandle(f)
% incrememt the count variable -> this will end up on the slider value
count = count + 1e-5;
% reset count if > 1 -> so the slider cant go out of range.
if count >= 1
count = 0;
end
set ( uic, 'Value', count );
% initiate a drawnow -> this allows matlab to process GUI events
drawnow();
end
end
缺點是您在循環->中插入了一個drawow,這可能會使它變慢。
如果這不能解決您的問題,則需要更好地解釋您想做什么...(我認為)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.