WPF

Control de servomotores con Arduino y WPF

Los servomotores son motores que integran una circuitería de control que permiten posicionar su eje dentro de un rango. Típicamente los servomotores permiten posicionar el eje con precisión dentro de un rango angular de 0 a 180 grados aproximadamente.

Constan de tres señales de entrada: alimentación, referencia, y señal de control. Utilizando la señal de control se puede posicionar el motor dentro del rango. El control se realiza a través de pulsos de duración determinada de la señal de control. Por ejemplo, para posicionar un servomotor controlado con pulsos de 1msg a 2msg de rango 0-180 grados a 90 grados necesitaríamos suministrar a la señal de control un pulso de 1.5msg de duración.

Se conecta el control del servomotor a la salida digital número 9 del Arduino que programaremos para recibir mensajes de posicionamiento a través del puerto serie, interpretarles y posicionar el servomotor. Para ello utilizaremos las librerías de control de servos (Servo) y de delimitación de mensajes del puerto serie (Messenger).

La inicialización del programa del Arduino se muestra en la siguiente figura donde simplemente indicamos a la librería de control de servos que se utilizará el pin 9 para el control, inicializamos el puerto serie a 115200 baudios e inicializamos la librería de procesado de mensajes.

inicialización control servomotor arduino

Dentro del bucle principal simplemente se leerá el puerto serie esperando mensajes de la forma ‘SERVO n’ donde n es un número de 0 a 178 que indica el ángulo en grados donde se desea posicionar el motor. Una vez interpretado el mensaje satisfactoriamente se posicionara el servomotor y se añadirá un pequeño retraso de 15msg que permita al servomotor posicionarse antes de recibir otra orden.

bucle principal control servomotor arduino 

Para la aplicación WPF diseñaremos una clase con una única propiedad que permita establecer la posición del servo. Haremos que dicha propiedad sea ‘Bindable’ para poderla enlazar de forma natural con los controles de interface gráfico.

La parte principal de dicha clase se muestra en la figura siguiente:

clase controladora de servomotor en .net

y se creará un interface gráfico para el control en XAML enlazando a dicha propiedad de la siguiente manera:

xaml para el interface gráfico del control de servomotores con arduino

El resultado se puede ver en el siguiente video. El código fuente de ambos programas se adjunta en el artículo:

Efecto Sepia con WPF 3.5 SP1

Una de las novedades introducidas en el service pack 1 de la versión 3.5 de Windows Presentation Foundation es la posibilidad de utilizar ‘Pixel shaders’ personalizados como efectos para cualquier componente visual. 

En los comienzos de la fotografía, se aplicaba el tonado sepia a las fotografías en blanco y negro, debido a que dicho proceso hacía más duraderas a las fotografía, y es por ello que muchas de las fotografías antiguas tienen ese característico aspecto basado en tonos marrones.

El siguiente fragmento de código define un 'pixel shader', el cual al aplicarle como efecto a cualquier elemento Visual de una aplicación WPF, le dará esa característica tonalidad sepia.

pixel shader para el efecto sepia

La variable lumaCoeffs es un vector cuyo producto escalar con el vector que define los valores RGB en una pixel de la imagen, nos da el valor de luminancia que corresponde a ese punto. El valor de luminancia se utiliza para posteriormente obtener el color en tono sepia correspondiente a ese valor utilizando la función lerp, que se utiliza para hacer una interpolación lineal entre los dos colores que definen los 'extremos' de la gama de tonalidades sepia.

Por el momento, no podemos utilizar el efecto directamente desde Visual Studio y se necesita compilarle primero utilizando la utilidad fxc del SDK de DirectX. Si hemos guardado el código de la figura anterior en un fichero con el nombre sepia.fx podemos compilarle a un archivo sepia.ps que se podrá utilizar directamente desde WPF de la siguiente manera:

  • fxc  /T ps_2_0 /E main /Fosepia.ps sepia.fx

Una vez compilado el efecto podemos utilizarlo derivando una clase de ShaderEffect llamada, por ejemplo, SepiaEffect, y asignado el archivo sepia.ps a su propiedad PixelShader. Dicho archivo, habrá tenido que ser incluido previamente en el proyecto de Visual Studio y se deberá haber establecido su ‘build action’ como resource.

Para más detalles consultar el código fuente que acompaña a este artículo, que utiliza el efecto tal y como se muestra en la siguiente figura.

Demo del efecto sepia

 Referencia:

Silverlight 2 Beta 1

Ha sido hecha pública la Beta 1 de Silverlight 2 en la conferencia Mix08.

Silverlight 2 permite escribir aplicaciones multiplataforma utilizando cualquier lenguaje .NET (incluyendo C#, VB, JavaScript, IronPython y IronRuby).

Actualmente se pueden ejecutar aplicaciones Silverlight en Windows, Mac y Linux, estando previsto su soporte para dispositivos Symbian (Nokia) y Windows Mobile.

Tal y como cuenta Scott Guthrie, Silverlight incluye un buen subconjunto de las librerías base del .NET Framework (Collections, IO, Generics, Threading, Globalization, RegularExpressions, etc), incluyendo soporte para LINQ.

Para la representación gráfica se cuenta con un subconjunto de WPF, y se incluyen unos cuantos controles.

También se incluye un amplio soporte para la comunicación por red, incluyendo sockets.

Se adjunta el código fuente de la ilustración que acompaña a este artículo.

Primeras impresiones sobre Caliburn

Llevo un tiempo buscando una alternativa a CompositeUI, un buen Framework que me ha facilitado escribir unas cuantas aplicaciones.

En .NET Framework 3.0, Microsoft introdujo un  nuevo sistema de representación (WPF), junto con un nuevo modelo para la construcción de aplicaciones en donde la parte visual de los componentes de la interfaz de usuario típicamente se define utilizando un lenguaje de marcado denominado xaml, al estilo de html. Mediante dicho lenguaje, además, se pueden utilizar las avanzadas capacidades de enlazado a datos (Data Binding) que proporciona el framework.

Sin embargo, CompositeUI es previo a la introducción de las WPF y aunque se han realizado esfuerzos por compaginar ambos entornos, es difícil realizar una buena utilización de lo mejor de cada entorno a la hora de construir una aplicación.

El post de Rob Eisenberg sobre Caliburn (Excalibur) despertó mi interés, así que he estado estudiando un poco su código y la sensación que me ha producido es realmente buena.

El funcionamiento es sencillo, tal como se ve en la aplicación de ejemplo que viene con el código fuente.  El primer paso a realizar es inicializar el sistema, por ejemplo, en el constructor de la aplicación.

public App()
{
    ShellApplication.Start(
        new CustomConfiguration()
        );
}

El objeto suministrado construye una nueva instancia del contenedor a utilizar, en este caso, WindsorContainer, y configura el sistema registrando diversos servicios o componentes.

Entre dichos componentes se encuentra la clase ApplicationPresenter que define el presentador que utilizará la ventana principal de la aplicación (MainWindow) que queda registrado de la siguiente manera.

container.AddComponent("ApplicationPresenter",
    typeof(ApplicationPresenter), typeof(ApplicationPresenter));

A partir del momento que registramos un objeto en el contenedor podemos aprovechar todas las ventajas de la inyección de dependencias, también conocida como inversión de control (IoC).

De forma resumida, bajo inyección de dependencias, las clases de objetos definen que tipo de objetos o interfaces necesitan (dependencias), así como que eventos publican y a cuales desean suscribirse, siendo el contenedor el encargado de proveer a las instancias de los objetos con dichas dependencias. Estos sistemas presentan importantes ventajas desde el punto de vista de flexibilidad, escalabilidad y fiabilidad.

Caliburn provee de dos atributos para la gestión de eventos. Podemos publicar un evento del tipo Action<T> marcándole con el atributo Publish tal y como se ve en el ejemplo siguiente.

[Publish("event://NombreDelEvento")]
public event Action<object> Evento;

Y podemos recibir dicho evento en los objetos que nos interese simplemente definiendo un método que encaje con el delegado del evento, en este caso Action<object> y marcándole con el atributo Subscribe.

[Subscribe("event://NombreDelEvento")]
public void GestorDelEvento(object parametro)
{
    //Acciones a realizar cuando se produzca el evento
}

Cada vez que solicitemos un objeto al contenedor, este se encargará de realizar las gestiones necesarias para 'cablear' automáticamente los eventos.

Por último mencionar que podemos obtener objetos del contenedor utilizando el método estático Resolve. Por ejemplo, para obtener un objeto del tipo ApplicationPresenter previamente registrado utilizaríamos el siguiente código.

ApplicationPresenter presenter = 
    (ApplicationPresenter)Shell.Container
    .Resolve(typeof(ApplicationPresenter));

Caliburn también nos proporciona algunas extensiones de marcado para utilizar en xaml que nos permiten obtener una instancia de un presentador directamente desde una vista asignándole a la propiedad DataContext de la vista así como enlazar directamente ciertos componentes de la interfaz de usuario (botones y objetos de menú) a métodos públicos definidos en el presentador.

Distribuir contenido