Bien, el pequeño proyecto que les traigo el día de hoy es de graficar la entrada analógica de nuestro Arduino, es decir, el Convertidor Analógico Digital.
Este proyecto lo presenté hace varios meses como una práctica de laboratorio en mi querídisima (ROFL) facultad de mi Universidad, FIME UANL.
Vamos a graficarlo en la PC usando una aplicación creada por mi mismo en C#.
Bien, puedo resumir todo esto en unas cuantas etapas:
- Armamos un circuito sencillo donde tengamos conectad a forma de divisor de voltaje nuestro potenciómetro, tu sabes man, una terminal de un extremo a voltaje, la otra a tierra y la terminal de enmedio a una de las entradas analogicas del Arduino.
- Esto sencillamente para al momento de variar la resistencia en el potenciometro, en la terminal de en medio varía el voltaje.
- NOTA: si tenemos un potenciometro logaritmico (los "normales jaja", los mas baratos) nuestra salida sera una función logaritmica (aah en serio!!) de la variación de la resistencia, si requieres un poco de más "precisión" usa uno lineal.
- Nuestro Arduino estará conectado a la PC por el USB
- Por medio de comunicación Serial mandaremos el resultado de la conversión Analógica - Digital cada vez que se requiera refrescar la gráfica
- La aplicación en la PC hecha en C# recibe los datos por Serial y refresca la gráfica.
Circuito
Esquematico del circuito (NOTA: La terminal superior del potenciometro tambien esta conectada a 5V así como a AREF) |
Sketch de Arduino:
void setup() { Serial.begin(115200); analogReference(EXTERNAL);
Inicializa(); } void loop() { Get_Instruccion(); } int Get_Instruccion() { if(Serial.available()) { switch(Serial.read()) { case 'r'://Leer entrada analogica y mandar dato Analog_Read(); break; case 's': //En espera a nueva inicializacion Salir(); break; } } } void Salir() { Inicializa(); //Loop en inicializa esperando nueva inicializacion } void Analog_Read() { int resultado = 0; resultado = analogRead(0); //Leemos el pin analogico 0 en 10bits Serial.write(resultado / 4); //Mandamos el resultado en 8bits por Serial } //Inicializamos la comunicacion serial //Debe mandar una secuencia de caracteres tal que cumplan con el criterio "square" void Inicializa() { int caracter[6]; int i = 0; caracter[0] = 's'; caracter[1] = 'q'; caracter[2] = 'u'; caracter[3] = 'a'; caracter[4] = 'r'; caracter[5] = 'e'; while(1) {//Mientras no se inicialize no sale del ciclo if(Serial.available()) { if(Serial.read() == caracter[i]) { if(i == 5) {//Si es la ultima iteracion Serial.write('a');//escribimos caracter de confirmacion break; //Salimos del while } i++; } } } //Termina While }Explicaré un poco el código para el Arduino:
Al inicio se encuentra la función Inicializa(), esta se encarga de inicializar al Arduino, por así decirlo, lo que hace es esperar a recibir cierta cadena de caracteres por Serial, si esa cadena de caracteres es la correcta entonces se pondrá en marcha el programa principal confirmando esto por mandando un carácter de confirmación por Serial
La función principal Get_Instruccion() ejecuta cierta operación de acuerdo a lo recibido por Serial, si recibe "r" quiere decir que nuestra aplicación en C# esta requiriendo una lectura delo convertidor analógico digital, si recibe "s" es que se debe salir al al bucle de Inicialización.
Parte del Codigo para C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace Practica2_LabDSM
{
public partial class Form_Main : Form
{
Arduino arduino = null;
int[] muestreo;
public
Form_Main()
{
InitializeComponent();
muestreo = new
int[50];
}
private
void groupBox_PuertoSerial_Enter(object sender, EventArgs
e)
{
}
private
void Form_Main_Load(object
sender, EventArgs e)
{
serial_combo(this.comboBox_Puertos);
for (int i = 0; i < 50; i++)
{
//this.chart_Datos.Series[0].Points.AddY(i);
muestreo[i] = 0;
}
}
private
void button_Iniciar_Click(object sender, EventArgs
e)
{
if
(this.comboBox_Puertos.Items.Count > 0)
{
if
(this.comboBox_Puertos.SelectedIndex > -1)
{//Si esta seleccionado algun puerto
arduino = new Arduino(this.comboBox_Puertos.Text, 115200);//Inicializamos arduino a 115200 bauds
arduino.Inicializa_Comunicacion();
this.button_Iniciar.Enabled
= false;
this.button_Stop.Enabled
= true;
timer.Enabled = true;
timer.Start();
}
}
}
//Metodo que primero limpia y despues llena la
comboBox pasada como
//parametro con los puertos serie disponibles
private void serial_combo(ComboBox combo)
{
combo.Items.Clear();
string[]
ports = SerialPort.GetPortNames();
foreach
(string port in
ports)
{
combo.Items.Add(port);
}
}
private
void Form_Main_FormClosed(object sender, FormClosedEventArgs
e)
{
try
{
arduino.CierraPuerto();
}
catch
{
;
}
}
private
void timer1_Tick(object
sender, EventArgs e)
{
Get_Lectura();
}
private
void button_Stop_Click(object
sender, EventArgs e)
{
try
{
arduino.Stop();
arduino.CierraPuerto();
arduino = null;
this.button_Stop.Enabled
= false;
this.button_Iniciar.Enabled
= true;
this.timer.Stop();
this.timer.Enabled
= false;
}
catch
{
arduino = null;
}
}
private
void Get_Lectura()
{
int
punto = 0;
if
(arduino != null)
{
punto = arduino.GetLectura();
this.textBox_caracter.Text
= Convert.ToChar(punto).ToString();
ActualizaGrafica(punto);
}
}
private void
ActualizaGrafica(int punto)
{
RecorreArray(punto);
this.chart_Datos.Series[0].Points.Clear();
for
(int i = 0; i < 50; i++)
{
this.chart_Datos.Series[0].Points.AddY(muestreo[i]);
}
}
private
void RecorreArray(int
punto)
{
int[]
muestreoAux = new int[50];
for
(int i = 0; i < 49; i++)
{
muestreoAux[i + 1] =
muestreo[i];
}
muestreoAux[0] = punto;
muestreo = muestreoAux;
}
private
void button_Refresh_Click(object sender, EventArgs
e)
{
serial_combo(this.comboBox_Puertos);
}
}
}
Este código en sí no ayuda en mucho, sólo se ve bonito =). Es mejor si descargas la solución completa (Tip, está mas abajo)
Screenshot de la Interfaz en C# de la aplicación. |
***********************_________________________________________********************
DESCARGAS:
- Solución de C# para Visual Studio 2010 y Sketch Arduino: aqui (compresión RAR)
- Esquematico: pdf, png
Si cargas el sketch al Arduino y Corres la solución de VS2010 todo debe funcionar perfecto, pero te coloco unas instrucciones para que lo hagas bien y sin dudas:
- Abre con Arduino el archivo prac2_2.ino
- Carga el Sketch al Arduino
- Abre la solcion de VS2010 (Practica2_LabDSM.sln)
- Conecta el Arduino a la PC por USB
- Corre la aplicación de C# (Run)
- Una vez se esté ejecutando el programa selecciona el puerto serie que corresponde a tu arduino, si no aparece da click en Refrescar
- Click en Iniciar
Esto mismo puede ser usado, para muchos propósitos, por ejemplo, si cambias el potenciómetro por un LM35 tendrás un graficador de Temperatura etc...
Usando un poco de imaginación y programación tendrás lo que necesitas!!
Tags:
- Arduino
- Arduino y C#
- Graficar Arduino
- Graficar Convertidor Analogico Digital
- Analog Digital Converter Arduino with C#
- Graficar potenciometro con Arduino en la PC
Hola. muy buen post.
ResponderEliminarEn este momento estoy realizando un trabajo similar, con una PIC18 y codigo en C#. Quisiera preguntarte con que frecuencia se da tu evento Tick del Timer, ya que en este momento tengo problemas con ello (con 50 ms mi aplicación funciona, pero si agrego una sola linea de codigo en C#, mi grafica ya no se actualiza)
Muchas gracias! mi correo es j.santacruz.leon@gmail.com
Saludos, el intervalo del Tick es de 100ms.
EliminarHabría que ver mas o menos tu codigo en C# amigo para pensarle en una solución!
Un Saludo!!
disculpa me podrias decir como debe de ser la conexión al Arduino Uno ya que al tratar de graficar en c# no lo puedo hacer
ResponderEliminarPodrías explicarte mejor amigo Anonimo?
EliminarSimplemente conectas por USB el Arduino a la PC (te debe crear el puerto virtual COM1 sobre Windows).
Saludos
de hecho mi pregunta es como va la conexión del potenciometro al arduino ya que se me a dificultado eso un poco.....!!!!!
ResponderEliminarA ver, creo que no me explique bien en el esquemático de arriba:
Eliminarpin 1 pot -> 5V
pin 2 pot (pin de en medio) -> A0
pin 3 pot -> GND
Y también conectas los 5V a AREF.
Listo
Saludos
Hola tengo una duda, por que inicia la comunicacion serial con "Serial.begin(115200)", me parece creer que la comunicacion serial es de 9200 bauds esto no altera sus datos?, otra duda al momento de hacer la comunicacion al pasar el sensor por un amplificador seguidor y de hay al puerto de la arduino esxiste la posibilidad de que haya perdidas de voltaje esto es mi salida del amplificador mide .21 y recibo en la arduino .20 o .19 esto me parece muy raro no se si tiene alguna idea del porque, gracias
ResponderEliminarHola Ada Espinoza.
Eliminar1.- Hay diferentes velocidades, 115200bds es buena velocidad, mucho mayor a 9200bds, si Arduino la soporta no veo el inconveniente en usarla, y por supuesto no altera en nada los datos (solo se comunican mas rápido, lo cual es mejor). Si quisieras usar otra velocidad (como 9600 ó 9200) tienes que modificar el codigo Arduino y el de C# para sincronizarlos a la misma velocidad (recordando que UART es Asincrono).
2.- Perdidas de voltaje (no creo que eso sea posible allí), lo mas seguro es que el ADC no esté bien calibrado, segura que conectaste el ARef del Arduino?, tienes que calcular también la amplificación. Me explico.
Si tu ARef lo colocas a 5V significa que tienes un rango de 0V a 5V para el ADC de 10 bits del arduino por tanto 5V/1023bit = 4.88mV/bit.
Es decir cuando obtengas un 1 en el ADC quiere decir que estas midiendo 4.88mV cuando obtengas 10 en el ADC estas midiendo 48.8mV y así hasta que obtengas 1023 en el ADC que seran 5V.
etc...
Saludos.
Hola, si es lo que estaba observando que conecto a 5v Aref, pero estaba leyendo que por default esta a 5V por eso considere que podria no conectarlo, pero lo conectare solo que tengo otra duda tambien encontre que si se conecta Aref hay que cambiar a EXTERNAL, cuando se llame la funcion analogRead() para evitar posibles daños a la arduino eso en donde se hace? es que no lo veo en su codigo
EliminarNo la usé porque el valor por default que usa Arduino para la referencia del ADC es 5V, el cableado solo estaba para ejemplificar.
EliminarSi usas referencia a 5V igual no lo conectes, pero si necesitas por ejemplo 3V3, sí deberas conectarlo y agregar la linea de codigo en void setup():
analogReference(EXTERNAL);
http://arduino.cc/es/Reference/AnalogReference
Toda la documentación está en la pagina de Arduino incluyendo como se usan las funciones principales loop y setup.
Saludos
Pues si es de hay de donde saque la informacion que le comentaba y por eso le preguntaba si tenia una idea de por que me pasaba eso, por que estoy considerando igual el ADC por default como viene en la documentacion de 5 volts y 10 bits pero aun asi leo con multimetro en el circuito y me aparece .21 y ya lo que aparece en la arduino haciendo la conversion con el ADC es de .20 o .19, estoy usando un sensor lm35 asi como comenta que de igual forma se puede estaba pensando igual graficarla pero quise primero ver si enviaba los datos bien, pero no puedo pasar de ese paso
EliminarRecuerda que observar afecta lo observado!! Es decir, si mides algo afectarás lo que estas midiendo.
EliminarY si me preguntas a mí obtener de un ADC .20V cuando el valor "real" (entre comillas porque el multímetro puede fallar) es .21V es un excelente resultado, quieres que platiquemos de eso por otro medio, esta conversación esta muy larga para un blog...
Si en verdad deseas precisión en serio tendras que usar mejores instrumentos, amplifica la señal de tu LM25 por un factor de 10 con un Amplificador de Instrumentación (recomiendo el AD624) para obetener 2.1V en lugar de 0.21, referenciar a 5V, y de esa manera poder reducir el error (podrías llegar a medir hasta 5V entonces lo que si mal no recuerdo con un lm35 serían 50ºC)
Si por favor me podria proporcionar un correo electrónico o usted dira, gracias
EliminarEn la parte superior izquierda de este blog estan los links a mi facebook o a mi Google+, el que gustes. (Mi Google+ es mi correo de Gmail).
Eliminaroye lo que se va graficando es dinamico, es decir el eje de tiempo sigue graficando siempre como este video????? http://www.youtube.com/watch?v=k9axoFqIjNY
ResponderEliminarEs parecido sí, pruebalo, no ocupas mas que un potenciometro, un arduino y una pc con windows, es todo...
Eliminarhola hazael estoy haciendo un proyecto con pic y c#, soy nuevo en c# y quiero comunicar con usb-hid, no tengo claro el codigo para que los datos del CAD los capture el pc,
ResponderEliminarsi me puedes orientar te lo agradeceria
Lo siento richard zerpa, aun no he trabajado con comunicación nativa USB (HID, Bulk...) por falta de tiempo, siempre he comunicado con la PC usando UART (sea con FTDI, sea RS232).
EliminarPero en cuanto tenga un chance empezaré con eso y agregaré una entrada al blog.
Saludos.
ayudame con un compilador en ensamblador o tienes alguno t lo agradecere
ResponderEliminarexcelente post, para utilizar el sensor de temp. lm35, debo agregar una conversion al programa para que de la lectura correcta?
ResponderEliminarSí, es muy sencillo agregar un LM35 solo necesitas multiplicar los bits obtenidos (0 -> 1023) por un factor para obtener el Voltaje dado por el LM35 o los grados C, si gustas puedo pasarte uno ya hecho
EliminarHola amigo, podrias explicar o si sabes donde como en un chart (grafico de windows form9 en c#) poder poner el eje en X el tiempo en segundos (o milisengundos) y el valor de Y que sea el valor del potenciometro? graciassss
ResponderEliminarAntes que nada. Puedes modificar este ejemplo para hacer todo lo que desees, está hecho para eso.
Eliminar1.- En este ejemplo el eje X es el tiempo solo camibiale el nombre del Eje a algo como "tiempo (s)" o algo así y de acuerdo a tu tiempo de muestreo (en el timer) cada cuadrícula valdrá tantos segundos o milisegundos.
2.- En este ejemplo el eje Y va de 0 a 256 de acuerdo al valor del voltaje a la salida del potenciometro que pasa por el ADC del Arduino, debido a que el valor del ADC de 0 corresponde a 0V de voltaje hay una relación de Línea Recta entre ambos y se puede resolver por regla de tres simple.
Por tanto para obtener el voltaje V para un valor ADC (entre 0 a 256) la formula sería V = (ADC)(5) / 256.
Aplica lo anterior y podrás covnertir este ejemplo en algo que te sea más útil.
Saludos.
sera complicado hacer todo este proyecto con un arduino uno y graficar estos datos en visual basic 6.0?????????????
ResponderEliminarNo lo creo, puedo apostar a que es muy parecido.
EliminarPero..... para que querrias usar tecnologia de hace 20 años?
(Te lo piden asi en tu universidad supongo :P)
Lo unico que necesitas para tener algo parecido a este proyecto pero en VB 6.0 es:
1. Una libreria para controlar el Puerto Serial.
2. Librerias para crear graficas (tengo entendido que VB6.0 no posee librearias para graficos de manera nativa pero he visto proyectos -y hecho uno- que usa directamente las .dll que vienen al instalar Office.
Suerte.
Corrijo, librearias para graficas (NO graficos) "chart libraries" en gringo.
Eliminarprivate void Form_Main_Load(object sender, EventArgs e)
ResponderEliminar{
serial_combo(this.comboBox_Puertos);
for (int i = 0; i < 50; i++)
{
muestreo[i] = 0;
}
}
Puedes explicarme este bucle?
Pone en 0 todo el array muestreo.
Eliminar(que en teoría debería ya estar en 0)
Me parece que puedes eliminar ese bucle y el programa seguiría funcionando bien.
Saludos
Hola, Quiero realizar este proyecto pero en ves de usar un arduino con un chipKit Max32, que en pocas palabras es lo mismo que un Mega pero con mayor velocidad de reloj, Que debo cambiarle en el codigo de c# y en el del el arduino,
ResponderEliminarSalu2
Hola Luis.
EliminarPara usar el chipkit en teoria no deberias tener que modificar nada.
Just as is.
Carga el codigo de Arduino al chipKit por medio de la IDE que proporciona digilent (la roja) y listo.
Saludos
Buenas tardes, alguien que tenga el .rar que me lo pueda pasar de favor D: me urge y no lo puedo bajar, no sé si es mi PC o el internet :v
ResponderEliminarPuedes enviar todos los datos que desees. Pero la forma en la que los envías depende de ti, usando un arduino conectado a la PC estarás ocupando un solo puerto Serie, por ese puerto serie puedes enviar todo un byte a la vez, dependerá de como programes los algoritmos de envío y recepcion de datos. No es algo que se pueda ver demasiado directo pero es posible hacerlo por supuesto.
ResponderEliminarUna pregunta: como podria enviar y visualizar mas de 255 osea no dividir el valor del potenciometro sobre 4.....
ResponderEliminarrevicir Serial.write(resultado / 4); //Mandamos el resultado en 8bits por Serial ......
como podria ver en el textbox de 0 a 2014.... si le quito /4 quiero que muestre 1024. pero no lo muestra
Hola.
EliminarUna forma interesante de poder enviar datos mayores a un byte sería creando una especie de ciclo. Tanto en el Arduino como en la PC.
Dicho ciclo enviará tantos datos desees.
Algo como:
Arduino:
while(existen_datos)
{
send(dato);
}
PC:
while(not_finish)
{
datos += read(dato);
}
Puedes crear tu propio "protocolo" de transmisión, algo que le indique a la PC cuantos datos va a recibir O enviar un dato específico para romper el ciclo (como un cero).
Saludos.
hola amigo muy interesante el proyecto pero tengo una duda si deseo conectar un potenciometro a un pic y que los datos sean enviados a arduino! como podria recibir esos datos enviados en arduino??? para luego ser enviados a c#.
ResponderEliminarSaludos
No entiendo el cometario de potenciómetro logarítmico(los normales) de toda la vida los dos son potenciómetros normales, tanto los lineales como los logarítmicos, otra cosa es que tu uses los logarítmicos para todo y por ello digas que son los normales es decir los que normalmente usas tu
ResponderEliminarbuenas, con una molestia si se quisiera duplicar o triplicar la grafica que se tendria que modificar???
ResponderEliminarCasi todo...
EliminarExcelente proyecto pero yo queria hacer lo mismo pero con 5 graficas y poner 5 potenciometros y de vez de medir datos quiero graficar voltajes de 0 a 5v esto es posible pero como ?
ResponderEliminarCompletamente posible, pero vas a requerir bastante programación
Eliminaramigo si deseo cambiar el potenciometro por un LM35 como quedaria el codigo modificad
ResponderEliminarNo tienes que modificar nada si lo único que quieres es graficar la forma de la onda. Habrá que hacer variaciones si necesitas traficar otro tipo de datos, como temperatura por ejemplo.
Eliminarcomo se puede unir el codigo del otro sensor arduino al archivo en c shart
ResponderEliminarcomo se puede unir el codigo del otro sensor MPU6050 arduino al archivo en c sharp, que parte del codigo se debiese modificar?
ResponderEliminarSi dicho sensor tiene una salida Analógica de entre 0 y 5v es perfectamente compatible. Solo tienes que quitar el pot y reemplazarlo por tu sensor.
ResponderEliminar