Osciloscopio casero
Durante mis estudios en ingeniería necesité en múltiples ocasiones un osciloscopio para poder trabajar con señales. Sin embargo, debido a los altos costos de estos equipos, no me los podía permitir. Aquí es donde el ingenio y algo de conocimiento me llevaron a usar Arduino y Processing para construir un osciloscopio casero.
El IDE de Arduino viene con múltiples ejemplos y aquí hay uno clave para este proyecto. Dentro de la sección de Ejemplos, encontramos la categoría Communication y ahí mismo está Graph.
El código de Arduino sería de esta manera:
void setup() {
// inicializamos la comunicacion Serial
Serial.begin(9600);
}
void loop() {
// leemos el pin análogo A0 y lo enviamos por el puerto serial
Serial.println(analogRead(A0));
// esperamos un poco para que el conversor analogo a digital se establize
//tras la última lectura
delay(2);
}
Como podemos ver, es bastante sencillo. Partimos de inicializar el módulo serial, y de ahí nos mantenemos en un ciclo, en el cual leemos el dato que nos llega por el puerto análogo y este valor lo escribimos en el puerto serial a modo de string.
El código de Processing es el siguiente:
import processing.serial.*;
Serial myPort; // creamos la variable del puerto serial
int xPos = 1; // inicializamos la posicion horizontal
float inByte = 0;
void setup () {
// ajustamos el tamaño de la ventana:
size(400, 300);
// imprimiremos la lista de puertos disponibles
println(Serial.list());
// en la mayoría de los casos solo exitiría un elemento en el puerto sería (el arduino), pero de no ser así ajusta el valor 0, segun corresponda
myPort = new Serial(this, Serial.list()[0], 9600);
// espera hasta que tenga datos en el puerto serial
myPort.bufferUntil('\n');
// ajustar el color del backround:
background(0);
}
void draw () {
// ajustamos el color de la linea a dibujar:
stroke(127, 34, 255);
line(xPos, height, xPos, height - inByte);
// al llegar al final del ancho de la pantalla, reiniciamos valores
if (xPos >= width) {
xPos = 0;
background(0);
} else {
// incrementamos la poscion horizontal
xPos++;
}
}
void serialEvent (Serial myPort) {
// leemos el caracter que viene del puerto seríal en codigo ASCII
String inString = myPort.readStringUntil('\n');
if (inString != null) {
// eliminamos cualquier espacio en blanco
inString = trim(inString);
// usamos map para transformar los valores que vienen del puerto serial
// de 0 hasta 1023 y los ajustamos al la altura de la ventana de 0 hasta height
// que hemos configurado a 300px en el setup
inByte = float(inString);
println(inByte);
inByte = map(inByte, 0, 1023, 0, height);
}
}
Una vez hemos programado el Arduino, pasaremos a realizar el montaje de los componentes necesarios. Aquí vamos a usar únicamente un potenciómetro, de donde obtendremos nuestra lectura análoga.

Al ejecutar todo junto, deberíamos tener un gráfico que responde a los cambios que realicemos en el potenciómetro, justo como se puede ver en el siguiente video.
De momento tenemos una buena base de la cual podemos partir. Lo que sigue ahora es hacer unos ajustes dentro de Processing para que se parezca más a lo que veríamos dentro de un osciloscopio.
Para transformar el gráfico en una línea, he encontrado que la solución que da mejores resultados es almacenar el punto anterior de la coordenada X y la coordenada Y. Modificaremos la función line() para representar el gráfico que vemos en pantalla, de modo que los dos primeros parámetros que recibe sean el X y Y de la lectura anterior, y los dos siguientes parámetros los X y Y de la lectura actual.
Además, agregaremos una cuadrícula para obtener un resultado más “estético”. Dicho esto, ajustaremos el código de Processing de esta manera:
import processing.serial.*;
Serial myPort; // creamos la variable del puerto serial
int x = 1; // inicializamos la posicion horizontal
int prevX = 0; // inicializamos la posicion horizontal previa
float y, prevY = 0; // inicializamos la posicion vertical y vertical previa
int GRID_RESOLUTION = 10; // la cantidad de lineas verticales y horizontales a dibujar
void setup () {
// ajustamos el tamaño de la ventana:
size(400, 300);
// imprimiremos la lista de puertos disponibles
println(Serial.list());
// en la mayoría de los casos solo exitiría un elemento en el puerto sería (el arduino), pero de no ser así ajusta el valor 0, segun corresponda
myPort = new Serial(this, Serial.list()[2], 9600);
// espera hasta que tenga datos en el puerto serial
myPort.bufferUntil('\n');
// invocamos la funcion initializeGraph, para cargar los valores por defecto
initializeGraph();
}
void draw () {
line(prevX, prevY, x, y);
prevX = x;
prevY = y;
// al llegar al final del ancho de la pantalla, reiniciamos valores
if (x >= width) {
initializeGraph();
} else {
// incrementamos la posición horizontal:
x++;
}
}
void serialEvent (Serial myPort) {
// leemos el caracter que viene del puerto seríal en codigo ASCII
String inString = myPort.readStringUntil('\n');
if (inString != null) {
// eliminamos cualquier espacio en blanco
inString = trim(inString);
// usamos map para transformar los valores que vienen del puerto serial
// de 0 hasta 1023 y los ajustamos al la altura de la ventana de 0 hasta height
// que hemos configurado a 300px en el setup
y = float(inString);
println(y);
y = map(y, 0, 1023, 0, height);
}
}
void initializeGraph() {
x = 1;
prevX = 0;
background(0);
stroke(255);
strokeWeight(1);
for(int i = 1; i<= GRID_RESOLUTION; i++){
float yResolution = width / GRID_RESOLUTION;
float xResolution = height / GRID_RESOLUTION;
float gridYPos = i * yResolution;
float gridXPos = i * xResolution;
line(gridYPos, 0,gridYPos, height);
line(0, gridXPos,width, gridXPos);
}
strokeWeight(2);
stroke(35, 127, 35);
}
Una vez hechos estos cambios, obtendremos algo más cercano a lo que representaría un osciloscopio, lo cual podemos ver en el siguiente video.
Llegados a este punto, ya tenemos algo bastante llamativo que se asemeja a un osciloscopio básico, sin embargo, esto sigue siendo una versión muy rudimentaria.
Aún no tenemos la capacidad de distinguir la frecuencia y amplitud de las ondas, y de hecho estamos limitados a la lectura de señales menores a 60 Hz.
Estas “limitaciones” son las que resolveremos en el próximo post.
Pues bien, muchas gracias por llegar hasta aquí. Te recuerdo suscribirte para recibir las notificaciones y puedas enterarte de todos los proyectos que iré realizando.