Correo: [email protected] - Teléfono: +56979962128

Programming With Classes and Objects on the Arduino

Una clase es como una plantilla que te permite reutilizar el código sin tener que escribirlo una y otra vez. Por ejemplo, supongamos que necesitas crear 20 documentos que tengan todos la misma fuente, encabezado y márgenes. Sería demasiado lento cambiar el formato de los 20 documentos individualmente. En lugar de eso, puedes crear un documento de plantilla con la fuente, el encabezado y los márgenes correctos, luego agregar el texto y guardarlo como un archivo separado.

Las clases son como ese documento de plantilla. Son plantillas de código para lo que se denominan “objetos”. Piensa en una clase como el documento de plantilla y en el objeto como el documento individual. Los objetos le permiten acceder a las funciones y variables dentro de una clase. A veces, a un objeto se lo denomina “instancia” de una clase.

Mira el vídeo de este tutorial aquí:

Ejemplo: Parpadeo de un LEDs sin uso de clases ni objetos 

Para demostrar lo útiles que pueden ser las clases y los objetos, hagamos un proyecto de ejemplo que hace parpadear dos LED a diferentes velocidades sin utilizar clases ni objetos.

Estos son los componentes que necesitarás para este proyecto:

Conecta los componentes como se muestra a continuación:

Blink With Classes and Objects WIRING DIAGRAM

Este ejemplo hará que el LED verde parpadee durante dos segundos y que el LED rojo parpadee durante un segundo:

int redLED = 10;
int greenLED = 11;

void setup() {
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
}

void loop() {
digitalWrite(greenLED, HIGH);
delay(2000);
digitalWrite(greenLED, LOW);
delay(2000);

digitalWrite(redLED, HIGH);
delay(1000);
digitalWrite(redLED, LOW);
delay(1000);
}

Explicación del Código  

En la parte superior del código declaramos variables para los pines 

redLED

y 

greenLED e indicamos el numero de la salida digital en la cual conectaremos los leds respectivamente.

En la sección

setup()

configuramos greenLED y redLED como 

OUTPUT (salida) utilizando la función pinMode().

En la sección 

loop()

, colocamos digitalWrite seguido de  

greenLED

como HIGH, colocamos un delay(retardo) durante 2000 milisegundos, luego en la línea siguiente digitalWrite como LOW y luego un delay  durante otros 2000 milisegundos.

A continuación, colocamos digitalWrite seguido de  

redLED

como HIGH, creamos un delay durante 1000 milisegundos, y en la siguiente línea digitalWrite como LOW y luego un delay durante otros 1000 milisegundos.

Este es un código resulta grande para una tarea tan simple como encender y apagar un par de LED. Sin embargo, podemos hacer que este programa sea mucho más pequeño con el uso de clases y objetos.

Parpadeo de LEDs con clases y objetos 

Veamos cómo hacer parpadear los LED en el ejemplo anterior con clases y objetos. Comenzaremos escribiendo el código para la clase y, más adelante, crearemos objetos para acceder al código dentro de la clase.

Para crear una clase Arduino, necesitamos crear dos archivos: un archivo cabecera (header) y un archivo fuente (source). Escribiremos el sketch que utiliza esta clase más adelante, pero ahora comencemos a escribir el archivo de cabecera.

El archivo de cabecera (header File)

El archivo de cabecera es donde se declara la clase. También es donde se declaran las funciones y variables que se usan dentro de la clase. Veamos paso a paso cómo escribir un archivo de cabecera.

El primer fragmento de código necesario en el archivo de cabecera se denomina protección de inclusión

(include guard).

La protección de inclusión evita errores de programa si la biblioteca se incluye accidentalmente más de una vez.

#ifndef MyClass_h
#define MyClass_h
// code goes here
#endif

Puedes nombrar el archivo de cabecera como quieras, pero en este tutorial se llamará MyClass. El archivo debe guardarse con la extensión .h para que funcione. En  

#ifndef

y 

#define

, el nombre del archivo de encabezado debe ir seguido de 

_h

.

A continuación, debemos incluir la biblioteca Arduino.h , ya que es la biblioteca principal que contiene todas las funciones integradas de Arduino. Si la incluimos en el archivo de cabecera, esas funciones estarán disponibles para su uso en la clase:

#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
#endif

Ahora podemos definir la clase. Para definir una clase, escribe 

class

seguido del nombre de la clase: 

#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
class MyClass {
// class code goes here
};
#endif

El nombre de la clase en este ejemplo es 

MyClass

. El código de la clase va entre llaves.

Las funciones y variables dentro de una clase pueden ser públicas o privadas:

#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
class MyClass {
public:
private:
};
#endif

Las palabras claves public y private se conocen como especificadores de acceso. Las funciones y variables públicas se pueden utilizar dentro del ejemplo, pero las funciones y variables privadas solo se pueden utilizar dentro de la clase.

Cada clase necesita una función especial llamada constructor. El constructor define lo que sucederá cuando se cree un objeto. Cuando escribamos el código para este proyecto, vamos a crear un objeto para greenLED  y otro objeto para redLED. El constructor le dirá a Arduino qué hacer cuando creemos esos objetos de tipo LED.

Escribiremos el código para el constructor cuando lo definamos en el archivo fuente, pero necesitamos declararlo en el archivo de cabecera. Dado que los objetos se crearán en el ejemplo, la declaración del constructor debe ser pública y tener el mismo nombre que la clase. La clase en este ejemplo se llama 

MyClass

, por lo que la declaración del constructor será 

MyClass()

:

#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
class MyClass {
public:
MyClass();
private:
};
#endif
En este proyecto de ejemplo, conectaremos dos LED al Arduino, por lo que debemos configurar el modo de cada pin como OUTPUT. Al escribir el código para el constructor en el archivo fuente, incluiremos la función pinMode() dentro de él. Dado que pinMode() requiere el número de pin como primer parámetro, debemos pasar dicho número al constructor para que la función pueda utilizarlo. Para lograrlo, declaramos una variable de tipo int llamada pin dentro de los paréntesis de la declaración del constructor.
#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
class MyClass {
public:
MyClass(int pin);
private:
};
#endif
Ahora debemos declarar la función que hará que los LED parpadeen. Dentro de una clase, las funciones se declaran de la misma manera que en los ejemplos anteriores. Primero, especificamos el tipo de retorno. Como esta función no devolverá ningún valor, su tipo de retorno será void. Luego, asignamos un nombre a la función; en este caso, la llamaremos myFunction().
#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
class MyClass {
public:
MyClass(int pin);
void myFunction();
private:
};
#endif
Dado que esta función hará parpadear los LED, sería útil poder controlar la velocidad del parpadeo. Para lograrlo, podemos pasar una variable a la función myFunction(), la cual definirá la duración de los retardos. Cuando usemos la función en el ejemplo, deberá recibir un parámetro que establezca dicha duración. Ahora, declararemos una variable dentro de myFunction() para almacenar ese parámetro y la llamaremos blinkRate.
#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
class MyClass {
public:
MyClass(int pin);
void myFunction(int blinkRate);
private:
};
#endif
Ahora, cualquier argumento que se pase a la función myFunction() en el ejemplo será recibido por el código de la función en el archivo fuente. La función myFunction() necesitará conocer los números de los pines a los que están conectados los LED, por lo que debemos declarar una variable para almacenarlos. Dado que esta variable solo se utilizará dentro de la función, la declararemos como privada. Es común que los nombres de las variables privadas comiencen con un guion bajo (_). Siguiendo esta convención, declararemos una variable privada llamada _pin.
#ifndef MyClass_h
#define MyClass_h
#include "Arduino.h"
class MyClass {
public:
MyClass(int pin);
void myFunction(int blinkRate);
private:
int _pin;
};
#endif

Este es todo el código que necesitamos para el archivo de cabecera.

Para guardar el archivo de cabecera, dirígete a Documentos > Arduino > Bibliotecas. Crea una nueva carpeta con el mismo nombre que la clase (MyClass en este ejemplo). Guarda el archivo de cabecera en esta carpeta. El archivo de cabecera debe guardarse con una extensión .h. En este ejemplo, el archivo de cabecera se llamaría MyClass.h.

El archivo fuente 

El archivo fuente contiene el código real de las funciones y define lo que sucederá cuando se cree un objeto. Repasemos el proceso de escritura de un archivo fuente.

El archivo de fuente debe tener el mismo nombre que el archivo de cabecera pero con una extensión “.cpp”.

Lo primero que debemos hacer es incluir la biblioteca Arduino.h para que podamos utilizar las funciones integradas de Arduino como 

pinMode()

, 

digitalWrite()

, y 

delay()

: 

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass() {
}
 

Luego, debemos incluir el archivo de cabecera que acabamos de escribir. Lo hacemos de la misma manera en la que incluimos todas las clases, con un 

#include

seguido del nombre del archivo de encabezado entre comillas:

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass() {
}

Ahora podemos escribir la definición del constructor. Este código se ejecutará cada vez que se cree un objeto en el sketch. La definición del constructor comienza con el nombre de la clase seguido de dos puntos. En este ejemplo, la clase es 

MyClass

. Los dos puntos se denominan operador de resolución de alcance (scope resolution operator). Después de los dos puntos se encuentra el nombre del constructor que declaramos en el archivo de cabecera. El constructor debe tener el mismo nombre que la clase. Por lo tanto, el nombre del constructor es 

MyClass()

:

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass() {
}

Los objetos que creamos con esta clase van a representar los pines de Arduino conectados a los LED . Cada vez que se crea un objeto LED, el número 

pinMode()

de cada pin deberá configurarse como salida. Para ello, debemos pasar el número del pin de Arduino conectado al LED al constructor declarando una variable llamada 

pin

dentro del constructor 

MyClass()

:

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass(int pin) {
}

Dentro del constructor, todo lo que tenemos que hacer es configurar los modos de los pines de los LED. El número de pin almacenado en la variable

pin

se pasará al constructor cuando se cree el objeto, por lo que configuramos pinMode con 

pin, OUTPUT

:

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass(int pin) {
pinMode(pin, OUTPUT);
}

¿Recuerdas la variable privada

_pin

que declaramos en el archivo de cabecera? Ahora la asignaremos a la variable pública

pin

que declaramos dentro del

constructor

 

MyClass()

. 

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass(int pin) {
pinMode(pin, OUTPUT);
_pin = pin;
}

Entonces ahora escribamos la función que hará que los LED parpadeen. Para definir una función, primero escriba el tipo de retorno de la función. La función en este ejemplo no devolverá ningún valor, por lo que su tipo de retorno es 

void

.

A continuación, escribe el nombre de la clase a la que pertenece la función. En este ejemplo, la función pertenecerá a la clase

MyClass

. A continuación, incluye el operador de resolución de alcance

::

seguido del nombre de la función. Ya declaramos la función

myFunction()

en el archivo de cabecera, por lo que podemos utilizarlo:

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass(int pin) {
pinMode(pin, OUTPUT);
_pin = pin;
}
void MyClass::myFunction(){
}

La función 

myFunction()

tendrá un parámetro que establece la duración de los parpadeos del LED. Declaramos una variable en el archivo de cabecera llamado 

blinkRate

para almacenar ese valor, pero también debemos declararla aquí en el archivo de origen dentro de los paréntesis de 

myFunction()

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass(int pin) {
pinMode(pin, OUTPUT);
_pin = pin;
}
void MyClass::myFunction(int blinkRate){
}

Esto creará un parámetro para la función 

myFunction()

. Ahora, cuando llamamos a la función en el ejemplo, podemos pasarle un argumento. En este ejemplo, el argumento será la variable 

blinkRate

.

Ahora podemos incluir el código para hacer que los LED parpadeen. Es el mismo código básico que se suele utilizar para hacer parpadear los LED:

#include "Arduino.h”
#include "MyClass.h"
MyClass::MyClass(int pin) {
pinMode(pin, OUTPUT);
_pin = pin;
}
void MyClass::myFunction(int blinkRate){
digitalWrite(_pin, HIGH);
delay(blinkRate);
digitalWrite(_pin, LOW);
delay(blinkRate);
}

Primero ponemos digitalWrite y la variable

_pin como

HIGH. En el constructor, la variable privada

_pin

se estableció igual que la variable pública

pin

. Entonces, cuando se crea el objeto LED, el número de pin se almacenará en la variable pública

pin

y se pasará al constructor. Ese número de pin también se almacenará en la variable privada 

_pin

y se pasará a la función 

digitalWrite()

.

La duración del parpadeo se establecerá en el ejemplo y se almacenará en la variable

blinkRate

, por lo que la usaremos 

blinkRate

como argumento de la función

delay()

. Luego, digitalWrite seguido de la variable privada   

_pin

con un  LOW y luego un delay

blinkRate

.

Ok, eso es todo lo que necesitamos para el archivo fuente.

Para guardar el archivo fuente, dirígete a Documentos > Arduino > Bibliotecas. Guarda el archivo fuente en la carpeta que se creó para MyClass. El archivo fuente debe tener el mismo nombre que el archivo de cabecera, pero con la extensión .cpp. En este ejemplo, el archivo de cabecera se llamaría MyClass.cpp.

Ahora vamos a escribir el código.

El código 

En la programación de Arduino, las clases se tratan como bibliotecas, por lo que podemos incluir la clase

MyClass

en el código de la misma manera que se incluyen las bibliotecas:

#include <MyClass.h>

Para utilizar las funciones que se definieron en la clase, necesitaremos crear algunos objetos. Haremos parpadear dos LED, por lo que tendremos un objeto para el LED verde y un objeto para LED rojo.

Para crear un objeto, escriba el nombre de la clase y luego el nombre del objeto. Los objetos pueden tener el nombre que desee. En este ejemplo, estamos creando un 

redLED()

objeto para el LED rojo y un 

greenLED()

objeto para el LED verde. Cada objeto se llama a través de la clase

MyClass

:

#include <MyClass.h>
MyClass redLED(10);
MyClass greenLED(11);

Cuando definimos el constructor MyClass

en el archivo fuente, le pasamos la variable pública

pin

. Ahora podemos usar el número de pin de Arduino como argumento del objeto y ese número de pin se pasará al constructor. En este ejemplo, el constructor establecerá el modo de pin de los pines 10 y 11 como salidas.

Ahora podemos escribir la sección loop

()

.

Vamos a hacer parpadear el LED rojo y el LED verde con la función myFunction

()

que se definió en el archivo fuente. Para usar funciones de una clase o biblioteca, escriba el nombre del objeto, un punto y luego el nombre de la función que desea llamar:

#include <MyClass.h>
MyClass redLED(10);
MyClass greenLED(11);
void setup(){
}
void loop(){
greenLED.myFunction(2000);
}

Esto llamará a la función

myFunction()

de la clase

MyClass

y la aplicará al objeto

greenLED

.

Cuando definimos la función

myFunction()

, le pasamos la variable  

blinkRate

para controlar la velocidad con la que parpadearán los LED. 

Con 

2000

como el argumento,el 

delay()

dentro de la función  

myFunction()

se retrasará 2000 milisegundos.

Ahora solo tenemos que llamar a la función myFunction

()

en el objeto 

redLED

. El LED rojo parpadeará durante 1000 milisegundos:

#include <MyClass.h>
MyClass redLED(10);
MyClass greenLED(11);
void setup() {
}
void loop() {
greenLED.myFunction(2000);
redLED.myFunction(1000);
}

Lo bueno de usar clases y objetos es que puedes reutilizar las mismas funciones en varios objetos. Esto hace que tu código sea más simple, más eficiente y más fácil de usar para otros.

Después de cargar el sketch, deberías ver el LED rojo parpadeando una vez por segundo y el LED verde parpadeando cada dos segundos.

 

Aprende esto en un curso

Si prefieres verlo en vivo y con alguien que resuelva tus dudas, estos cursos presenciales de MCI Educación cubren el tema de este tutorial: