Arduino - Osciloscopio multicanal (Osciloscopio del hombre pobre)

Arduino - Osciloscopio multicanal (Osciloscopio del hombre pobre)

Tabla de contenido:

Anonim

Estoy presentando actualizaciones de software para el Osciloscopio Arduino (Osciloscopio del hombre pobre) que permiten visualizar dos o tres canales de datos simultáneamente. Las características principales son idénticas al osciloscopio original, con la excepción de algunas líneas que agregué para mejorar la capacidad de los usuarios para estimar cuáles son los voltajes medidos reales. RuiSantos encontró el software original en la red y compartió esta información en su instructivo y en su sitio web. Muchas gracias RuiSantos por compartir esto.

Tenga en cuenta que este "dispositivo" no es un osciloscopio real. La mayoría de las características que esperaría de un osciloscopio no están disponibles. Sin embargo, si te gusta visualizar datos que no son demasiado rápidos, entonces esto es simplemente increíble. Por ejemplo, lo usaré para verificar una secuencia de datos que voy a crear con un par de 555 temporizadores. Pero esa es otra historia.

Características del software / osciloscopio:

Adquisición y visualización de datos de 1 canal (original y más rápido), de 2 canales (más lento) o de 3 canales (incluso más lento)

Rango de señal de 0-5 V determinado por hardware, es decir, Arduino

Zoom de escala de tiempo de entrada / salida presionando +/-

Línea roja = datos del canal 1

Línea verde = datos del canal 2

Línea azul = datos del canal 3

Líneas grises = pasos de 0.5V

Líneas amarillas oscuras = pasos 1V

Funcionalidad de captura de pantalla: al hacer clic en el botón del mouse, el programa almacena una captura de pantalla de su ventana de datos. Básicamente, esto le permite "detener" los datos y mirarlos. Conveniente para el análisis de datos. Para hacer que esto funcione, debe ingresar a la sección "draw ()" del programa y ajustar la ruta del archivo a una que funcione con su computadora.

Todo lo que necesitas es un Arduino y un cable USB.

Suministros:

Paso 1: El Código

Aparte del software, no hay nada nuevo en configurar esto. Para su comodidad, estoy repitiendo los pasos enumerados en la instrucción de RuiSantos.

1)

Procesamiento de descarga. El procesamiento es un entorno de programación que se ve y se siente idéntico al entorno de programación Arduino. También tiene el mismo precio, lo que significa que es gratis. Haga click aquí para descargar. Configúralo como configuraste tu software Arduino. Se ejecuta como el IDE de Arduino.

El procesamiento se puede usar para mostrar imágenes, líneas u objetos e interactuar con ellos. Esta es mi primera experiencia con el programa.

2)

Dependiendo de cuántos canales quiera tener, cargue uno de los "Bocetos de Arduino" que se muestran a continuación en su Arduino. El código para enviar y recibir los datos se basó en el código de este gran capítulo de libro que explica cómo enviar múltiples campos de texto desde un Arduino a la computadora y procesarlos con Procesamiento.

3)

Luego toma el respectivo "Bosquejo de procesamiento" de abajo y lo copia en Procesamiento

4)

Cambie la "Ruta" en la última línea del código a una ruta de su elección.

5)

Ejecutarlo en Procesamiento.

6)

Asegúrese de que sus señales no superen los 5 V antes de conectarlas a:

Channel1 => pin0 analógico

Channel2 => pin1 analógico

Channel3 => pin2 analógico

Notas:

  • Los bocetos de procesamiento utilizan el puerto serie 0 como estándar. Es posible que tenga que ajustar este valor si utiliza un puerto serie diferente.
  • Documenté cada paso en el programa con muchos comentarios. Por lo tanto, el código debe ser "autoexplicativo".
  • Experimentalmente descubrí que para algunas configuraciones los datos pueden no mostrarse en tiempo real debido a varias razones interconectadas:
    • El retraso que se establece en el programa Arduino no es lo suficientemente grande. => Se envían demasiados datos. => El tiempo de procesamiento se acumula. => Los datos se muestran con retraso. Para comprobar los retrasos, apagué manualmente la fuente de alimentación que estaba conectada a las entradas analógicas de mi Arduino mientras observaba la respuesta de voltaje que muestra Procesando. Hice esto por un período prolongado de tiempo. Si la respuesta fue inmediata, quedé satisfecho.
    • Si hace zoom con "+", mostrará menos datos. Esto tiene un efecto directo sobre la posibilidad de retrasos, ya que se necesita menos tiempo de procesamiento.
    • La ventana es demasiado ancha. => Demasiados valores x necesitan ser cambiados. => Demasiado tiempo para los cálculos. => Elegí un tamaño de ventana mucho más pequeño que el tamaño de mi pantalla para abordar este efecto.
Disfrute de los múltiples canales en su osciloscopio de hombres pobres y hágame saber si se le ocurre alguna mejora.

Código de 2 canales Arduino:

/ * CommaDelimitedOutput sketch * /

#define ANALOG_IN_Ch1 0

# define ANALOG_IN_Ch2 1

configuración del vacío ()

{

Serial.begin (9600);

}

bucle de vacío ()

{

int val1 = analogRead (ANALOG_IN_Ch1); / * Lee valores desde Pin0 analógico = Canal1 * /

int val2 = analogRead (ANALOG_IN_Ch2); / * Lee valores desde Pin1 analógico = Canal2 * /

Serial.print ('H'); / * Encabezado único para identificar el inicio del mensaje * /

Serial.print (",");

Serial.print (val1, DEC);

Serial.print (",");

Serial.print (val2, DEC);

Serial.print (","); / * Tenga en cuenta que una coma se envía después del último campo * /

Serial.println (); / * enviar un cr / lf * /

retraso (50); // Esto puede ser más rápido que 50ms.

}

Código de 3 canales de Arduino:

/ * CommaDelimitedOutput sketch * /

#define ANALOG_IN_Ch1 0

# define ANALOG_IN_Ch2 1

# define ANALOG_IN_Ch3 2

configuración del vacío ()

{

Serial.begin (9600);

}

bucle de vacío ()

{

int val1 = analogRead (ANALOG_IN_Ch1); / * Lee valores desde Pin0 analógico = Canal1 * /

int val2 = analogRead (ANALOG_IN_Ch2); / * Lee valores desde Pin1 analógico = Canal2 * /

int val3 = analogRead (ANALOG_IN_Ch3); / * Lee valores desde Pin2 analógico = Canal3 * /

Serial.print ('H'); / * Encabezado único para identificar el inicio del mensaje * /

Serial.print (",");

Serial.print (val1, DEC);

Serial.print (",");

Serial.print (val2, DEC);

Serial.print (",");

Serial.print (val3, DEC);

Serial.print (","); / * Tenga en cuenta que una coma se envía después del último campo * /

Serial.println (); / * enviar un cr / lf * /

retraso (50);

}

Procesando código de 2 canales:

/*

* Osciloscopio

* Da una representación visual de tres pines analógicos en tiempo real.

*

* Este software amplía la cantidad del canal de una versión anterior.

* La versión anterior fue un proyecto que forma parte de Accrochages.

* Ver

*

* El autor de este software adaptado no tiene relación con los Acrochages.

* Les agradece por la gran plantilla y la inspiración para escribir este software.

*

* La siguiente declaración fue parte del software original.

* Esto es para tu información.

*

* (c) 2008 Sofian Audry ([email protected])

*

* Este programa es software libre: puedes redistribuirlo y / o modificarlo.

* bajo los términos de la Licencia Pública General de GNU tal como fue publicada por

* la Free Software Foundation, ya sea la versión 3 de la Licencia, o

* (a su elección) cualquier versión posterior.

*

* Este programa se distribuye con la esperanza de que sea útil, * pero SIN NINGUNA GARANTÍA; sin ni siquiera la garantía implícita de

* COMERCIABILIDAD o APTITUD PARA UN PROPÓSITO PARTICULAR. Ver el

* GNU General Public License para más detalles.

*

* Debes haber recibido una copia de la Licencia Pública General de GNU

* junto con este programa. Si no, ve .

*/

importación processing.serial. *;

Serie myPort; / * Crear objeto de clase serial * /

char HEADER = 'H'; / * carácter para identificar el inicio de un mensaje * /

corto LF = 10; / * Alimentación de línea ASCII * /

short portIndex = 0; / * determina el puerto USB utilizado * /

int val = {-1, -1}; / * Variable utilizada para la función getY, 2 posiciones para 2 canales * /

int valuesCh1; / * Las siguientes tres variables mantendrán los datos de la ventana en la memoria para que puedan ser empujados y mostrados * /

int valuesCh2;

zoom flotante; / * Definir "zoom" como variable de punto flotante * /

configuración del vacío ()

{

// tamaño (1014, 690); / * Abre una ventana de tamaño específico, tamaño máximo de la pantalla de mi computadora portátil, pueden producirse problemas de retraso * /

tamaño (600, 400); / * pantalla más pequeña => menos para calcular => sin problemas de retardo * /

myPort = new Serial (this, Serial.list () portIndex, 9600); / * Abra el puerto al que está conectada la placa y use la misma velocidad (9600 bps) * /

valuesCh1 = new int width; / * Define la matriz con tantos elementos como x-pixel en la ventana, utilizados para trazar datos del Canal1 * /

valuesCh2 = new int width; / * … de Channel2 * /

zoom = 1.0f; / * Comenzar con el factor de zoom 1x * /

suave(); / * Dibujo de imágenes con bordes lisos * /

}

/ * Esta función convierte un valor de datos de canal en píxeles mostrados desde

* parte superior del gráfico (que es la posición 0)

* esta función devuelve un valor entero * /

int getY (int val)

{

return (int) (altura - val / 1023.0f * (altura - 1));

}

/ * Función que lee los datos de la serie que fueron enviados por arduino.

* Pone una matriz con los tres valores del arduino.

* La función se llama en la función de dibujo * /

int getData ()

{

int ChValues ​​= {-1, -1}; / * Definir matriz para esta función * /

Mensaje de cadena = myPort.readStringUntil (LF); / * Leer en la cadena de datos seriales enviados por arduino * /

if (message! = null) / * Haga esto solo cuando se recibió un mensaje válido completo * /

{

String data = message.split (","); / * Dividir el mensaje separado por comas en sus segmentos * /

if (data 0.charAt (0) == HEADER) / * Verifique el carácter del encabezado en el primer campo, siempre verdadero para el mensaje completo * /

{

para (int i = 1; i <data.length-1; i ++) / * Omitir el encabezado y terminar cr y lf => mirar solo los tres puntos de datos * /

{

ChValues ​​i-1 = Integer.parseInt (datos i); / * Escribir los datos del canal en la matriz, cambié de datos a la matriz en 1 debido al encabezado * /

}

}

}

devuelve ChValues; / * Devuelve la matriz ChValues ​​que contiene datos de canal * /

}

/ * Esta función empuja todos los puntos de datos de la ventana una posición más hacia la izquierda, luego agrega el punto de datos que se acaba de leer * /

void pushValue (int value)

{

para (int i = 0; i

{

valoresCh1 i = valoresCh1 i + 1; / * Mover el punto de datos en la posición * /

valoresCh2 i = valoresCh2 i + 1;

}

valuesCh1 width-1 = value 0; / * Agregar punto de datos * /

valuesCh2 width-1 = value 1;

}

/ * Esta función dibuja los datos en la ventana * /

dibujar líneas vacías ()

{

int displayWidth = (int) (ancho / zoom); / * Calcula el ancho de la ventana, considerando el cambio x si se establece un zoom * /

int k = valuesCh1.length - displayWidth; / * Esto calcula la posición hasta la cual se muestran los puntos de datos * /

int x0 = 0; / * El valor de x a la izquierda de la ventana (= 0) se asigna a x0 y se usa para todos los canales * /

int ya0 = getY (valuesCh1 k); / * El valor y del último punto mostrado se asigna a ya0 para el canal 1 * /

int yb0 = getY (valuesCh2 k); / * El valor y del último punto mostrado se asigna a yb0 para el canal 2 * /

para (int i = 1; i

{

k ++; / * Incremento k para el siguiente punto de datos * /

int x1 = (int) (i * (width-1) / (displayWidth-1)); / * Calcular el siguiente valor de x * /

int ya1 = getY (valuesCh1 k); / * Obtener el siguiente valor de y para el canal 1 * /

int yb1 = getY (valuesCh2 k); / * Obtener el siguiente valor de y para channel2 * /

strokeWeight (2); / * Dibuja líneas más gruesas * /

carrera (255, 0, 0); / * Dibuja una línea roja para el canal1 * /

línea (x0, ya0, x1, ya1); / * Trazar un segmento de línea para el canal 1 * /

carrera (0, 255, 0); / * Dibuja una línea verde para channel2 * /

línea (x0, yb0, x1, yb1); / * Trazar un segmento de línea para el canal 2 * /

x0 = x1; / * Shift x valor para calcular los siguientes segmentos de línea * /

ya0 = ya1; / * Cambie el valor de y para el canal 1 para calcular los siguientes segmentos de línea * /

yb0 = yb1; / * Cambie el valor de y para que el canal 2 calcule los siguientes segmentos de línea * /

}

}

/ * Esta función dibuja líneas de cuadrícula en la ventana

* He espaciado las líneas para que representen pasos de 10% y 20% en 2 colores diferentes

* Para señales de 5 V máx., Es decir, pasos de 0.5 y 1.0 V * /

void drawGrid ()

{

carrera (150, 150, 0);

línea (0, altura / 5, ancho, altura / 5);

línea (0, altura * 2/5, ancho, altura * 2/5);

línea (0, altura * 3/5, ancho, altura * 3/5);

línea (0, altura * 4/5, ancho, altura * 4/5);

carrera (150, 150, 150);

línea (0, altura / 10, ancho, altura / 10);

línea (0, altura * 3/10, ancho, altura * 3/10);

línea (0, altura * 5/10, ancho, altura * 5/10);

línea (0, altura * 7/10, ancho, altura * 7/10);

línea (0, altura * 9/10, ancho, altura * 9/10);

}

/ * Esta función permite acercar el eje x de los datos.

* Se ejecuta en segundo plano y se nota cuando se presiona la tecla derecha

* Acercar presionando "+"

* Alejar con presionar "-" * /

void keyReleased ()

{

interruptor (llave)

{

caso '+':

zoom * = 2.0f;

println (zoom);

if ((int) (ancho / zoom) <= 1)

zoom / = 2.0f;

descanso;

caso '-':

zoom / = 2.0f;

si (zoom <1.0f)

zoom * = 2.0f;

descanso;

}

}

/ * Esta es la función principal que llama a las otras funciones.

* Esta función se ejecuta continuamente * /

empate vacío ()

{

fondo (1); / * Establece el fondo de la ventana * /

drawGrid (); / * Dibuja la cuadrícula en la ventana * /

val = getData (); / * Lee los datos de los tres canales enviados por el arduino a una matriz * /

if (val 0! = -1) / * Si los datos están en el primer canal, realice la función * /

{

pushValue (val); / * Empuja los datos hacia abajo una posición y agrega un nuevo punto de datos * /

}

dibujar líneas(); / * Agregar el siguiente conjunto de datos a la ventana * /

si (mousePressed) / * realiza una acción cuando se presiona el botón del mouse * /

{

guardar ("/ YourPathHere / OsciData1.png"); / * Guardar captura de pantalla de la ventana de datos, pero cuidado con la imagen se sobrescribirá con el segundo clic del mouse * /

}

}

Procesando código de 3 canales:

/*

* Osciloscopio

* Da una representación visual de tres pines analógicos en tiempo real.

*

* Este software amplía la cantidad del canal de una versión anterior.

* La versión anterior fue un proyecto que forma parte de Accrochages.

* Ver

*

* El autor de este software adaptado no tiene relación con los Acrochages.

* Les agradece por la gran plantilla y la inspiración para escribir este software.

*

* La siguiente declaración fue parte del software original.

* Esto es para tu información.

*

* (c) 2008 Sofian Audry ([email protected])

*

* Este programa es software libre: puedes redistribuirlo y / o modificarlo.

* bajo los términos de la Licencia Pública General de GNU tal como fue publicada por

* la Free Software Foundation, ya sea la versión 3 de la Licencia, o

* (a su elección) cualquier versión posterior.

*

* Este programa se distribuye con la esperanza de que sea útil, * pero SIN NINGUNA GARANTÍA; sin ni siquiera la garantía implícita de

* COMERCIABILIDAD o APTITUD PARA UN PROPÓSITO PARTICULAR. Ver el

* GNU General Public License para más detalles.

*

* Debes haber recibido una copia de la Licencia Pública General de GNU

* junto con este programa. Si no, ve .

*/

importación processing.serial. *;

Serie myPort; / * Crear objeto de clase serial * /

char HEADER = 'H'; / * carácter para identificar el inicio de un mensaje * /

corto LF = 10; / * Alimentación de línea ASCII * /

short portIndex = 0; / * determina el puerto USB utilizado * /

int val = {-1, -1, -1}; / * Variable utilizada para la función getY, 3 posiciones para 3 canales * /

int valuesCh1; / * Las siguientes tres variables mantendrán los datos de la ventana en la memoria para que puedan ser empujados y mostrados * /

int valuesCh2;

int valuesCh3;

zoom flotante; / * Definir "zoom" como variable de punto flotante * /

configuración del vacío ()

{

// tamaño (1014, 690); / * Abre una ventana de tamaño específico, el tamaño máximo de la pantalla de mi computadora portátil, retrasa los problemas a través de la ventana * /

tamaño (600, 400); / * pantalla más pequeña => menos para calcular => sin problemas de retardo * /

myPort = new Serial (this, Serial.list () portIndex, 9600); / * Abra el puerto al que está conectada la placa y use la misma velocidad (9600 bps) * /

valuesCh1 = new int width; / * Define la matriz con tantos elementos como x-pixel en la ventana, utilizados para trazar datos del Canal1 * /

valuesCh2 = new int width; / * … de Channel2 * /

valuesCh3 = new int width; / * … de Channel3 * /

zoom = 1.0f; / * Comenzar con el factor de zoom 1x * /

suave(); / * Dibujo de imágenes con bordes lisos * /

}

/ * Esta función convierte un valor de datos de canal en píxeles mostrados desde

* parte superior del gráfico (que es la posición 0)

* esta función devuelve un valor entero * /

int getY (int val)

{

return (int) (altura - val / 1023.0f * (altura - 1));

}

/ * Función que lee los datos de la serie que fueron enviados por arduino.

* Pone una matriz con los tres valores del arduino.

* La función se llama en la función de dibujo * /

int getData ()

{

int ChValues ​​= {-1, -1, -1}; / * Definir matriz para esta función * /

Mensaje de cadena = myPort.readStringUntil (LF); / * Leer en la cadena de datos seriales enviados por arduino * /

if (message! = null) / * Haga esto solo cuando se recibió un mensaje válido completo * /

{

String data = message.split (","); / * Dividir el mensaje separado por comas en sus segmentos * /

if (data 0.charAt (0) == HEADER) / * Verifique el carácter del encabezado en el primer campo, siempre verdadero para el mensaje completo * /

{

para (int i = 1; i <data.length-1; i ++) / * Omitir el encabezado y terminar cr y lf => mirar solo los tres puntos de datos * /

{

ChValues ​​i-1 = Integer.parseInt (datos i); / * Escribir los datos del canal en la matriz, cambié de 1 a la matriz debido al encabezado * /

}

}

}

devuelve ChValues; / * Devuelve la matriz ChValues ​​que contiene datos de canal * /

}

/ * Esta función empuja todos los puntos de datos de la ventana una posición más hacia la izquierda, luego agrega el punto de datos que se acaba de leer * /

void pushValue (int value)

{

para (int i = 0; i

{

valoresCh1 i = valoresCh1 i + 1; / * Mover el punto de datos en la posición * /

valoresCh2 i = valoresCh2 i + 1;

valuesCh3 i = valuesCh3 i + 1;

}

valuesCh1 width-1 = value 0; / * Agregar punto de datos * /

valuesCh2 width-1 = value 1;

valuesCh3 width-1 = value 2;

}

/ * Esta función dibuja los datos en la ventana * /

dibujar líneas vacías ()

{

int displayWidth = (int) (ancho / zoom); / * Calcula el ancho de la ventana, considerando el cambio x si se establece un zoom * /

int k = valuesCh1.length - displayWidth; / * Esto calcula la posición hasta la cual se muestran los puntos de datos * /

int x0 = 0; / * El valor de x a la izquierda de la ventana (= 0) se asigna a x0 y se usa para todos los canales * /

int ya0 = getY (valuesCh1 k); / * El valor y del último punto mostrado se asigna a ya0 para el canal 1 * /

int yb0 = getY (valuesCh2 k); / * El valor y del último punto mostrado se asigna a yb0 para el canal 2 * /

int yc0 = getY (valuesCh3 k); / * El valor y del último punto mostrado se asigna a yc0 para el canal 3 * /

para (int i = 1; i

{

k ++; / * Incremento k para el siguiente punto de datos * /

int x1 = (int) (i * (width-1) / (displayWidth-1)); / * Calcular el siguiente valor de x * /

int ya1 = getY (valuesCh1 k); / * Obtener el siguiente valor de y para el canal 1 * /

int yb1 = getY (valuesCh2 k); / * Obtener el siguiente valor de y para channel2 * /

int yc1 = getY (valuesCh3 k); / * Obtener el siguiente valor de y para channel3 * /

strokeWeight (2); / * Dibuja líneas más gruesas * /

carrera (255, 0, 0); / * Dibuja una línea roja para el canal1 * /

línea (x0, ya0, x1, ya1); / * Trazar un segmento de línea para el canal 1 * /

carrera (0, 255, 0); / * Dibuja una línea verde para channel2 * /

línea (x0, yb0, x1, yb1); / * Trazar un segmento de línea para el canal 2 * /

trazo (0, 0, 255); / * Dibuja una línea azul para channel3 * /

línea (x0, yc0, x1, yc1); / * Trazar un segmento de línea para el canal 3 * /

x0 = x1; / * Shift x valor para calcular los siguientes segmentos de línea * /

ya0 = ya1; / * Cambie el valor de y para el canal 1 para calcular los siguientes segmentos de línea * /

yb0 = yb1; / * Cambie el valor de y para que el canal 2 calcule los siguientes segmentos de línea * /

yc0 = yc1; / * Cambie el valor de y para que el canal 3 calcule los siguientes segmentos de línea * /

}

}

/ * Esta función dibuja líneas de cuadrícula en la ventana

* He espaciado las líneas para que representen pasos de 10% y 20% en 2 colores diferentes

* Para señales de 5 V máx., Es decir, pasos de 0.5 y 1.0 V * /

void drawGrid ()

{

carrera (150, 150, 0);

línea (0, altura / 5, ancho, altura / 5);

línea (0, altura * 2/5, ancho, altura * 2/5);

línea (0, altura * 3/5, ancho, altura * 3/5);

línea (0, altura * 4/5, ancho, altura * 4/5);

carrera (150, 150, 150);

línea (0, altura / 10, ancho, altura / 10);

línea (0, altura * 3/10, ancho, altura * 3/10);

línea (0, altura * 5/10, ancho, altura * 5/10);

línea (0, altura * 7/10, ancho, altura * 7/10);

línea (0, altura * 9/10, ancho, altura * 9/10);

}

/ * Esta función permite acercar el eje x de los datos.

* Se ejecuta en segundo plano y se nota cuando se presiona la tecla derecha

* Acercar presionando "+"

* Alejar con presionar "-" * /

void keyReleased ()

{

interruptor (llave)

{

caso '+':

zoom * = 2.0f;

println (zoom);

if ((int) (ancho / zoom) <= 1)

zoom / = 2.0f;

descanso;

caso '-':

zoom / = 2.0f;

si (zoom <1.0f)

zoom * = 2.0f;

descanso;

}

}

/ * Esta es la función principal que llama a las otras funciones.

* Esta función se ejecuta continuamente * /

empate vacío ()

{

fondo (1); / * Establece el fondo de la ventana * /

drawGrid (); / * Dibuja la cuadrícula en la ventana * /

val = getData (); / * Lee los datos de los tres canales enviados por el arduino a una matriz * /

if (val 0! = -1) / * Si los datos están en el primer canal, realice la función * /

{

pushValue (val); / * Empuja los datos hacia abajo una posición y agrega un nuevo punto de datos * /

}

dibujar líneas(); / * Agregar el siguiente conjunto de datos a la ventana * /

si (mousePressed) / * realiza una acción cuando se presiona el botón del mouse * /

{

guardar ("/ YourPathHere / OsciData1.png"); / * Guardar captura de pantalla de la ventana de datos, pero cuidado con la imagen se sobrescribirá con el segundo clic del mouse * /

}

}