sEMG项目总结(4)康复手上位机系统

康复手上位机系统

目录

1串口通信

这里写图片描述

%%主函数:注释说明和窗口初始化
function varargout = serial_communication2(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @serial_communication2_OpeningFcn, ...
                   'gui_OutputFcn',  @serial_communication2_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end

%%子函数OpeningFcn打开窗口时的初始化程序
function serial_communication2_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
warning('off');
javaFrame = get(hObject, 'JavaFrame');
javaFrame.setFigureIcon(javax.swing.ImageIcon('mll.png'));

%% 初始化参数
hasData = false;     %表征串口是否接收到数据
isShow = false;      %表征是否正在进行数显示,即是否正在执行函数dataDisp
isStopDisp = false;  %表征是否按下了【停止显示】按钮
isHexDisp = false;   %表征是否勾选了【十六进制显示】
isHexSend = false;   %表征是否勾选了【十六进制发送】
numRec = 0;          %接收字符计数
numSend = 0;         %发送字符计数
strRec = '';         %已接收的字符串

%% 将上述参数作为应用数据,存入窗口对象内
setappdata(hObject, 'hasData', hasData);
setappdata(hObject, 'strRec', strRec);
setappdata(hObject, 'numRec', numRec);
setappdata(hObject, 'numSend', numSend);
setappdata(hObject, 'isShow', isShow);
setappdata(hObject, 'isStopDisp', isStopDisp);
setappdata(hObject, 'isHexDisp', isHexDisp);
setappdata(hObject, 'isHexSend', isHexSend);

guidata(hObject, handles);

%%OutputFcn函数是窗口的输出子函数
function varargout = serial_communication2_OutputFcn(hObject, eventdata, handles) 
varargout{1} = handles.output;

%%串口回调函数
function com_Callback(hObject,~, handles)
%%在com对象产生过程中执行的回调函数
function com_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%%波特率回调函数
function rate_Callback(hObject, eventdata, handles)
function rate_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%%校验位回调函数
function jiaoyan_Callback(hObject, eventdata, handles)
function jiaoyan_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%%数据位回调函数
function data_bits_Callback(hObject, eventdata, handles)
function data_bits_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%%停止位回调函数
function stop_bits_Callback(hObject, eventdata, handles)
function stop_bits_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%% (1) 【打开/关闭串口】按钮的回调函数
%%    打开串口,并初始化相关参数
function start_serial_Callback(hObject, eventdata, handles)

%% 若按下【打开串口】按钮,打开串口
if get(hObject, 'value')
    com_n = sprintf('com%d', get(handles.com, 'value'));   %% 获取串口的端口名
    rates = [300 600 1200 2400 4800 9600 19200 38400 43000 56000 57600 115200];
    baud_rate = rates(get(handles.rate, 'value'));         %% 获取波特率
    %% 获取校验位设置
    switch get(handles.jiaoyan, 'value')
        case 1
            jiaoyan = 'none';
        case 2
            jiaoyan = 'odd';
        case 3
            jiaoyan = 'even';
    end
    data_bits = 5 + get(handles.data_bits, 'value');  %% 获取数据位个数
    stop_bits = get(handles.stop_bits, 'value');      %% 获取停止位个数
    %% 创建串口对象
    scom = serial(com_n);
    scom
    %% 配置串口属性,指定其回调函数                               配置串口属性,指定其回调函数
    set(scom, 'BaudRate', baud_rate, 'Parity', jiaoyan, 'DataBits',...           %BytesAvailableFcnCount:字节计数
        data_bits, 'StopBits', stop_bits, 'BytesAvailableFcnCount', 10,...       %BytesAvailableFcn:字节计数回调函数
        'BytesAvailableFcnMode', 'byte', 'BytesAvailableFcn', {@bytes, handles},...%BytesAvailableFcnMode:字节模式,一般byte
        'TimerPeriod', 0.05, 'TimerFcn', {@dataDisp, handles});    %TimerFcn:定时回调函数,TimerPeriod:定时周期,串口数据通信

    %% 将串口对象的句柄作为用户数据,存入窗口对象
    set(handles.figure1, 'UserData', scom);
    %% 尝试打开串口
    try                           %执行过程中如果出错,执行catch下的语句
        fopen(scom);  %打开串口

    catch   % 若串口打开失败,提示“串口不可获得!”
        msgbox('串口不可获得,未连接外设!');
        set(hObject, 'value', 0);  %弹起本按钮 
        return;
    end
    %% 打开串口后,允许串口发送数据,清空接收显示区,点亮串口状态指示灯
    %% 并更改本按钮文本为“关闭串口”
    set(handles.period_send, 'Enable', 'on');  %启用【自动发送】按钮
    set(handles.manual_send, 'Enable', 'on');  %启用【手动发送】按钮
    set(handles.xianshi, 'string', '');        %清空接收显示区
  %  set(handles.activex1, 'value', 1);        %点亮串口状态指示灯
    set(hObject, 'String', '关闭串口');         %设置本按钮文本为“关闭串口”
else  %若关闭串口
    %% 停止并删除定时器
    t = timerfind;        %查找定时器
    if ~isempty(t)
        stop(t);
        delete(t);
    end
    %% 停止并删除串口对象
    scoms = instrfind;    %在内存查找串口对象
    stopasync(scoms);     %停止异步读写
    fclose(scoms);
    delete(scoms);
    %% 禁用【自动发送】和【手动发送】按钮,熄灭串口状态指示灯
    set(handles.period_send, 'Enable', 'off', 'value', 0); %禁用【自动发送】按钮
    set(handles.manual_send, 'Enable', 'off');  %禁用【手动发送】按钮

    set(hObject, 'value', 0);  %弹起本按钮 
    set(hObject, 'String', '打开串口');         %设置本按钮文本为“关闭串口”
    % set(handles.activex1, 'value', 0);  %熄灭串口状态指示灯
end

%%(2)  串口数据显示,串口的TimerFcn回调函数
function dataDisp(obj, event, handles)

%% 获取参数
hasData = getappdata(handles.figure1, 'hasData'); %串口是否收到数据
strRec = getappdata(handles.figure1, 'strRec');   %串口接收的字符串,定时显示该数据
numRec = getappdata(handles.figure1, 'numRec');   %串口接收到的数据个数

%% 若串口没有接收到数据,先尝试接收串口数据
if ~hasData
    bytes(obj, event, handles);
end

%% 若串口有数据,显示串口数据
if hasData
    %% 给数据显示模块加互斥锁
    %% 在执行显示数据模块时,不接受串口数据,即不执行BytesAvailableFcn回调函数
    setappdata(handles.figure1, 'isShow', true); 

    %% 若要显示的字符串长度超过10000,清空显示区
    if length(strRec) > 10000
        strRec = '';
        setappdata(handles.figure1, 'strRec', strRec);
    end

    %% 显示数据
    set(handles.xianshi, 'string', strRec);

    %% 更新接收计数
    set(handles.rec,'string', numRec);

    %% 更新hasData标志,表明串口数据已经显示
    setappdata(handles.figure1, 'hasData', false);

    %% 给数据显示模块解锁
    setappdata(handles.figure1, 'isShow', false);
end

%% (3) 串口接收数据,串口的BytesAvailableFcn回调函数(字节计数回调函数)
function bytes(obj, ~, handles)
%% 获取参数
strRec = getappdata(handles.figure1, 'strRec');         %获取串口要显示的数据
numRec = getappdata(handles.figure1, 'numRec');         %获取串口已接收数据的个数
isStopDisp = getappdata(handles.figure1, 'isStopDisp'); %是否按下了【停止显示】按钮
isHexDisp = getappdata(handles.figure1, 'isHexDisp');   %是否十六进制显示
isShow = getappdata(handles.figure1, 'isShow');         %是否正在执行显示数据操作

%% 若正在执行数据显示操作,暂不接收串口数据
if isShow
    return;
end

%% 获取串口可获取的数据个数
n = get(obj, 'BytesAvailable');

%% 若串口有数据,接收所有数据
if n
    %% 更新hasData参数,表明串口有数据需要显示
    setappdata(handles.figure1, 'hasData', true);

    %% 读取串口数据
    a = fread(obj, n, 'uchar');   %从obj中读出n个数据,8位无符号读出

    %% 若没有停止显示,将接收到的数据解算出来,准备显示
    if ~isStopDisp 

        %% 根据进制显示的状态,解析数据为要显示的字符串
        if ~isHexDisp 
            c = char(a');

        else
            strHex = dec2hex(a')';
            strHex2 = [strHex; blanks(size(a, 1))];
            c = strHex2(:)';
        end

        %% 更新已接收的数据个数
        numRec = numRec + size(a, 1);    %size(a,1)返回矩阵 a 的行数

        %% 更新要显示的字符串
        strRec = [strRec c];
    end
    %% 更新参数
    setappdata(handles.figure1, 'numRec', numRec); %更新已接收的数据个数
    setappdata(handles.figure1, 'strRec', strRec); %更新要显示的字符串
end

%% (4)清空要显示的字符串
function qingkong_Callback(hObject, eventdata, handles)
setappdata(handles.figure1, 'strRec', '');
set(handles.xianshi, 'String', '');%% 清空显示

%% (5)根据【停止显示】按钮的状态,更新isStopDisp参数
function stop_disp_Callback(hObject, eventdata, handles)
if get(hObject, 'Value')
    isStopDisp = true;
else
    isStopDisp = false;
end
setappdata(handles.figure1, 'isStopDisp', isStopDisp);

%function radiobutton1_Callback(hObject, eventdata, handles)
%function radiobutton2_Callback(hObject, eventdata, handles)
%function togglebutton4_Callback(hObject, eventdata, handles)

%%(6) 根据【十六进制显示】复选框的状态,更新isHexDisp参数
function hex_disp_Callback(hObject, eventdata, handles)
if get(hObject, 'Value')
    isHexDisp = true;
else
    isHexDisp = false;
end
setappdata(handles.figure1, 'isHexDisp', isHexDisp);

%% (7)手动发送回调函数
function manual_send_Callback(hObject, eventdata, handles)
scom = get(handles.figure1, 'UserData');
numSend = getappdata(handles.figure1, 'numSend');
val = get(handles.sends, 'UserData');
numSend = numSend + length(val);
set(handles.trans, 'string', num2str(numSend));
setappdata(handles.figure1, 'numSend', numSend);

%% 若要发送的数据不为空,发送数据
if ~isempty(val)
    %% 设置倒计数的初值
    n = 1000;
    while n

       %% 获取串口的传输状态,若串口没有正在写数据,写入数据
        str = get(scom, 'TransferStatus');
        if ~(strcmp(str, 'write') || strcmp(str, 'read&write'))    %strcmp比较两个字符串是否相等
            fwrite(scom, val, 'uint8', 'async');         %数据写入串口
            val
            break;
        end
        n = n - 1; %倒计数
    end
end

%% (8)清空发送区
function clear_send_Callback(hObject, eventdata, handles)
set(handles.sends, 'string', '')
set(handles.sends, 'UserData', []); %% 更新要发送的数据

%function checkbox2_Callback(hObject, eventdata, handles)

%% (9) 【自动发送】按钮的Callback回调函数
function period_send_Callback(hObject, eventdata, handles)

%% 若按下【自动发送】按钮,启动定时器;否则,停止并删除定时器
if get(hObject, 'value')
    t1 = 0.001 * str2double(get(handles.period1, 'string'));%获取定时器周期
    t = timer('ExecutionMode','fixedrate', 'Period', t1, 'TimerFcn',...
        {@manual_send_Callback, handles});    %创建定时器
    set(handles.period1, 'Enable', 'off');    %禁用设置定时器周期的Edit Text对象
    set(handles.sends, 'Enable', 'inactive'); %禁用数据发送编辑区
    start(t);  %启动定时器
else
    set(handles.period1, 'Enable', 'on'); %启用设置定时器周期的Edit Text对象
    set(handles.sends, 'Enable', 'on');   %启用数据发送编辑区
    t = timerfind; %查找定时器
    stop(t); %停止定时器
    delete(t); %删除定时器
end

%% (10)设置发送周期文本框
function period1_Callback(hObject, eventdata, handles)

function period1_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%% (11)计数清零,并更新参数numRec和numSend
function clear_count_Callback(hObject, eventdata, handles)
set([handles.rec, handles.trans], 'string', '0')
setappdata(handles.figure1, 'numRec', 0);
setappdata(handles.figure1, 'numSend', 0);

%% (12)设置是否允许复制接收数据显示区内的数据
function copy_data_Callback(hObject, eventdata, handles)
if get(hObject,'value')
    set(handles.xianshi, 'enable', 'on');
else
    set(handles.xianshi, 'enable', 'inactive');

end

%% (13)关闭窗口时,检查定时器和串口是否已关闭 ,若没有关闭,则先关闭
function figure1_CloseRequestFcn(hObject, eventdata, handles)
t = timerfind;  %% 查找定时器
%% 若存在定时器对象,停止并关闭
if ~isempty(t)
    stop(t);  %若定时器没有停止,则停止定时器
    delete(t);
end

scoms = instrfind;  %% 查找串口对象
%% 尝试停止、关闭删除串口对象
try
    stopasync(scoms);
    fclose(scoms);
    delete(scoms);
end
delete(hObject);   %% 关闭窗口

%% (14)根据【十六进制发送】复选框的状态,更新isHexSend参数
function hex_send_Callback(hObject, eventdata, handles)
if get(hObject,'value')
    isHexSend = true;
else
    isHexSend = false;
end
setappdata(handles.figure1, 'isHexSend', isHexSend);
%% 更新要发送的数据
sends_Callback(handles.sends, eventdata, handles);

%%  (15) 数据发送编辑区的Callback回调函数,更新要发送的数据
function sends_Callback(hObject, eventdata, handles)

%% 获取数据发送编辑区的字符串
str = get(hObject, 'string');

%% 获取参数isHexSend的值
isHexSend = getappdata(handles.figure1, 'isHexSend');
if ~isHexSend        %若为ASCII值形式发送,直接将字符串转化为对应的数值
    val = double(str);
else  %若为十六进制发送,获取要发送的数据
    n = find(str == ' ');   %查找空格,返回所有空格的位置
    n =[0 n length(str)+1]; %空格的索引值  n行向量

    %% 每两个相邻空格之间的字符串为数值的十六进制形式,将其转化为数值
    for i = 1 : length(n)-1 
        temp = str(n(i)+1 : n(i+1)-1);  %获得每段数据的长度,为数据转换为十进制做准备
        if ~rem(length(temp), 2)
            b{i} = reshape(temp, 2, [])'; %将每段十六进制字符串转化为单元数组
        else
            break;
        end
    end
    val = hex2dec(b)';     %将十六进制字符串转化为十进制数,等待写入串口
end
%% 更新要显示的数据
set(hObject, 'UserData', val); 

2患者信息记录

3患者主被动康复

4游戏

4.1打地鼠

这里写图片描述

function varargout = gamedishu(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @gamedishu_OpeningFcn, ...
                   'gui_OutputFcn',  @gamedishu_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
function gamedishu_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
function varargout = gamedishu_OutputFcn(hObject, eventdata, handles) 
varargout{1} = handles.output;

%%(1)开始游戏
function start_game_Callback(hObject, eventdata, handles)
tic                              %开始计时
I0=imread('background.jpg');     %读取背景图   %% imread 读取图像得到三维矩阵,前两维是空间坐标,第三维取值1/2/3代表三基色红、绿、蓝
I1=imread('mouse.jpg');          %读取地鼠

background_size = size(I0);
mouse_size = size(I1);

I1_Alpha = double((I1(:,:,1)<230 & I1(:,:,2) <230 & I1(:,:,3) <230));   %% 将地鼠图片中的白色区域置1,(隐藏)

hitCount=0;                              %定义一个变量并取0
ratHole_location=load('ratHole.txt');    %取出鼠洞文本文档中的值 ,已经从背景图片中获得(应该是鼠洞的左上角坐标值)
ratHole_num=size(ratHole_location,1);    %确定鼠洞的个数并赋值给N           

ratHole_location(:,1) = ratHole_location(:,1) + mouse_size(2)./2;    % 求得鼠洞出口的中心位置 
ratHole_location(:,2) = ratHole_location(:,2) + mouse_size(1)./2;    % 为什么是:X+y,Y+x

rand_ratLocation=floor(rand*ratHole_num)+1;                          % 对N中的元素随机取整(随机取1-12),floor取比它小的整数,rand取0-1的随机小数
set(handles.end_game,'UserData',0);             %终止程序isStop=0

imshow(I0);                                     %显示Image1的内容   
set(gca, 'NextPlot', 'Add');   %gca返回当前axes对象的句柄值,nextplot重绘模式,add使用当前的坐标轴,把新的图形对象加到此坐标轴中

ratImage_changed = image(-1000,-1000,I1);        % image(x,y,C), x,y指定坐标轴的范围,显示相同的图片
set(ratImage_changed,'AlphaData', I1_Alpha);     % 改变 I1_Alpha 值,可以改变明暗(透明程度)
pos_clickedShow = text(0, -8, '');               % text(x,y,'string')在图形指定位置显示字符串

for k=1:100000                  
    x_rat=ratHole_location(rand_ratLocation,1);  
    y_rat=ratHole_location(rand_ratLocation,2);  % 定义地鼠的横纵坐标
    rat_rescale_factor = (y_rat+200)./(background_size(1)+200); %%地鼠缩放因子,有不同的方法设置rescale_factor,100 是随便取的数字

    %将地鼠贴图到背景图的范围内,YData有点疑问
    set(ratImage_changed ,'XData', [x_rat-mouse_size(2)*rat_rescale_factor./2, x_rat+mouse_size(2)*rat_rescale_factor./2],...
        'YData', [y_rat-mouse_size(1)*rat_rescale_factor+10.* rat_rescale_factor, y_rat+10.*rat_rescale_factor]);

    pos_clicked=get(gca,'currentpoint');  %确定鼠标的坐标 ,获取最近一次点击的位置,返回一个2*3矩阵,axes是3D的,每行代表一个点的坐标
    x_clicked=pos_clicked(1,1);
    y_clicked=pos_clicked(1,2);
    set(pos_clickedShow, 'String', sprintf('%d %d',x_clicked,y_clicked));   % 显示当下鼠标点击的位置
    drawnow;

    %判断鼠标是否点击在地鼠的范围内
    if ((x_clicked>=x_rat-mouse_size(2)*rat_rescale_factor./2)...
            &&(x_clicked<=(x_rat+x_rat+mouse_size(2)*rat_rescale_factor./2))...
            &&(y_clicked>=y_rat-mouse_size(1)*rat_rescale_factor)...
            &&(y_clicked<=y_rat))  
        hitCount=hitCount+1;                                                     % 对变量DJ进行累加
        set(handles.correct_hit,'String',sprintf('正确打击:%3.0f次',hitCount));  % 在text2中显示DJ的值
        rand_ratLocation=floor(rand*ratHole_num)+1;                              % 随机取整N中的元素
    end;

    isStop=get(handles.end_game,'UserData');   % 把pushbutton2的内容赋值给isStop
    if (isStop==1);                            % 判断isStop==1
        break;              
    end;
end;
set(handles.game_time, 'String', sprintf('游戏时间:%3.0f秒',toc));  %计时结束,并在text1中显示时间

%%(2)结束游戏
function end_game_Callback(hObject, eventdata, handles)
set(handles.end_game,'UserData',1);        % isStop=1

4.2flappy bird

这里写图片描述

function varargout = flappy_point(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @flappy_point_OpeningFcn, ...
                   'gui_OutputFcn',  @flappy_point_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end


function flappy_point_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;

global g y1 y2 y3 Fs1 Fs2 Fs3 picMbg picMbd flysound vwall cond record 
record=0;
flysound=0;
g=5;    %%重力加速度              %%============================================================================
vwall=4;  %%类似于鸟的水平速度       %%============================================================================
cond=0;   %%条件数

[y1,Fs1] = audioread('fb_music\die.wav');
[y2,Fs2] = audioread('fb_music\jump.wav');
[y3,Fs3] = audioread('fb_music\fly.wav');

axes(handles.axes1);
cla reset;      %%清除当前的 axes
picbg=imread('fb_pic\BG.bmp');
imshow(picbg,'xdata',[1,80],'ydata',[1,110]);
set(handles.axes1,'unit','normalized','visible','on');
axis([0 80 0 110]);  %%表示坐标轴的最小最大值
axis off;  %%关闭所用坐标轴上的标记、格栅、单位标记

set(handles.kaishi,'enable','on');
set(handles.qingchu,'enable','on');

picMbg=picbg;
size1=size(picbg(:,1,1));
for i=1:size1(1)
    picMbg(i,:,:)=picbg(size1(1)+1-i,:,:); %%横坐标,逆序
end

picbd=imread('fb_pic\bird.png');
picMbd=picbd;
size1=size(picbd(:,1,1));
for i=1:size1(1)
    picMbd(i,:,:)=picbd(size1(1)+1-i,:,:);   
end

guidata(hObject, handles);
function varargout = flappy_point_OutputFcn(hObject, eventdata, handles) 
varargout{1} = handles.output;

%%(1)【清除】按钮
function qingchu_Callback(hObject, eventdata, handles)
global record
record=0;
set(handles.gaofen,'string',num2str(record));     %%高分清除掉

%%(2)【按键按下】回调函数
function figure1_KeyPressFcn(hObject, eventdata, handles)
global v cond
press=get(hObject,'currentkey');     %%获取当下按下的按键的值
if strcmp(press,'downarrow')  %%向下键,开始
    if (cond==0)
        kaishi_Callback(hObject, eventdata, handles);
        return;
    end
end
switch press
    case {'space','uparrow'}   %% 空格键、向上键,向上跳
        v=5;           %%=================================================================================================
        game_level=get(handles.selecte_level,'value');
        switch game_level
            case 2
                 v=2;
            case 3
                 v=5;
            case 4
                 v=8;
        end
end

%%(3)【开始】按钮
function kaishi_Callback(hObject, eventdata, handles)
global v record g vwall cond y1 y2 Fs1 Fs2 flysound picMbg picMbd
%dt=str2num(get(handles.shijian,'string')); %时间 0.05秒    
dt=0.05;               %%================================================================================================

%%选择游戏难度
game_level=get(handles.selecte_level,'value');
switch game_level
    case 2
        g=2;
        dt=0.02;
        vwall=3;
    case 3
        g=5;
        dt=0.05;
        vwall=11;
    case 4
        g=8;
        dt=0.07;
        vwall=13;
end

cond=1;
flysound=1;
v=0.0;     %%鸟的初始垂直高度
h=70;      %%鸟的初始高度

xx1=110;   %%每张图两个障碍物,横坐标
xx2=155;

s=0;     %%鸟横向飞过的路程
dx=0;

hh1=round(20+40*rand);  %%障碍物,随机高度 (20+40*rand) 20-60之间       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
hh2=round(20+40*rand);                     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

axes(handles.axes1);
cla reset;   %%清除当前axes
hold on;     %%使当前轴与图形保持而不被刷新,准备接受此后将绘制,  (新图与旧图共存)
a1=imshow(picMbg,'xdata',[1,80],'ydata',[1,110]);      %显示第一张背景
a2=imshow(picMbg,'xdata',[80,159],'ydata',[1,110]);    %显示第二张背景
bd=imshow(picMbd,'xdata',[27,33],'ydata',[68.5,73.5]); %显示鸟
hold off;    %%使当前轴与图形不在具备被刷新的性质  (原图被新图代替)
axis xy;     %%使用笛卡尔坐标系,原点在左下角
axis([0 80 0 110]);

set(handles.kaishi,'enable','off');
set(handles.qingchu,'enable','off');

%%设置障碍物,用粗线表示
L1=line([xx1,xx1],[hh1+40,110],'color','g','linewidth',42,'erasemode','normal');    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
L2=line([xx1,xx1],[0,hh1-10],'color','g','linewidth',42,'erasemode','normal');      %%%%%%%%%%%%%%%%%%%%%%%%%%
L3=line([xx2,xx2],[hh2+40,110],'color','g','linewidth',42,'erasemode','normal');    %%%%%%%%%%%%%%%%%%%%%
L4=line([xx2,xx2],[0,hh2-10],'color','g','linewidth',42,'erasemode','normal');      %%%%%%%%%%%%%%%%%%%%%%%%%%%

%%障碍物的前端区域
L5=line([xx1,xx1],[hh1+30,hh1+40],'color',[0 1 0.5],'linewidth',48,'erasemode','normal');  %%%%%%%%%%
L6=line([xx1,xx1],[hh1-10,hh1],'color',[0 1 0.5],'linewidth',48,'erasemode','normal');      %%%%%%%%
L7=line([xx2,xx2],[hh2+30,hh2+40],'color',[0 1 0.5],'linewidth',48,'erasemode','normal');   %%%%%%%%%%%%
L8=line([xx2,xx2],[hh2-10,hh2],'color',[0 1 0.5],'linewidth',48,'erasemode','normal');     %%%%%%%%%%%%%%%%%

while(cond==1)     %%死循环
    dx=dx+1;
    count=fix(dx/3.5);   %% fix取整函数,朝零向取整
    if(count>80)         %%图片宽度 80
        count=0;
        dx=0;
    end

    picx1=1-count;
    picx2=80-count;
    set(a1,'xdata',[picx1,picx1+79]);    %%显示背景图片
    set(a2,'xdata',[picx2,picx2+79]);

    h=h+v*dt-0.5*g*dt^2;  %%鸟的高度,只受重力作用   
    v=v-g*dt;             %%鸟的速度,垂直方向上的  

    xx1=xx1-vwall*dt;     %%飞过 dt 时间之后的,水平位置   8*0.05=0.4,水平每次减少 0.4
    xx2=xx2-vwall*dt;

    prescore=fix((s-40)/45.0);  %%之前得分  s=84,prescore=0;
    if(prescore<0)
        prescore=0;
    end

    s=s+vwall*dt;    %%鸟的飞行长度   s=85,score=1
    score=fix((s-40)/45.0);
    if(score<0)
        score=0;
    end

    if(score>prescore)   %%当前得分大于之前得分
        switch game_level
            case 1
                sound(y2,Fs2);   %%前两个游戏等级有声音提示,后两个没有,有声音提示游戏较卡
            case 2
                sound(y2,Fs2);
        end
    end

    set(bd,'ydata',[h-2,h+2]);   %%设置每次循环鸟的高度

    set(L1,'xdata',[xx1,xx1]);   %%设置每次循环,障碍物的水平位置
    set(L2,'xdata',[xx1,xx1]);
    set(L5,'xdata',[xx1,xx1]);
    set(L6,'xdata',[xx1,xx1]);
    set(L3,'xdata',[xx2,xx2]);
    set(L4,'xdata',[xx2,xx2]);
    set(L7,'xdata',[xx2,xx2]);
    set(L8,'xdata',[xx2,xx2]);

    if(xx1<(-5))                  %%每次循环 xx1减少一点
        hh1=round(20+40*rand);    %%设置随机高度             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        xx1=85;
        set(L1,'xdata',[xx1,xx1],'ydata',[hh1+40,110]);     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        set(L2,'xdata',[xx1,xx1],'ydata',[0,hh1-10]);       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        set(L5,'xdata',[xx1,xx1],'ydata',[hh1+30,hh1+40]);  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        set(L6,'xdata',[xx1,xx1],'ydata',[hh1-10,hh1]);     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%55
    end

    if(xx2<(-5))
        hh2=round(20+40*rand);                              %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        xx2=85;
        set(L3,'xdata',[xx2,xx2],'ydata',[hh2+40,110]);     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        set(L4,'xdata',[xx2,xx2],'ydata',[0,hh2-10]);       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        set(L7,'xdata',[xx2,xx2],'ydata',[hh2+30,hh2+40]);  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        set(L8,'xdata',[xx2,xx2],'ydata',[hh2-10,hh2]);     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    end

    if((h>110)||(h<0))     %%如果鸟的高度超出背景图片范围,死亡
        cond=0;            %%条件数置0,跳出死循环
        set(handles.kaishi,'enable','on');
        set(handles.qingchu,'enable','on');

        if(record<=score)
            record=score;  %%最高得分低于当前得分,替换
            set(handles.gaofen,'string',num2str(record));
        end
        sound(y1,Fs1);  %%死亡的声音
        %flysound=0;
        text(12,70,'Game Over','fontsize',40,'color','k');

        while(h>0)   %%当鸟的高度超过图片上限时,死亡,鸟降落
            h=h-1;
            pause(0.005);
            set(bd,'ydata',[h-2,h+2]);
        end

    else    %%当鸟的高度在背景图范围内时,
        if((xx1<=38)&&(xx1>=22))   %%(1)                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            if((h>(hh1+28))||(h<(hh1+2)))   %%死亡        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                cond=0;
                set(handles.kaishi,'enable','on');
                set(handles.qingchu,'enable','on');
                if(record<=score)
                    record=score;
                    set(handles.gaofen,'string',num2str(record));
                end
                sound(y1,Fs1);
               %flysound=0;
                text(12,70,'Game Over','fontsize',40,'color','k');
                while(h>0)
                    h=h-1;
                    pause(0.005);
                    set(bd,'ydata',[h-2,h+2]);
                end
            end
        end

        if((xx2<=38)&&(xx2>=22))   %%(2)                      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            if((h>(hh2+28))||(h<(hh2+2)))    %%死亡             %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                cond=0;
                set(handles.kaishi,'enable','on');
                set(handles.qingchu,'enable','on');
                if(record<=score)
                    record=score;
                    set(handles.gaofen,'string',num2str(record));
                end
                sound(y1,Fs1);
                %flysound=0;
                text(12,70,'Game Over','fontsize',40,'color','k');
                while(h>0)
                    h=h-1;
                    pause(0.005);
                    set(bd,'ydata',[h-2,h+2]);
                end
            end
        end
    end

    set(handles.fenshu,'string',num2str(score));
    drawnow;
end


function qingchu_CreateFcn(hObject, eventdata, handles)
function kaishi_CreateFcn(hObject, eventdata, handles)
function fenshu_Callback(hObject, eventdata, handles)
function fenshu_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function gaofen_Callback(hObject, eventdata, handles)
function gaofen_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function shijian_Callback(hObject, eventdata, handles)
function shijian_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
function selecte_level_Callback(hObject, eventdata, handles)
function selecte_level_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

%%%=====================================================================================================================


5信号实时采集(delsys)

function get_original_semg
HOST_IP = '127.0.0.1';
NUM_SENSORS = 2;

global CH1 CH2 plotHandlesEMG data_arrayEMG data_save byteflag flag p1 p2 p3 p4
CH1=5;
CH2=6;
plotHandlesEMG = zeros(NUM_SENSORS,1);
data_arrayEMG = [];
data_save=[];
byteflag=0;
flag=0;
p1=imread('photo\snooze.png');
p2=imread('photo\open.jpg');
p3=imread('photo\grasp.jpg');
p4=imread('photo\end2.jpg');

interfaceObjectEMG = tcpip(HOST_IP,50041);
interfaceObjectEMG.InputBufferSize = 6400;
commObject = tcpip(HOST_IP,50040);

axesHandlesEMG = zeros(NUM_SENSORS,1);
figureHandleEMG = figure('Name', 'EMG Data','Numbertitle', 'off',  'CloseRequestFcn', {@localCloseFigure, interfaceObjectEMG,  commObject});
set(figureHandleEMG, 'position', [400 50 850 600]);

for i = 1:NUM_SENSORS
    axesHandlesEMG(i) = subplot(2,2,i);   
    plotHandlesEMG(i) = plot(axesHandlesEMG(i),0,'-y','LineWidth',1);
    set(axesHandlesEMG(i),'YGrid','on');
    set(axesHandlesEMG(i),'XGrid','on');
    set(axesHandlesEMG(i),'Color',[.15 .15 .15]);
    set(axesHandlesEMG(i),'YLim', [-.0005 .0005]);
    set(axesHandlesEMG(i),'YLimMode', 'manual');
    set(axesHandlesEMG(i),'XLimMode', 'manual');
    set(axesHandlesEMG(i),'XLim', [0 2000]);
    xlabel(axesHandlesEMG(i),'Samples');    
    title(sprintf('EMG %i', i)); 
end
axis;
subplot(2,2,3);

bytesToReadEMG = 2560;
interfaceObjectEMG.BytesAvailableFcn = {@localReadAndPlotMultiplexedEMG,plotHandlesEMG,bytesToReadEMG};
interfaceObjectEMG.BytesAvailableFcnMode = 'byte';
interfaceObjectEMG.BytesAvailableFcnCount = bytesToReadEMG;
drawnow;

try
    fopen(interfaceObjectEMG);
    fopen(commObject);
catch
    localCloseFigure( interfaceObjectEMG, commObject);
    delete(figureHandleEMG);
    error('CONNECTION ERROR: Please start the Delsys Trigno Control Application and try again');
end
fprintf(commObject, sprintf(['START\r\n\r']));  

function localReadAndPlotMultiplexedEMG(interfaceObjectEMG, ~,~,~, ~)
bytesReady = interfaceObjectEMG.BytesAvailable;
bytesReady = bytesReady - mod(bytesReady,2560);    % 1280/(4个字节/样本)/(16通道) = 20个样本
if (bytesReady == 0)
    return;
end

global CH1 CH2 plotHandlesEMG data_arrayEMG data_save byteflag flag p1 p2 p3 p4
data = cast(fread(interfaceObjectEMG,bytesReady), 'uint8');  % data 是每次新来的数据
data = typecast(data, 'single');        
data_save = [data_save; data];

if(size(data_arrayEMG, 1) < 32000)           % 32000/4/16=2000个样本,大概一秒
    data_arrayEMG = [data_arrayEMG; data];
else
    data_arrayEMG = [data_arrayEMG(size(data,1) + 1  :  size(data_arrayEMG, 1));data];
end

byteflag=byteflag+bytesReady;
if byteflag>=12800    % 12800字节=200个样本,约0.1秒
    byteflag=0;
    data_ch1 = data_arrayEMG(CH1:16:end);      
    data_ch2 = data_arrayEMG(CH2:16:end);
    set(plotHandlesEMG(1), 'Ydata', data_ch1); 
    set(plotHandlesEMG(2), 'Ydata', data_ch2);

    flag=flag+1
    switch flag
        case {1,200,400,600,800}
            imshow(p1);
        case {100,500}
            imshow(p2);
        case {300,700}
            imshow(p3);
        case 900
            imshow(p4);
    end
drawnow
end

function localCloseFigure(figureHandle,~,interfaceObject1,  commObject)
global CH1 CH2 data_save 
ch1 = data_save(CH1:16:end);
ch2 = data_save(CH2:16:end);         
save patient_sEMG\semg ch1 ch2          %关闭实时读取显示页面时,保存数据为 .mat格式

data = [ch1,ch2];
load patient_sEMG\Patient_name.mat 
ct = datestr(now,31);
rename = [ct(1:4),ct(6:7),ct(9:10),ct(12:13),ct(15:16),pname];
save (char(strcat('patient_sEMG\',rename)),'data');   % 保存数据在 时间+姓名的mat文件中

if isvalid(interfaceObject1)
    fclose(interfaceObject1);
    delete(interfaceObject1);
    clear interfaceObject1;       
end
if isvalid(commObject)
    fclose(commObject);
    delete(commObject);
    clear commObject;
end
delete(figureHandle);
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值