Mensajes de depuración a través del monitor Serie

Una de las ventajas de utilizar el entorno de programación de Arduino es poder utilizar otras herramientas más avanzadas como el monitor Serie, donde el código de nuestra aplicación puede mostrar mensajes informativos, que no aparecen directamente en ningún dispositivo de la placa Arduino. Esto se usa normalmente para depurar el código de las aplicaciones por parte de los programadores para ir conociendo los valores que van tomando las variables o por dónde va transcurriendo la ejecución del código.

Para poder usa el monitor serie, en el bloque de inicio del código de la aplicación (setup) debes habilitar la comunicación indicando la velocidad de transmisión, que en este caso es 9600:

Serial.begin(9600);

Cada vez que desees mostrar un mensaje en el monitor serie, debes efectuar una llamada a la función print de Serial, como en este ejemplo:

Serial.print("mi mensaje\n");

Como habrás podido observar, se ha añadido \n al final del mensaje. Esto lo puedes utilizar cada vez que desees introducir un salto de línea, es decir, que si no se indica \n, cada mensaje aparecerá justo detrás del anterior, por lo que se dificultaría su visibilidad.

Si en lugar de mostrar un mensaje con un texto literal, deseas mostrar el valor de una variable, deberás indicar el nombre de la variable sin usar las comillas:

Serial.print(variable);

Para ver los mensajes, abre el monitor serie después de iniciar la ejecución de la aplicación, usando el menú Herramientas > Monitor Serial.

Para probar esta funcionalidad, y puedas depurar el funcionamiento de tu código, añade un mensaje Serial cuando se pulse cada botón y sigue usándolo en los siguientes apartados para conocer si está funcionando correctamente el código que vayas desarrollando.

Ejemplo:

Mostrar la distancia medida por un sensor de ultrasonidos

Código


 
Medidas mostradas en el monitor serie
 

 
 
 
 

Variables. Conceptos y tipos

 ¿Que es una variable? Una variable es un lugar donde almacenar un datos cuyo valor no es constante sino que puede ir cambiando a lo largo de la ejecución del programa.

Antes de usarse, las variables tienen que ser declaradas definiendo su tipo y valor o bien pueden permanecer sin recibir un valor previo hasta que la instrucción se lo asigne. La mayoría de los lenguajes de programación exigen definir las variables al principio, de modo que estas primeras órdenes constituyen instrucciones de definición de datos.

La sintaxis general para definir una variable es:

tipo nombre=valor;

Por ejemplo: int contador=0;

Los nombres de variables pueden tener letras, números y el símbolo ’_’. Deben empezar por una letra (pueden empezar por ’_ ’ pero no es recomendable pues es el criterio que usan las rutinas de la biblioteca).

Pueden llevar mayúsculas y minúsculas. En C se distingue entre mayúsculas y minúsculas. La costumbre es que las variables van en minúscula y las constantes en mayúscula

Usa las mismas reglas dentro del código para el nombramiento de variables, ya sea en minúscula con palabras separadas con guiones bajos, tantos como sea necesario para mejorar la legibilidad o utilizar la convención “CapWords” (palabras que comienzan con mayúsculas), aunque generalmente la primera palabra se pone en minúsculas.

Usa un solo guión bajo como prefijo para métodos no públicos y variables de instancia.

Las palabras reservadas if, else,etc . . . no pueden usarse como nombres de variables.

Nombres para evitar: Nunca uses los caracteres ‘l’ (letra ele en minúscula), ‘O’ (letra o mayúscula), o ‘I’ (letra i mayúscula) como simples caracteres para nombres de variables, para evitar confusiones a la hora de leer el código.

Declaración de variables.

Una variable tiene un nombre, un valor y un tipo. Con la asignación, se puede cambiar el valor de la variable.

Todas las variables deben ser declaradas antes de su uso. Las declaraciones deben aparecer al principio de cada función o bloque de sentencias. Al declarar una variable se debe indicar primero el tipo de variable y luego su nombre, opcionalmente se le puede dar un valor, lo que se llama inicializar la variable.

La declaración consta de un tipo de variable y una lista de variables separadas por coma.

  • int i,j;

  • float x,pi;

  • unsigned long longitud, contador;

Las variables pueden inicializarse en la declaración

  • float pi=3.1416;

  • unsigned long contador=0;

Puede utilizarse el modificador const para indicar que la variable no puede ser cambiada en tiempo de ejecución.

  • const float e=2.7182;

La declaración de una variable sólo debe hacerse una vez en un programa, pero el valor de la variable se puede cambiar en cualquier momento usando aritmética y reasignaciones diversas.

Una variable puede ser declarada en una serie de lugares del programa y en función del lugar en donde se lleve a cabo la declaración, esto determinará en qué partes del programa se podrá hacer uso de ella, es lo que se denomina ámbito de la variable o scope.

C y C++ se dice que son lenguajes de tipado estático, es decir, la comprobación de tipificación se realiza durante la compilación, y no durante la ejecución, por lo tanto no podemos cambiar el tipo de una variable en tiempo de ejecución. Otros lenguajes, generalmente interpretados, son de tipado dinámico y una misma variable puede tomar valores de distinto tipo en distintos momentos, como PHP o python.

Ámbito de una variable

Una variable puede ser declarada al inicio del programa antes de la parte de configuración setup(), a nivel local dentro de las funciones, y, a veces, dentro de un bloque, como para los bucles del tipo if.. for.., etc. En función del lugar de declaración de la variable así se determinará el ámbito de aplicación, o la capacidad de ciertas partes de un programa para hacer uso de ella.

Una variable global es aquella que puede ser vista y utilizada por cualquier función y estamento de un programa. Esta variable se declara al comienzo del programa, antes de setup().

Recordad que al declarar una variable global, está un espacio en memoria permanente en la zona de static data y el abuso de variables globales supone un uso ineficiente de la memoria.

Una variable local es aquella que se define dentro de una función o como parte de un bucle. Sólo es visible y sólo puede utilizarse dentro de la función en la que se declaró. Por lo tanto, es posible tener dos o más variables del mismo nombre en diferentes partes del mismo programa que pueden contener valores diferentes, pero no es una práctica aconsejable porque complica la lectura de código.

El modificador de variable static, es utilizado para crear variables que solo son visibles dentro de una función, sin embargo, al contrario que las variables locales que se crean y destruyen cada vez que se llama a la función, las variables estáticas mantienen sus valores entre las llamadas a las funciones.

Constantes

En programación, una constante es un valor que no puede ser alterado/modificado durante la ejecución de un programa, únicamente puede ser leído. Una constante corresponde a una longitud fija de un área reservada en la memoria principal del ordenador, donde el programa almacena valores fijos. Por ejemplo el valor de PI = 3.1416.

El modificador const, modifica el comportamiento de una variable haciéndola “read-only”, esto significa que puede usarse como cualquier otra variable pero su valor no puede ser cambiado.

En C++ las constantes también pueden ser definidas a nivel de módulo antes de compilar, de forma que no ocupan memoria y su nombre es sustituido por el valor definido en el proceso de compilación. Estas constantes por norma se escriben con letras en mayúscula y guiones bajos separando palabras. Por ejemplo, MAX_OVERFLOW y TOTAL. Se usa la palabra clave #define para definirlas.

Más información en: https://www.arduino.cc/en/Reference/Define

A la hora de elegir un tipo de variable u otro, es importante escoger el que requiera el número menor de posiciones de memoria para cubrir nuestras necesidades; de está manera se evita sobredimensionar el programa y restar recursos de memoria. 


Tipos de datos

En programación, un tipo de dato informático o simplemente tipo es un atributo de los datos que indica al ordenador (y/o al programador) sobre la clase de datos que se va a trabajar. Esto incluye imponer restricciones en los datos, como qué valores pueden tomar y qué operaciones se pueden realizar.

Los tipos de datos comunes son: números enteros, números con signo (negativos), números de coma flotante (decimales), cadenas alfanuméricas, estados (booleano), etc.

byte

Byte almacena un valor numérico de 8 bits sin decimales. Tienen un rango entre 0 y 255. Sin signo.

int (entero)

Enteros son un tipo de datos primarios que almacenan valores numéricos de 16 bits sin decimales comprendidos en el rango 32,767 a -32,768.

long (entero largo)

El formato de variable numérica de tipo extendido “long” se refiere a números enteros (tipo 32 bits = 4 bytes) sin decimales que se encuentran dentro del rango -2147483648 a 2147483647.

float (decimales)

El formato de dato del tipo “coma flotante” o “float” se aplica a los números con decimales. Los números de coma flotante tienen una mayor resolución que los de 32 bits que ocupa con un rango comprendido 3.4028235E+38 a -3.4028235E+38.

Los números de punto flotante no son exactos, y pueden producir resultados extraños en las comparaciones. Los cálculos matemáticos de coma flotante son también mucho más lentos que los del tipo de números enteros, por lo que debe evitarse su uso si es posible. En Arduino el tipo de dato double es igual que el float.

boolean

Un booleano solo tiene dos valores true y false. Cada booleano ocupa un byte de memoria.

char (carácter)

Un char representa un carácter que ocupa 1 byte de memoria. Los caracteres simples se representan con comillas simples ‘a’ y para múltiples caracteres o strings se representan con comillas dobles “Hola!”.

Recordar que los caracteres se almacenan como números usando la codificación ASCII, lo que significa que es posible hacer operaciones aritméticas con los caracteres.

Tipos de Datos en Arduino

En Arduino podemos definir los tipos de datos tanto en variables locales como globales:

  • Void     Está reservado para la declaración de funciones.
  • Char    Se utiliza para almacenar datos de tipo texto. Ocupa un byte.
  • Byte     Se utiliza para almacenar números entre el 0 y 255. Ocupa un byte.
  • int        Se utiliza para almacenar números entre el -32768 y 32767. Ocupa dos bytes.
  • usigned int   Se utiliza para almacenar números enteros positivos. Ocupa dos bytes y permite almacenar números entre el 0  y 655535.
  • long   Se utiliza para almacenar números enteros largos, entre el -2147483648 y 2147483647. Ocupa cuatro bytes.
  • unsigned long   Se utiliza para almacenar números enteros positivos largos. Ocupa cuatro bytes y permite almacenar números entre el 0 y el 4294967296.
  • float     Se utiliza para almacenar números con decimales. Ocupa cuatro bytes.
  • String  Se utiliza para guardar cadenas de caracteres.

Asimismo, los datos pueden ser constantes, cuyo valor no cambia a lo largo del programa, o variables, cuyo contenido puede ir cambiando a lo largo de la ejecución.

Crear juguetes reciclando

 Propuesta de trabajo

Siguiendo el método de proyectos tecnológicos, diseña y construye la maqueta de un robot pequeño utilizando materiales reciclados. Debes tener en cuenta las siguientes condiciones:

Obligatorias

  1. Tendrán que ser realizados con trozos de madera y materiales reciclados, como pueden ser: botones, tapones de envases, tornillos, tuercas y restos de diferentes materiales  como pueden ser alambre, cuerdas, etc...

  2. El diseño es libre y cada alumn@ debe de fabricar su propio robot..

  3. Las dimensiones son reducidas, la maqueta del robot no debe superar los 15 cm de altura..

  4. Es obligatorio tener una caja personalizada para guardar el proyecto una vez terminado y los materiales durante la fase de fabricación..

  5. Se puede trabajar en casa y en el aula de tecnología.

  6. Es obligatorio terminar las tareas propuestas hasta la fecha.

Documentación que hay que presentar

  1. Memoria técnica. La redacción se deberá realizar con un procesador de textos (google docs, word, writer..) o editor de presentaciones (Prower point, presentaciones de google, genially, canva...). En el siguiente enlace puedes encontrar información sobre la elaboración de la memoria técnica Cómo redactar la memoria técnica


     

Puedes ampliar información

¿Cómo alimento mi Arduino?


Así que vamos a hacer un repaso de algunas de las opciones de alimentación más comunes de las placas Arduino. Para alimentar tu proyecto puedes repasar esta lista en orden y elegir la primera fuente que cumpla con las características que necesitas o deseas, porque voy a repasarlas de las más sencillas a las más especiales.

El puerto USB

Allá donde haya un puerto USB puedes alimentar tu Arduino. Sin más complicaciones. El puerto USB es la fuente de alimentación más fácil y segura de utilizar con Arduino. Si estás aprendiendo, utiliza una de las siguientes opciones USB siempre que puedas.

El puerto USB del ordenador

Cuando conectamos nuestro Arduino al ordenador por el puerto USB ya lo estamos alimentando:
  • Voltaje de 5V de forma continua. Estupendo para trabajar con él y alimentar todo tipo de accesorios.
  • Puede entregar hasta 500 mA.
  • Necesitamos el ordenador. ¡Qué fuente de alimentación más cara!
  • Por lo general el ordenador tiene que estar encendido para que los puertos USB tengan alimentación (aunque depende de las capacidades de tu ordenador).
  • Si le pedimos más de 500mA podemos dañarlos y dejarlos inservibles. Están protegidos de exceso de corriente, ¿pero quién quiere poner la protección a prueba? 

Cargador de móvil


Igual que podemos alimentar Arduino con el puerto USB del ordenador, podemos hacerlo con cualquier fuente de alimentación USB, como un cargador de móvil. Muchas placas Arduino no tienen conector MicroUSB como los móviles, pero puedes coger uno de esos cargadores que tienen un puerto USB y el cable se puede desconectar. ¡A esos cargadores puedes ponerle cualquier cable USB!
  • Voltaje de 5V de forma continua. Estupendo para trabajar con él y alimentar todo tipo de accesorios.
  • Pueden entregar al menos 1A de corriente (excepto los más antiguos). Los más modernos superan los 2A. La corriente máxima la encontramos en la etiqueta del cargador.
  • No pasa por el regulador de 5V de Arduino, que está limitado a 800mA. Pasa por un transistor P-MOSFET que soporta corrientes de 2,4A de forma continua.
  • Muy económico.
  • Fácilmente disponible.

Powerbank

¡Fuera cables! Los powerbanks tienen puertos USB, ¿verdad? Pues entonces podemos alimentar nuestro Arduino.

Voltaje de 5V de forma continua. Estupendo para trabajar con él y alimentar todo tipo de accesorios.
  • La corriente máxima depende del estado de carga de la batería interna. Cuando está llena fácilmente supera 1 y 2A.
  • No pasa por el regulador de 5V de Arduino, que está limitado a 800mA. Pasa por un transistor P-MOSFET que soporta corrientes de 2,4A de forma continua.
  • Muy económico.
  • Fácilmente disponible.
  • ¡Vivan los proyectos móviles!
  • Recargable por el conector de carga del powerbank, sin circuitería adicional.
El pin VIN

En los pines de Arduino puedes encontrar uno etiquetado como VIN. ¡Úsalo con cuidado! El pin VIN tiene dos funcionalidades:

Si estamos alimentando Arduino por cualquiera de sus conectores, en el pin VIN tendremos el voltaje bruto de alimentación. Es decir, si estamos alimentando Arduino por USB, en VIN tendremos 5V que podemos utilizar para alimentar otros accesorios. Si estamos alimentando Arduino a través del conector jack, en VIN tendremos el mismo voltaje que tenga la fuente de alimentación que estamos utilizando.

Si NO estamos alimentando Arduino por ninguno de sus conectores, podemos utilizar el pin VIN y un GND para alimentar la placa. Las características de la fuente son las mismas que las del conector jack, pues hace uso del mismo regulador de 5V para regular su voltaje.
  • Sin necesidad de conector. Solo necesitas 2 cables: el negativo a GND y el postivo a VIN. 
  • Perfecto para portapilas y otras fuentes de alimentación sin conector. 
  • Puedes utilizar reguladores de tensión externos.

Aplicación de la función map()

Controlar la posición del eje de un servomotor con un potenciómetro

En ocasiones, los valores que obtenemos de una lectura de un pin analógico, como un sensor, pueden estar fuera de una escala determinada, y tenemos que convertirlos a otro rango para poder usarlos.

El valor de salida que podemos darle al servomotor es de 0 a 180, que se traduce en la posición del eje, pero los datos que leemos del sensor pueden llegar a 1024. Por esto debemos mapear el resultado, es decir , dejarlo en unos valores de entre 0 y  180.

La función “map” del programa asigna un valor máximo y un valor mínimo a un rango dado.

El valor máximo suele estar en 1024, pero el mínimo en nuestro caso será 0. Por eso en el código se especifican las siguientes valores:

valorPotenciometro = analogRead(potenciometro);
posicion = map(valor, 0, 1023, 0, 180);

valor = map(valor que recibo, de Mínimo, de Máximo, a Mínimo, a Máximo)

Descripción

Re-asigna un número de una gama de valores a otra.

Parámetros


valor que recibo: el número a mapear   valorPotenciometro=(analogRead(potenciometro)
deMínimo: el límite inferior del rango actual del valor  (0)
deMáximo: el límite superior del rango actual del valor (1023)
aMínimo: el límite inferior del rango resultado del valor (0)
aMáximo: el límite superior del rango resultado del valor (180)

Valor retornado por la función

El valor mapeado. (posicion)

La función map () usa números enteros por lo que no va a generar decimales, cuando las operaciones matemáticas podrían indicar que debería hacerlo. Los decimales remanentes se truncan, y no son redondeados o promediados.

Nota: No restringe los valores dentro del rango, ya que los valores fuera de la gama a veces se entiende que son útiles. La función constrain () se puede usar antes o después de esta función, si se desean límites de los intervalos.

El código correspondiente al void loop(), se corresponderá con las siguientes acciones:
  1. Guardo en valor lo que marca el potenciómetro.
  2. Mapeo el valor que su rango original es de 0-1023 a 0-180 que es lo que me interesa para controlar la posición del eje del sermovotor (0-180º).
  3. Posicionar el servomotor.

// sketch para controlar la posición del eje de un servomotor

#include

// Incluimos la librería para poder controlar el servo

int valorPotenciometro=0;
int posicion=0;
// Declaramos la variable para controlar el servo
Servo servoMotor;

void setup() {
  // Iniciamos el monitor serie para mostrar el resultado
  Serial.begin(9600);

  // Iniciamos el servo para que empiece a trabajar con el pin 9
  servoMotor.attach(9);
}

void loop() {
 valorPotenciometro=analogRead(0); //Leemos el valor del potenciometro
    posicion = map(valorPotenciometro, 0, 1023, 0, 180);
    servoMotor.write(posicion);
   
}
 






Ejemplo 2 Control del brillo de un diodo led

#define pinLed 5
int valorPotenciometro=0;
int brillo=0;

void setup() {
 pinMode(pinLed, OUTPUT);

}

void loop() {
valorPotenciometro=analogRead(0); //Leemos el valor del potenciometro
    brillo = map(valorPotenciometro, 0, 1023, 0, 255);
 
  analogWrite(pinLed,brillo);
}
 






¿Qué son los potenciómetros?

Un potenciómetro es un resistor eléctrico con un valor de resistencia variable y generalmente ajustable manualmente. Los potenciómetros utilizan tres terminales. En muchos dispositivos eléctricos los potenciómetros son los que establecen el nivel de salida. Por ejemplo, en un altavoz el potenciómetro ajusta el volumen; en un televisor o un monitor de ordenador se puede utilizar para controlar el brillo.


El valor de un potenciómetro viene expresado en ohmios (símbolo Ω) como las resistencias, y el valor del potenciómetro siempre es la resistencia máxima que puede llegar a tener. La mínimo lógicamente es cero. Por ejemplo un potenciómetro de 10KΩ puede tener una resistencia variable con valores entre 0Ω y 10.000Ω.

Los potenciómetros que encontramos en el mercado vienen con un valor de resistencia determinado. Estos valores han sido estandarizados y solamente encontraremos valores de resistencia específicos, por ejemplo 1K, 5K, 10k, 50k, 100k, etc. Este valor de resistencia lo podemos medir entre las terminales 1 y 3 del potenciómetro.

Su símbolo es básicamente, el símbolo de una resistencia con una flecha que nos indica que podemos variar su valor.



La capacidad de variar la resistencia entre 2 terminales y mantenerla entre sus extremos permite que los potenciómetros se utilicen como variadores de tensión. En ciertas aplicaciones se necesita establecer un nivel de tensión de referencia. Para esto se emplea un potenciómetro conectando la patas 1 y 3 a una fuente de voltaje y a tierra, respectivamente. Veamos el diagrama:

En Arduino vamos a utilizar los potenciómetros para variar por ejemplo la intensidad de luz de un diodo led, variar la velocidad de giro de un motor, variar la posición del eje de un servomotor, etc..

El potenciómetro tiene tres patillas, la 1 la vamos a conectar a 5 v, la 3 a GND y la central a una entrada analógica (en esta patilla obtendremos un valor variable comprendido entre 0 y 5 v).


Los valores medidos por el pin analógico pueden ser utilizados como valores de una variable de nuestro programa para hacer algo o tomar decisiones, como, por ejemplo, variar la intensidad de luz. Para ello, usaremos la función analogRead.

Esta función devolverá un valor comprendido entre 0 y 1023, que generalmente se guardará en una variable.

analogRead(pin)

En el siguiente ejemplo utiliza un potenciómetro para encender cinco diodos LEDs, en función de la posición en la que se encuentre el cursor.



 Acceder al sketch: Encendido de 5 diodos leds