Éste es un programa realizado con Visual Basic Express 2013 (entorno de programación gratuito y que te puedes bajar de la página de Microsoft) para poder visualizar y guardar los datos de tensión leídos a través de Arduino.
This is a program made with Visual Basic Express 2013 (free tool for programmers that you can download from the Microsoft web page) that is useful to see and save tension data read through Arduino.
El programa está en su segunda versión y por supuesto, como suele ser usual en estos casos, no me hago responsable de cualquier daño que pueda hacer el programa.
This is a program made with Visual Basic Express 2013 (free tool for programmers that you can download from the Microsoft web page) that is useful to see and save tension data read through Arduino.
El programa está en su segunda versión y por supuesto, como suele ser usual en estos casos, no me hago responsable de cualquier daño que pueda hacer el programa.
Elegí Visual Basic por la facilidad y rapidez con la que se puede hacer un programa para entorno Windows con él. Está todo muy "masticado". Me hubiese gustado utilizar otro lenguaje de programación como Phyton, aunque fuese por probar, pero a día de hoy estoy más acostumbrado a Visual Basic, por no decir que no tengo ni idea de Phyton. Tal vez algún día ...
Para Arduino el programa es:
/*
Comunicación serial para Arduino
*/
int dato;
void setup(){
Serial.begin(9600); // La misma velocidad de conexión debe ser usada en el programa de Windows
}
void loop(){
dato=analogRead(A0); // Ver la siguiente imagen, donde se puede ver la entrada analógica utilizada.
Serial.println(dato); // Envía el valor leído
delay(1000);
/* Importante: "delay" debe tener el mismo valor que el intervalo de muestreo
del programa de Windows (ver variable intMuestreo) */
}
/*
Comunicación serial para Arduino
*/
int dato;
void setup(){
Serial.begin(9600); // La misma velocidad de conexión debe ser usada en el programa de Windows
}
void loop(){
dato=analogRead(A0); // Ver la siguiente imagen, donde se puede ver la entrada analógica utilizada.
Serial.println(dato); // Envía el valor leído
delay(1000);
/* Importante: "delay" debe tener el mismo valor que el intervalo de muestreo
del programa de Windows (ver variable intMuestreo) */
}
Y las pruebas se pueden hacer por ejemplo con el siguiente conexionado (R es un potenciómetro. En mi caso usé uno de 100K), en este caso con la Arduino Mega 2560:
A0 se trata de una entrada analógica que leerá una señal de entre 0 y 5 V, convirtiéndolo a un valor proporcional de entre 0 y 1023, es decir, si el A0 nos está diciendo que tiene una señal de 614, por ejemplo, nos está diciendo que tiene una señal de aproximadamente 3V (exactamente será el resultado de 614·(5/1023)).
Para Visual Basic la GUI será algo como lo que sigue (captura de una de las primeras versiones):
O también algo como lo que sigue (se corresponde con la segunda versión):
Como se puede ver tiene un selector del puerto COM, puerto que se elegirá según sea a cual se conecta Arduino, un botón para conectar y desconectar (son el mismo botón, que cambia de texto y de color según sea su función), un área donde se representará las tensiones leídas a lo largo del tiempo, un botón de "Guardar como ... " por si se quiere guardar los datos leídos en una hoja *.csv (si se desconecta y se vuelve a conectar se seguirán guardando los datos donde se dejó) y además hay una serie de datos que se muestran en tiempo real (uno de ellos notareis que está en un formato distinto, pero es para probar una función distinta a la usada en los otros campos).
Para la GUI se eligen las siguientes propiedades (es posible que algunas se elijan en el propio programa y no directamente en el editor de la GUI):
Ventana principal
Name Form1
Size 600; 400
Text Conexión Serial 2015 (9600 bps)
Selector del puerto de conexión (herramienta ComboBox)
Name cbxPuertos
Botón conectar/desconectar (herramienta Button)
Name btnConectar
Text Conectar
Gráfica (herramienta Chart)
Name chGrafica
Botón Guardar como (herramienta Button)
Name btnGuardarComo
Caja de texto de la ruta para Guardar como
Name tbxRuta
Multiline True
Caja de texto de la última lectura
Name tbxActual
Caja de texto del valor mínimo
Name tbxMinimo
Caja de texto del valor máximo
Name tbxMaximo
Caja de texto del valor medio acumulado
Name tbxMedia
Caja de texto del numero de lecturas correctas
Name tbxLecturas
Caja de texto del numero de lecturas incorrectas
Name tbxIncorrectas
Y como elementos o herramientas insertadas no visibles:
Dialogo guardar como (herramienta SaveFileDialog)
Name dlgGuardarComo
Cronometro o timer (herramienta Timer)
Name tmrTimer
Comunicación o puertos serial (herramienta SerialPort)
Name spPuertos
Para Visual Basic el programa es:
REM Programa realizado con fines formativos. Sin garantías de ningún tipo
REM Autor:JAIS
REM Fecha: 06/04/2015
REM Versión: 2
REM Función: Comunicación serial con Arduino y graficado de los datos procedentes de él
REM Nombre: ComunicacionSerial2015
'Para poder acceder al sistema de archivos
Imports System
Imports System.IO
Imports System.IO.StreamWriter
'Para poder dibujar el gráfico
Imports System.Windows.Forms.DataVisualization.Charting
Public Class Form1
Const vConexion As Integer = 9600 'En esta ocasión no daremos opción de conectar a otras velocidades que no sean la usual
Const intMuestreo As Integer = 1000 'En milisegundos (este valor debe ser el usado también en el programa de Arduino)
Const digRedondeo As Integer = 2 'Redondearemos todos los números o lecturas a 2 decimales
Const factorConv As Double = 5 / 1023 'Factor de conversión entre dato de Arduino (valor interno) y tension real de entrada.
Const tensionMax As Double = 5 'Valor de la tensión máxima de entrada que permite Arduino
Const nMaxMedidas As Integer = 200 'REVISAR PARA QUE AL RECONECTAR SE REINICIE EL CONTADOR
'Se definen e inicializan las variables
Dim valorMinimo As Double = tensionMax 'Se elige el valor máximo disponible para que salga lo que salga sea menor a este valor
Dim valorMedio As Double = 0.0 'Valor medio de todos lso valores leidos hasta el momento
Dim valorActual As Double = 0.0 'Último valor leido
Dim cLecturas As Integer = 0 'Contador de lecturas correctas
Dim cIncorrectas As Integer = 0 'Contador de lecturas incorrectas
Dim strBufferIn As String = Nothing 'Se guardara en esta variable lo que se lea del puerto serial
Dim ruta As String = Nothing 'Ruta del archivo donde se guardan las lecturas
Dim archivo As Stream = Nothing 'Archivo donde se guardan las lecturas
Dim strStreamWriter As StreamWriter = Nothing
Private Sub Form1_FormClosing1(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
If ruta <> Nothing Then
strStreamWriter.Close() 'Se ejecuta al cerrar el formulario.
archivo.Close() 'Se cierra tambien el archivo
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Para ahorrarse poner un monton de With. Notar que se pone gbxProgreso y no Me porque
' realmente los controles a los que nos referimos están dentro de ese grupo
' Así se inicializan todas las propiedas que son iguales de los textBox del grupo Progreso.
'------------------------------------------------------------------------------------------------------------
For Each thisTbx As TextBox In gbxProgreso.Controls.OfType(Of TextBox)()
With thisTbx
.Enabled = False 'Para que no se puedan introducir datos, sólo leerlos.
.Text = "0" 'Por ejemplo. También podia poner n/a o similares.
.BackColor = Color.White
.TextAlign = HorizontalAlignment.Center
.BorderStyle = BorderStyle.None
End With
Next thisTbx
'Inicializar al cargar la ventana
'------------------------------------
tmrTimer.Enabled = False 'Debe estar desabilitado al principio
tbxRuta.Enabled = False 'Siempre está deshabilitado
tbxRuta.Text = "Aún no ha seleccionado ningún archivo"
'Se cargan los puertos disponibles y se añaden al combobox
'-----------------------------------------------------------------------
cbxPuertos.Items.Clear() 'Se limpia el combobox
For Each puertoDisponible As String In My.Computer.Ports.SerialPortNames
cbxPuertos.Items.Add(puertoDisponible)
Next
If cbxPuertos.Items.Count > 0 Then
cbxPuertos.Text = cbxPuertos.Items(0) 'Elegir el primer puerto de la lista como puerto visible
btnConectar.Enabled = True
btnGuardarComo.Enabled = True
btnConectar.BackColor = Color.Red
btnConectar.ForeColor = Color.White
Else
MessageBox.Show("Ningun puerto encontrado.")
btnConectar.Enabled = False
btnGuardarComo.Enabled = False
cbxPuertos.Items.Clear()
cbxPuertos.Text = ("")
End If
'Se acondiciona la gráfica (la ventana del gráfico donde se representan los datos leídos).
'--------------------------------------------------------------------------------------------------------
With chGrafica
.Legends("Legend1").Enabled = False 'Legend1 es el nombre por defecto que le da Visual a la leyenda de la gráfica. En principio sólo una si no se especifica otra cosa.
.Series("Series1").ChartType = SeriesChartType.Line 'Series1 es el nombre por defecto que el ada Visual a la serie de datos. En principio sólo una si no se añaden más.
With .ChartAreas("ChartArea1") 'También se puede poner ... ChartAreas(0)
.AxisX.Interval = 2
.AxisX.LabelStyle.Angle = 0
.AxisX.Maximum = 10
.AxisX.Title = "Medida nº"
.AxisY.Title = "Tensión [V]"
.AxisX.MajorGrid.Enabled = False
.AxisY.MajorGrid.LineColor = Color.LightBlue
End With
End With
End Sub
Private Sub btnGuardarComo_Click(sender As Object, e As EventArgs) Handles btnGuardarComo.Click
'Ventana de dialogo Guardar Como
'------------------------------------------
dlgGuardarComo.Filter = _
"Archivo de valores separados por punto y coma (*.csv)|*.csv|Archivos de texto (*.txt)|*.txt|Todos los archivos (*.*)|*.*"
dlgGuardarComo.ShowDialog()
ruta = dlgGuardarComo.FileName 'Incluye toda la ruta de acceso, no solo el nombre del archivo
If ruta <> Nothing Then
tbxRuta.Text = ruta
Try
If File.Exists(ruta) Then
archivo = File.Open(ruta, FileMode.Truncate) 'Para que no se mezclen datos primero hay que eliminar los datos anteriores
Else
archivo = File.Create(ruta)
End If
strStreamWriter = New StreamWriter(archivo, System.Text.Encoding.Default)
Catch ex As Exception
MessageBox.Show("Problemas al crear/abrir el archivo. Acceso denegado")
End Try
End If
End Sub
Private Sub btnConectar_Click(sender As Object, e As EventArgs) Handles btnConectar.Click
'Cambia el texto del botón conectar según estemos conectados o no.
If btnConectar.Text = "Conectar" Then
conectar()
Else
desconectar()
End If
End Sub
Private Sub tmrTimer_Tick(sender As Object, e As EventArgs) Handles tmrTimer.Tick
strBufferIn = spPuertos.ReadExisting 'Guardamos en nuestra variable lo que hay en el puerto, si es que hay algo
Static Dim valorMaximo As Double = 0.0
'Sólo si hay una lectura positiva se ejecuta el codigo del programa
If strBufferIn <> "" Then
Try
If Not IsNumeric(strBufferIn) Then
Throw New Exception("Lectura: " & strBufferIn)
End If
valorActual = CDbl(strBufferIn) * factorConv 'Lo metemos en un try por si no es posible convertir el valor que llega de arduino
'Se convierte a voltios (máximo 5 V) el valor dado por Arduino (máximo 1023)
tbxActual.Text = CStr(Math.Round(valorActual, digRedondeo))
'Verificar si es el valor mínimo
If valorActual < valorMinimo Then
valorMinimo = valorActual
tbxMinimo.Text = CStr(Math.Round(valorMinimo, digRedondeo))
End If
'Verificar si es el valor máximo
If valorActual > valorMaximo Then
valorMaximo = valorActual
tbxMaximo.Text = String.Format("{0:E}", Math.Round(valorMaximo, digRedondeo))
End If
'Calcular el valor medio
cLecturas += 1
tbxLecturas.Text = cLecturas.ToString()
If cLecturas > 1 Then
valorMedio = (cLecturas * valorMedio + valorActual) / (cLecturas + 1)
Else
valorMedio = valorActual
End If
tbxMedia.Text = Math.Round(valorMedio, digRedondeo).ToString()
If cLecturas > 10 Then
With chGrafica.ChartAreas(0).AxisX
.Minimum = .Minimum + 1
.Maximum = .Maximum + 1
End With
End If
chGrafica.Series("Series1").Points.AddY(valorActual)
If ruta <> Nothing Then
strStreamWriter.WriteLine(tbxLecturas.Text & ";" & tbxActual.Text)
End If
Catch ex As Exception
tbxActual.Text = ex.Message
cIncorrectas += 1
tbxIncorrectas.Text = CStr(cIncorrectas)
End Try
strBufferIn = ""
spPuertos.DiscardInBuffer() 'Se limpia el buffer de entrada para que no registre más datos o los repita
If cLecturas = nMaxMedidas Then
desconectar()
End If
End If
End Sub
Sub desconectar()
With btnConectar 'Se cambia el botón de conectar a estado de desconectado
.Text = "Conectar"
.BackColor = Color.Red
.ForeColor = Color.White
End With
tmrTimer.Enabled = False
spPuertos.Close() 'Se cierra la conexión pero no el archivo, por si hay que volver a escribir al reconectarse.
End Sub
Sub conectar()
With btnConectar 'Se cambia el botón de conectar a estado de conectado
.Text = "Desconectar"
.BackColor = Color.LightGreen
.ForeColor = Color.Black
End With
With spPuertos 'Se abre el puerto de conexion
.PortName = cbxPuertos.Text
.BaudRate = vConexion
.Open()
End With
With tmrTimer 'Se habilita el timer
.Enabled = True
.Interval = intMuestreo 'En milisegundos
End With
End Sub
End Class
Y finalmente el resultado es: