NetMF – Serial Port – Echo response App

Some people ask me to have any soft start guide using microframework serial port. Well, as you know in desktop apps is the typical “Hello World”, the translation into serial port apps are “Echo for response”.

This code shows how to open the serial port to read incoming bytes and resend it as an echo. Is the first brick to check that the UART is all right! After this lab, you are ready to build your own DCE/DTE protocol and play serial commands between both sides.

Imports System.IO.Ports
Imports System.Text
 
Imports Microsoft.SPOT
Imports Microsoft.SPOT.Hardware
 
Module EchoResponse
 
    Private WithEvents SerialComm As SerialPort =
        New SerialPort("COM1", 9600, Parity.None, 8, StopBits.One)
 
    Private DataReceived As String = ""
    Private PortActivity As New OutputPort(CType(55, Cpu.Pin), False)
 
    Sub Main()
        SerialComm.Open()
        ' include your functions here
        Thread.Sleep(Timeout.Infinite)
    End Sub
 
    Private Sub SerialIn() Handles SerialComm.DataReceived
        PortActivity.Write(True)
        Dim Length As Integer = SerialComm.BytesToRead
        Dim Frame(Length) As Byte
        SerialComm.Read(Frame, 0, Length)
        SerialComm.Write(Frame, 0, Length)
        DataReceived = ""
        PortActivity.Write(False)
    End Sub
End Module

Enjoy!! PepLluis,

Auto Data Entry Form’s

Muchos de los lectores de este blog muestran interés por ejemplos entorno a Windows forms y SQL Express, no hay duda y soy consciente de que este articulo no forma parte de esos “avances que están por venir” ni representa a ninguna novedad tecnológica actual; obviamente lejos de herramientas tan actuales como LightSwitch, sin embargo me complace compartirlo con vosotros pues creo que puede ser un buen soporte para ayudar en la comprensión de ciertos usos y técnicas sobre todo para los que empiezan.

Como digo, este es uno de esos artículos intemporales en varios aspectos, pues describe metodologías “retro” utilizando los clásicos SQL y Forms… si embargo no quiero que perdáis de vista que los “usos” y “técnicas” utilizadas pueden traspasar esa barrera atemporal y utilizarse en cualquier escenario actual… incluso en las nuevas aplicaciones “Metro Style” J

Al diseñar algunos ejemplos, disfruto partiendo de una plantilla de “Consola”, pues debido a la naturaleza y el propósito del mismo, esta concesión me permite “Salirme fuera de pistas” de lo que sería una aplicación comercial, pero a su vez me permite disfrutar de la libertad de construir algo desde los cimientos.

Como su nombre indica el objetivo del siguiente laboratorio es interactuar con la conocida base de datos para pruebas “NorthWnd”, utilizaremos la estructura de cualquiera de sus tablas para “Autogenerar” nuestro form de entrada (con todos sus textboxes) que nos permita añadir un nuevo registro a la tabla a través de un “Enlazador”. A modo de flecos para darle un poco mas de interés, he creído divertido incluir una pequeña funcionalidad que nos permita recorrer la tabla buscando todos los registros según la coincidencia del país introducido el textbox de búsqueda (con LINQ), y un par de botones para recorrer el enlazador, avanzando o retrocediendo a partir de la posición actual en el datagridview.

No creo que sea necesario un detalle mas exhaustivo, prefiero pasar al código, aunque antes quedo a vuestra disposición para continuar y desarrollar esta conversación según consideréis de interés.
Que disfrutéis
J

PepLluis,

Imports System.Drawing
Imports System.Windows.Forms
 
Imports System.Data
Imports System.Data.SqlClient
 
'
'
' Establecer un punto de entrada. Esto es una aplicacion VB
'
Module MiAplicacion
    Sub Main()
        Dim Ventana As New frmDinamico
        Ventana.Show()
        Application.Run()
    End Sub
End Module
 
 
Public Class frmDinamico
    Inherits Form
    'Punto de Inicializacion de nuestra ventana
 
    'Definicion de Variables de contexto
    Private MiConexion As New SqlConnection(
     "Data Source=.\SQLEXPRESS;" +
     "AttachDbFilename=D:\Bd_App\NORTHWND.MDF;" +
     "Integrated Security=True;Connect Timeout=30;User Instance=True")
 
    ' Adaptador, Enlazador y juego de datos para la tabla clientes
    Private MiAdaptador As New SqlDataAdapter("Select * from Customers", MiConexion)
    Private MiEnlazador As New BindingSource
    Private MiDataSet As New DataSet
 
    ''' <summary>
    ''' Al lanzar la ejecucion de la app
    ''' </summary>
    ''' <remarks></remarks>
    Sub New()
        Try
            Inicializacion()
        Catch fallo As Exception
            Messagebox.Show(fallo.Message, "Error Grave... no puedo continuar")
            End
        End Try
    End Sub
 
    ''' <summary>
    ''' Inicializar/Construir los objetos de la aplicacions
    ''' </summary>
    ''' <remarks></remarks>
    Sub Inicializacion()
        Me.Text = "Auto Entry Data Form"
        ' Crear y Enlazar datos
        Dim MiCommandBuild As New SqlCommandBuilder(MiAdaptador)
        MiConexion.Open()
        MiAdaptador.Fill(MiDataSet)
        MiENlazador.DataSource = MiDataSet.Tables(0)
        Dim MiDataGridView As New DataGridView
        MiDataGridView.DataSource = MiENlazador
        MiDataGridView.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top
        MiDataGridView.Dock = DockStyle.Top
        '
        ' Añadir los controles al Form
        Me.Controls.Add(MiDataGridView)
        Me.Controls.AddRange({
            New TextBox With {.Name = "Buscar", .Text = "", .Dock = DockStyle.Bottom},
            New Button With {.Name = "Añadir", .Text = .Name, .Dock = DockStyle.Bottom},
            New Button With {.Name = "Avanza", .Text = .Name, .Dock = DockStyle.Bottom},
            New Button With {.Name = "Retrocede", .Text = .Name, .Dock = DockStyle.Bottom}
            })
' Apuntar los handlers a sus funciones         AddHandler Me.Controls("Añadir").Click, AddressOf Nuevo         AddHandler Me.Controls("Avanza").Click, AddressOf Avanzar         AddHandler Me.Controls("Retrocede").Click, AddressOf Retroceder         AddHandler Me.Controls("Buscar").TextChanged, AddressOf Seleccionar         Me.Controls("Buscar").Focus()     End Sub     ''' <summary>     ''' Al final la ejecucion de la app     ''' </summary>     ''' <remarks></remarks>     Sub Fin() Handles Me.FormClosed         Application.ExitThread()         End     End Sub     ''' <summary>     ''' Query para seleccionar solo los registros coincidentes     ''' con la cadena de texto introducida en el TextBox 'Buscar'     ''' </summary>     ''' <remarks></remarks>     Sub Seleccionar()         MiENlazador.DataSource =                         (                          From S In MiDataSet.Tables(0)                           Where S.Item("Country").Contains(Me.Controls("Buscar").Text)                           Select Nombre = S.Item("CompanyName"),                                  Ciudad = S.Item("City")                         ).ToList     End Sub     ''' <summary>     ''' Enlazador : MoveNext     ''' </summary>     ''' <remarks></remarks>     Sub Avanzar()         MiEnlazador.MoveNext()     End Sub     ''' <summary>     ''' Enlazador : MovePrevious     ''' </summary>     ''' <remarks></remarks>     Sub Retroceder()         MiEnlazador.MovePrevious()     End Sub     ''' <summary>     ''' Crear un nuevo form conteniendo un TextBox y una etiqueta     ''' con su descripcion para cada columna de la tabla     ''' </summary>     ''' <remarks></remarks>     Sub Nuevo()         Dim AutoForm As New Form         AutoForm.Name = "Nuevo"         AutoForm.Text = "Data Entry Form"         Dim Pos_x As Integer = 5         Dim Pos_y As Integer = 10         Dim Etiqueta As Label         Dim Entrada As TextBox         For Each col As DataColumn In MiDataSet.Tables(0).Columns             Etiqueta = New Label             Etiqueta.Location = New Point(Pos_x, Pos_Y)             Etiqueta.Text = Col.ColumnName             Pos_X += Etiqueta.Width             Entrada = New TextBox             Entrada.tag = Etiqueta.Text             Entrada.Location = New Point(Pos_X, Pos_Y)             AutoForm.Controls.AddRange(New Control() {Etiqueta, Entrada})             Pos_x = 5             Pos_Y += Etiqueta.Height + 5         Next         AutoForm.height = Pos_y + 75         AutoForm.Show()     End Sub End Class

Convertir la trama recibida de ASCii a HEX

Respondiendo a la pregunta de David : «Al leer del puerto serie leo su contenido pero me lo muestra como ASCii, existe alguna forma para visualizar su contenido en HEX o Decimal?»

    Function AsciiToHex(TramaRecibida As String, ConvertToHex As BooleanAs String
        '
        ' Conversion de un string a una cadena de Hexadecimales / decimales
        For Each c As Char In TramaRecibida
            If ConvertToHex Then
                AsciiToHex += "0x" + Hex(Asc(c)) + " "
            Else
                AsciiToHex += Asc(c).ToString + " "
            End If
        Next
        Return AsciiToHex
    End Function

Para invocar la funcion :

        Dim RespuestaEnHex As String = AsciiToHex("abcABCD_CualquierTextoRecibido"True)
        Dim RespuestaEnDEC As String = AsciiToHex("abcABCD_CualquierTextoRecibido"False)

Espero  te sea util.
Saludos,
PepLluis,

La madurez de MicroFramework 4.2, Vuelve el Basic!

Si bien es cierto que han pasado 25 años desde los primeros micro controladores “todo en uno” de Intel  MCS51 que incluían un interprete “Basic” como “Firmware” y hacían nuestras delicias permitiéndonos encender y apagar “lucecitas” con instrucciones muy simples y sin tener que ahondar en profundos conocimientos… nadie discute que paulativamente aquella tecnología dejo de apasionarnos al ritmo que aparecieron nuevos procesadores y electronicas con mucho mas atractivo; de hecho incluso nos avergonzaba tener que numerar las líneas, pero también es cierto que después de aquellos primeros pinitos quedamos fuera de juego inmersos en complejos y potentes sistemas de 16/32b que embebían todo el chip set en un solo encapsulado… ya sabéis el resto de 32 a 64 y la necesidad de acumular un montón de conocimiento previo sobre el medio para poder terminar encendiendo y apagando nuestra querida “lucecita” 🙂 con la diferencia de haber tenido que escribir un monton de codigo mas … complejidad obliga!

Quizás buscando la moraleja se resumiría desde hace algunos años en la nostalgia de NO tener a mano aquellos viejos cacharros que nos permitían activar una salida de pulso con modulación simplemente con : 10 PWM 100,100,1000 , no quiero aburriros explicando como las nuevas plataformas y procesadores se alejaron cada vez mas del “Basic listo para funcionar” y se aproximaron al preámbulo técnico entre compiladores librerías, inicializaciones y descarga de binarios en la ‘flash’ para poder terminar haciendo lo mismo en un procesador super complejo. De ahi la gran aficion a chips como el PICAXE o Basic STAMP… En resumen sin darnos cuenta nos alejábamos definitivamente del concepto “Basic”.

La suerte y la buena noticia para todos los que sentimos pasión por estos artilugios que nos abstraen a esa mágica mezcla entre electrónica y lenguajes, es que a punto de pronunciar el tipico : “El Basic a Muerto” Viva el BASIC!!, vuelve a aparecer a escena la implementacion de «Visual Basic» para projectos del MicroFramework 4.2, que como sabeis solo estaba disponible para C# hasta la fecha. 

Que os parecería cacharrear utilizando visual studio y expresiones como las que siguen :

        While (True)
            Encender(Led_Azul)
            Esperar(1)
            Apagar(Led_Azul)
            Esperar(1)
            If "Expresion" = "Cierta" Then
                Encender(Alarma_1)
            Else
                Apagar(Alarma_1)
            End If
        End While

Uno de los avances mas importantes en este sentido, es la posibilidad de desarrollar y depurar aplicaciones con o sin electrónica, pues podemos crearnos nuestros propios dispositivos emuladores y en el mejor de los casos si disponemos del dispositivo físico podemos depurar directamente sobre la electrónica a traves del puerto serie o USB.

La proposición es fácil, bienvenidos al mundo de los apasionantes sistemas embebidos “on chip”, después de largos años de desarrollo .NET MicroFramework alcanza una madurez envidiable en su versión 4.2, convirtiéndose en un excelente ‘open source’ y como ya he dicho antes, incorporando por fin la posibilidad crear nuestros nuevos proyectos recuperando Visual Basic.

Me permito postearos esta sencilla introducción, como preámbulo a todo un apartado que nos puede dar mucho de que hablar, pues ciertamente muchos lectores de este blog siempre han mostrado especial interés en controlar dispositivos de una forma amigable. Esperando vuestros comentarios para ir dando formato a los futuros artículos.

Aquí tenéis el código completo para un hardware genérico. Creo que es muy interesante motivaros en la forma que podemos adaptar la redacción de nuestras funciones de una forma altamente inteligible.

Imports Microsoft.SPOT
Imports Microsoft.SPOT.Hardware
 
Public Module Principal
 
    Sub Main()
        While (True)
            Encender(Led_Azul)
            Esperar(1)
            Apagar(Led_Azul)
            Esperar(1)
            If "Expresion" = "Cierta" Then
                Encender(Alarma_1)
            Else
                Apagar(Alarma_1)
            End If
        End While
    End Sub
 
End Module
 
' Definicion de funciones
Module Funciones
    
    Sub Encender(pin As OutputPort)
        pin.Write(True)
    End Sub
 
    Sub Apagar(pin As OutputPort)
        pin.Write(False)
    End Sub
 
    Sub Esperar(segundos As Integer)
        Thread.Sleep(segundos * 1000)
    End Sub
End Module
 
' Constructores y definicion de nombres
Module GPIOs
    Public Led_Azul As OutputPort = New OutputPort(CType(55, Cpu.Pin), False)
    Public Alarma_1 As OutputPort = New OutputPort(CType(18, Cpu.Pin), False)
End Module

Que lo disfrutéis!
PepLluis,