2011-02-24 20 views
8

Hola chicos, estoy tratando de crear un script de matlab (archivo m) que será controlado por un script de VBA externo.Controlar un script de matlab (Pausa, Restablecer)

El script de matlab debe hacer la misma operación cada vez (incluso los parámetros cambian, pero este no es el caso en este caso) para un cierto número de bucles. Si lo veo bien, puede utilizar MATLAB Funktions en VBA así: http://www.mathworks.de/help/techdoc/matlab_external/f135590.html#f133975

Mi principal problema es cómo implementar la parte de MATLAB de este problema ... en el momento en que mi parte de control es el siguiente:

start.m:

run = 1; 
reset = 0; 
while run ~= 0  % Loop until external reset of 'run' to '0' 
    if reset ~= 0 
     doReset(); % Reset the parameters for the processing 
     reset = 0; 
     disp('I did a reset'); 
    end 

    disp('I am processing'); 
    doProcess(); 
    pause(1) 
end 
disp('I am done'); 

la parte reinicio funciona muy bien mientras se cambia el valor por el guión, pero cuando intento manualmente para cambiar el valor de 'correr' o 'reset' a cualquier otro valor en mi espacio de trabajo, no pasa nada ... mi secuencia de comandos no aborta, tampoco lo hace la re set-if do it's work ... me parece que el script no reconoce ningún cambio en el espacio de trabajo ?!

después, las variables 'ejecutar' y 'restablecer' se establecerán o desactivarán mediante el script de VBA. ¿Hay alguna razón plausible por la que no pueda abortar el bucle a mano?

¡Gracias por cualquier consejo!

saluda, poeschlorn

Editar:

Parece que el script carga las variables una vez antes de comenzar de nuevo y nunca en tiempo de ejecución ... ¿existe la posibilidad de tener acceso a una variable explícita espacio de trabajo ?

Edición 2:

uso de Matlab 2010b sin cajas de herramientas adicionales en el momento

Datos 3:

descubrí, que hay varios 'espacios de trabajo' o RAM en Matlab. Si mi función se está ejecutando, las variables se almacenan en el espacio de trabajo 'base' (?), Que no es el espacio de trabajo de matlab en el que puede hacer clic y cambiar cada valor. De modo que tengo que acceder a este siniestro espacio 'base' y cambiar la bandera 'ejecutar' a cero. ¿Algunas ideas?

+0

r.e. Edición 3: No hay nada siniestro, las funciones tienen su propia pila de variables y el área de trabajo otra (¡no quiere que una función de usuario cambie sus variables de espacio de trabajo y viceversa!). Si necesita acceder a una variable globalmente a través del espacio de trabajo y las funciones del usuario, use la palabra clave ** global **, es decir, 'ejecución global' tanto en su área de trabajo como en cualquier función que utilice: http://www.mathworks.com/ ayuda/techdoc/matlab_prog/f0-38052.html # f0-38470 - esto es asumiendo que su bucle no está bloqueando la interfaz externa ... –

+0

@Edit 3: Existe tal función: ['assigning'] (http: //www.mathworks.com/help/techdoc/ref/assignin.html) que es _muy_ no recomendado. – Juhl

+0

@Juhl: ¿Por qué esta función es muy desaconsejable? No veo ningún punto en contra de eso O.o – poeschlorn

Respuesta

1

¿Es su secuencia de comandos un script m-file o una función?

Si se trata de una función, perderá el alcance de las variables del espacio de trabajo y por eso no está funcionando. Me enciendo el código en una función como esta:

function processRun(run,reset) 
    while run ~= 0  % Loop until external reset of 'run' to '0' 
     if reset ~= 0 
     doReset; % Reset the parameters for the processing 
     reset = 0; 
     disp('I did a reset'); 
     end 

     disp('I am processing'); 
     [run,reset] = doProcess; 
     pause(1) 
    end 

entonces se puede establecer los valores de la carrera y restablecer evertime se llama a la función de VBA.

Si tiene una secuencia de comandos, intente eliminar las líneas de ejecución y restauración desde la parte superior, y establezca sus valores en el área de trabajo antes de ejecutar la secuencia de comandos. Creo que está sobrescribiendo los valores de su espacio de trabajo ejecutando el archivo de script.

+0

El código en sí es todo el contenido de un archivo m. Tengo un pequeño problema para entender cuál es tu código ... si lo veo bien, tengo que llamar a la función processRun (...) una vez? y luego puedo cambiar mis valores en el espacio de trabajo? – poeschlorn

+0

Si no tiene una definición de función, creo que puede estar sobrescribiendo las variables del espacio de trabajo en el script. Ver mi edición a mi respuesta original. –

+0

Me parece que la variable 'reset' se restablece a 0 si y solo si, por alguna razón, se cambió a 1 en el intervalo de tiempo entre el cheque anterior y el actual. Esa razón sería su script de VBA y no veo ningún problema lógico. Un misterio para mí –

4

Supongo que su problema es simplemente que su bucle está bloqueando la ejecución de la interfaz externa. Mientras se ejecuta el bucle, no puede acceder a las otras interfaces.

Quería hacer algo similar: permitir el control de un bucle de matlab mediante un programa externo (ya sea Ruby u otra instancia de matlab). La solución más flexible por el momento fue el uso de UDP. Hay una gran caja de herramientas llamada PNET para matlab, y supongo que VB también debe tener una biblioteca de socket. Simplemente abro un puerto UDP en ambos lados y uso comandos de texto simples para controlar y dar retroalimentación.

obj.conn = pnet('udpsocket', 9999); 
command = ''; 
while run ~= 0 
    nBytes = pnet(obj.conn, 'readpacket'); 
    if nBytes > 0 
     command = pnet(obj.conn, 'read', nBytes, 'string'); 
    end 
    switch command 
     case '--reset--' 
      doReset(); % Reset the parameters for the processing 
      reset = 0; 
      disp('I did a reset'); 
     case '--abort--' 
      run = 0; 
      disp('Going to abort'); 
     case '--echo--' 
      pnet(obj.conn, 'write', '--echo--'); 
      pnet(obj.conn, 'writepacket', remoteAddress, remotePort); 
    end 
    doProcess(); 
end 

De esta manera puedo construir mi propia interfaz de control extensible sin preocuparse por el bloqueo del bucle, que puede funcionar multiplataforma y multilenguaje, puede funcionar dentro de una máquina o de toda la red.

ACTUALIZACIÓN: Para hablar entre dos clientes UDP, debe configurar dos puertos UDP complementarios, ambos son clientes (este ejemplo es todo en matlab, obj obj aquí es una estructura, en mi caso es una clase i envolver alrededor de la funcionalidad pnet):

obj = struct(); 
obj.success = 0; 
obj.client1Port = 9999; 
obj.client2Port = 9998; 
obj.client1Address = '127.0.0.1'; 
obj.client2Address = '127.0.0.1'; 
obj.conn1 = pnet('udpsocket', obj.client1Port); 
obj.conn2 = pnet('udpsocket', obj.client2Port); 

pnet(obj.conn1, 'write', '--echo--') 
pnet(obj.conn1, 'writepacket', obj.client2Address, obj.client2Port); 

nBytes = pnet(obj.conn2, 'readpacket'); 
if nBytes > 0 
    command = pnet(obj.conn2, 'read', nBytes, 'string'); 
    if regexpi(command,'--echo--') 
     obj.success = obj.success+1; 
     fprintf('Client 2 recieved this message: %s\n',command); 
     pnet(obj.conn2, 'write', '--echo--') 
     pnet(obj.conn2, 'writepacket', obj.client1Address, obj.client1Port); 
    end 
end 

nBytes = pnet(obj.conn1, 'readpacket'); 
if nBytes > 0 
    command = pnet(obj.conn1, 'read', nBytes, 'string'); 
    if regexpi(command,'--echo--') 
     obj.success = obj.success+1; 
     fprintf('Client 1 got this back: %s\n',command); 
    end 
end 

if obj.success == 2 
    fprintf('\nWe both sent and received messages!\n'); 
end 
+0

Wow, esto es absolutamente increíble. ¿Puedes decirme dónde puedo encontrar la biblioteca PNET? Parece que Mathworks no tiene toda esa caja de herramientas en ninguna parte, pero algunas inoficiales están listas para cargar ... ¿puedes decirme cuál estás usando? – poeschlorn

+1

Sí, estoy usando pnet que ya está precompilado (para Win, OS X y Linux) de la caja de herramientas de psicofísica: [PTB] (http://psychtoolbox.org/wikka.php?wakka=HomePage), puede descargarlo y extraer el directorio, o raspar el svn [aquí] (http://svn.berlios.de/wsvn/osxptb/trunk/Psychtoolbox/PsychHardware/iViewXToolbox/tcp_udp_ip/?#a92ec166f430377948ced499fe2456e27) - la caja de herramientas en sí se encuentra [ aquí] (http://www.mathworks.com/matlabcentral/fileexchange/345-tcpudpip-toolbox-2-0-6) - puede usar TCP (confiable con más sobrecarga) o UDP (sin conexión y más rápido); UDP es más fácil de configurar. –

+1

Tenga en cuenta que también puede usar UDP directamente en Matlab si tiene la caja de herramientas Control de instrumentos [documentada aquí] (http://www.mathworks.com/help/toolbox/instrument/f16-54297.html). ** prefiero ** PNET, ya que puede enviar no solo tipos de datos simples, sino incluso objetos de matlab oop, que de otro modo serían casi imposibles de serializar y enviar a través de la red (debilidad del propio matlab). También hay una alternativa de interfaz Java Matlab para PNET [aquí] (http://www.mathworks.com/matlabcentral/fileexchange/24525-a-simple-udp-communications-application) –

1

lo sentimos, no tengo representante suficiente para hacer un comentario así que voy a citar aquí:

@ Adam Leadbetter: Gracias, esto tiene sentido . La única cosa que habe problemas con es cómo hacer una pausa (después de este reinicio y luego reanudar) la secuencia de comandos cuando se ha iniciado por run = 1 como parámetro ... - poeschlorn 25 de febrero a las 7:17

Si ¿Desea salir del circuito una vez que el restablecimiento se ha establecido en uno, y luego esperar que el ciclo continúe nuevamente una vez run = 1 que es más o menos lo mismo que comenzar de nuevo?

function processRun() 
run = 1; 
while run ~= 1 
    run = doProcess(); 
end 

si doProcess() vuelve 0 entonces la función processRun() terminará (como el comportamiento que desea tener cuando se restablece), la próxima vez que se llama processRun comienza de nuevo, con "reset" valores de/por defecto.

¿O me está faltando algo?

+0

Si te estás perdiendo algo, ¡yo también lo estoy! Creo que lo que has mostrado aquí es una forma más centrada en Matlab del código que la función que envolví. –

+0

Hola, Juhl, tu código es absolutamente claro, pero no estoy seguro de que puedas resolver mi problema. En este caso, doProcess() necesita obtener cualquier criterio para abortar el script o devolver '0'. Esta creteria tiene que provenir de una fuente externa. Mi problema es CÓMO tener acceso a una interrupción externa. – poeschlorn