Archivo de la categoría: Práctica

Joystick Arduino

Módulo de joystick XY:

El módulo tiene 5 pines: VCC, masa, X, Y, pulsación. La salida X, Y es analógica, además, puede presionar el joystick hacia abajo para activar la salida digital.

Cuando el joystick se encuentra en la posición de reposo o medio, debe devolver un valor de aproximadamente 512.

Tenemos que usar pines Arduino analógicos para leer los datos de los pines X / Y, y un pin digital para leer el botón. Para obtener lecturas estables del pin Key / Select, debe conectarse a VCC a través de una resistencia pull-up. Las resistencias incorporadas en los pines digitales de Arduino se pueden utilizar (INPUT_PULLUP).

Conexión Arduino:

Usar el código: https://github.com/jecrespo/Arduino-Kit-China-Guide/blob/master/02-Joystick/Analog_Joystick/Analog_Joystick.ino

Abrir el monitor serie y el serial plotter para ver los valores de salida del joystick.

Anuncios

Módulo Micrófono Arduino

Los transductores son dispositivos que convierten energía de una forma a otra. Un micrófono es un transductor que convierte la energía sonora en señales eléctricas. Micrófonos están disponibles en diferentes formas y tamaños. Dependiendo de la aplicación, un micrófono puede utilizar diferentes tecnologías para convertir sonidos en señales eléctricas.

El micrófono de condensador electret https://es.wikipedia.org/wiki/Micr%C3%B3fono_electret es un condensador de placas paralelas y trabaja en el principio de una capacitancia variable. Consiste en dos placas, una fija (llamada la placa trasera) y el otro movible (llamado diafragma) con una pequeña separación entre ellos. Un potencial eléctrico carga la placa. Cuando el sonido golpea al diafragma se inicia moviendo, cambiando así la capacitancia entre las placas.

Este módulo tiene dos salidas:

  • AO: salida analógica, señal de voltaje de salida en tiempo real del micrófono
  • DO: salida digital, cuando la intensidad del sonido alcanza un cierto umbral, la salida es una señal de nivel alto o bajo. La sensibilidad del umbral puede lograrse ajustando el potenciómetro.

Para asegurarse de que el micrófono pueda detectar tu voz o un sonido de palmas, se debe cambiar su sensibilidad girando el potenciómetro azul en el módulo.

Al modificar el potenciómetro, se ajusta la ganancia de la señal del micrófono y la salida analógica modifica su valor.

Para la salida digital, se compara la salida analógica con un valor fijo de la salida del altavoz, así que modificando el potenciómetro, se modifica la sensibilidad para que se active el pin digital.

Conexión con Arduino:

Este módulo proporciona dos modos de salida de señal, para lo cual escribimos dos códigos para probarlos:

El código analog_signal_output muestra por el serial plotter el valor de la salida analógica. Probar la salida con diferentes valores del potenciometro.

El código de digital_signal_output funciona cuando la voz llega a un cierto valor, activará una señal digital y se enciende el indicador L al mismo tiempo. Este valor desencadenante puede cambiarse según el método de ajuste de sensibilidad con el potenciometro. Este código también nos ayuda a calibrar la sensibilidad de la salida digital, cuando las pulsaciones de un sonido están entre 2 y 15 y la distancia entre pulsos consecutivos no es mayor de 100 ms.

Esta es la parte más complicada de este ejercicio. Para ajustar el límite de disparo lo que hacemos es girar el potenciómetro con un destornillador. Tenemos que dejarlo de tal forma que el LED que marca si está accionada la salida digital esté apagado, pero lo más próximo posible al límite en el que se enciende.

  • Si lo ajustamos mal y el LED está encendido, no detectamos ningún cambio y no podremos reaccionar a ningún estímulo sonoro.
  • Si lo ajustamos de forma que esté apagado pero demasiado lejos del límite en el que se enciende, habrá que hacer un sonido muy alto para detectar el sonido.
  • Un valor adecuado para una sensibilidad adecuada es que en la salida analógica haya un valor entre 530 y 600.

Para encender un led con dos palmadas consecutivas usar este código: https://github.com/jecrespo/Arduino-Kit-China-Guide/blob/master/01-Microfono/encender_palmas/encender_palmas.ino

Práctica: Funciones Definidas de Usuario

Menú Interactivo

Hacer un menú interactivo a través del puerto serie donde al pulsar la opción 1 enciende el led del pin 9, al pulsar la opción 2 apaga el led del pin 9 y al pulsar la opción 3 mido el voltaje que tengo en la entrada analógica A0 conectada a un potenciómetro y la muestra por pantalla.

Instalación:

Solución Ejercicio16: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio16-Menu_Interactivo

Función Detecta flanco

Señales digitales:

Hacer una función que detecte flancos ascendentes y descendentes, para ser reutilizada en otros proyectos.

Ponerla en un ejemplo con alguno de los botones.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio09-Funcion_Detecta_Flanco

Para ejercicio detecta flanco, probar con dos botones en los pines 2 y 3. La función detecta flanco solo funciona con un pulsador, pero cuando se intenta usar con dos pulsadores ya no funciona, la solución es crear un objeto.

Código para detectar flanco en dos pulsadores que falla: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/blob/master/Ejercicio09-Funcion_Detecta_Flanco_Error/Ejercicio09-Funcion_Detecta_Flanco_Error.ino

Dado Digital

Usando las funciones de números aleatorios hacer un dado digital que genere un número aleatorio entre 1 y 4 y encienda un led aleatorio cada vez que se pulse el botón A.

Usar la función de detección de flanco hecha en el anterior ejercicio.

Random Numbers

  • randomSeed() – Inicializa el generador de número pseudo-aleatorios
  • random() – Genera números pseudo-aleatorios

Paso 1 – Generar un valor aleatorio entre 1 y 4 al pulsar el botón

Paso 2 – Apagar el led anteriormente encendido y encender el nuevo led.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio10-Dado

Ejercicio propuesto. Hacer una ruleta electrónica con un neopixel ring

Tratamiento Avanzado de Strings

Como ya se ha visto anteriormente el tratamiento de strings es un parte muy importante en Arduino puesto que se usa muy frecuentemente y principalmente usamos en las comunicaciones, ya sea puerto serie, bluetooth, XBee, http, etc…

El uso de strings hace un uso intensivo de memoria lo que hace que podamos tener comportamientos extraños en los sketchs o incluso tengamos desbordamiento de memoria.

A la hora de usar strings en Arduino, podemos hacer uso de la clase String https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/ que nos ofrece unos métodos y es muy sencilla de usar, a cambio de ser poco eficiente a nivel de SRAM o usar los stringshttps://arduino.cc/reference/en/language/variables/data-types/string/ como arrays de chars https://arduino.cc/reference/en/language/variables/data-types/char/ que es más complejo de manejar pero más potente y tenemos más control del uso de memoria y pueden usarse muchas de las funciones estandard de C++.

String (Objeto)

Arduino nos ofrece una clase llamada String que facilita el uso de de las cadenas de caracteres con unos métodos muy sencillos de usar y poder usar los operadores que conocemos para los Strings.

Se trata de una clase que permite usar y manipular cadenas de texto de una forma más sencilla que los strings. Puedes concatenar, añadir, buscar, etc… usando los métodos/funciones que ofrece esta clase.

Los Strings tienen un uso intensivo de memoria, pero son muy útiles y se van a utilizar mucho en el apartado de comunicación, por ese motivo es importante aprender a manejar los Strings.

Tener en cuenta que al no ser un tipo de dato propiamente dicho sino una clase, tienes unas funciones asociadas (métodos), operadores y unas propiedades. Es una abstracción del dato y para aprender a usarlo hay que leerse la documentación correspondiente.

Toda la información de la clase String está en: https://arduino.cc/reference/en/language/variables/data-types/stringobject/

Ver documentación de Arduino sobre la clase String:

Tutoriales de uso de String:https://arduino.cc/en/Tutorial/BuiltInExamples#strings

Prácticas Manejo de Strings

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringLengthTrim donde se hace uso de las funciones length() y trim().

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringStartsWithEndsWith donde se hace uso de las funciones StartsWith() y EndsWith().

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringSubstring donde se hace uso de la función substring().

Ejecutar el ejemplo https://arduino.cc/en/Tutorial/StringToInt donde se hace uso de la función toInt()

Otra de las funciones más útiles de String es IndexOf() con ejemplos en https://www.arduino.cc/en/Tutorial/StringIndexOf

Ejercicio: Conectarse a www.aprendiendoarduino.com y analizar el texto descargado. El texto descargado es una página web que contiene datos de una música a tocar por el buzzer

Hacerlo usando la clase String.

Obtener y sacar por el puerto serie:

  • Tamaño de la web (número de caracteres)
  • Localizar las cadenas: “Inicio Notas”, “Fin Notas”, “Inicio Duración” y “Fin Duración”
  • Obtener las notas (frecuencia) y la duración de las notas. Luego reproducirlo.

Solución: https://github.com/jecrespo/aprendiendoarduino-Curso_Programacion_Arduino/tree/master/Ejercicio16-Strings_Avanzado

string (Array de chars)

Un string es un array de chars. Cuando se trabaja con grandes cantidades de texto, es conveniente usar un array de strings. Puesto que los strings son en si mismo arrays. En el reference de Arduino https://arduino.cc/reference/en/language/variables/data-types/string/

La notación de un string como array de chars es char*

El core de Arduino me ofrece varias funciones de análisis de caracteres: https://arduino.cc/reference/en/language/variables/data-types/string/

Una cadena en C++ es un conjunto de caracteres, o valores de tipo char, terminados con el carácter nulo, es decir el valor numérico 0 (\0). Internamente, en el ordenador, se almacenan en posiciones consecutivas de memoria. Este tipo de estructuras recibe un tratamiento muy especial, ya que es de gran utilidad y su uso es continuo. La manera de definir una cadena es la siguiente: char <identificador> [<longitud máxima>];

Cuando se declara una cadena hay que tener en cuenta que tendremos que reservar una posición para almacenar el carácter nulo terminador, de modo que si queremos almacenar la cadena “HOLA”, tendremos que declarar la cadena como: char Saludo[5]; Las cuatro primeras posiciones se usan para almacenar los caracteres “HOLA” y la posición extra, para el carácter nulo.

También nos será posible hacer referencia a cada uno de los caracteres individuales que componen la cadena, simplemente indicando la posición. Por ejemplo el tercer carácter de nuestra cadena de ejemplo será la ‘L’, podemos hacer referencia a él como Saludo[2].

Se puede manipular las cadenas de caracteres de la misma manera en que manipula cualquier otro tipo de array, sin embargo, es preferible hacer uso de una librería estándar especialmente escrita para manipulación de cadenas de caracteres, se trata de la librería <string.h> y que viene incluida con todo compilador de C, C++.

Reference de C++ para la clase string http://cplusplus.com/reference/string/string/ y http://cplusplus.com/reference/cstring/ con funciones como strcpy para strings null-terminated.

Los compiladores de C, C++ dan soporte a la biblioteca de funciones <string.h>, a la que accede por medio de la directiva #include <string.h>. No veremos en detalle todas las funciones contenidas en dicha biblioteca, y nos limitaremos a mostrar algunos ejemplos de ciertas funciones importantes.

  • strlen(): Obtener longitud de cadenas. Sintaxis: size_t strlen(const char *s);
  • strcpy(): Copiar cadenas. Sintaxis: char *stpcpy(char *dest, const char *src);
  • strcat(): Concatenar cadenas. Sintaxis: char *strcat(char *dest, const char *src);
  • strlwr(): Convertir a minúsculas. Sintaxis: char *strlwr(char *dest);
  • strupr(): Convertir a mayúsculas. Sintaxis: char *strupr(char *dest);
  • strchr(): Buscar carácter (hacia adelante). Sintaxis: char *strchr(char *s, int c);
  • strrchr(): Buscar carácter (hacia atras). Sintaxis: char *strrchr(char *s, int c);
  • strstr(): Buscar subcadena. Sintaxis: char *strstr(const char *s1, char *s2);
  • memset(): Establece el primer num bytes del bloque de memoria apuntado por ptr al valor especificado en value (interpretado como un unsigned char).. Sintaxis: void * memset ( void * ptr, int value, size_t num );

Reference:

En C++ también tenemos soporte a la clase cstring, que no debe confundirse con la <string.h>. Una de las ventajas que ofrece la clase cstring es que, a diferencia de las cadenas estándar, ésta posee la capacidad de crecer o disminuir su tamaño en tiempo de ejecución. Además, entre otras características destacables, la clase string soporta operaciones de asignación tales como: =, +, +=, etc.; y de comparación tales como: ==, <=, etc.

Documentacíon de la librería <string.h>: http://www.cplusplus.com/reference/cstring/

Clase string de C++: http://www.cplusplus.com/reference/string/string/

Ejercicio Strings_vs_strings: Partiendo de la base del ejercicio StringsComparisonOperators intentar hacer las operaciones de comparación de igualdad y distinto de los StringOne y StringTwo con string en lugar de String. Ver como es más complicado y para iniciarse en la programación es mejor usar String (objeto) que string (char array).

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio18-strings/_5-String_vs_string

Más información:

Ejercicios Avanzados  Strings

Ejercicio: Mandar un SMS mediante un módulo SIM800L, donde pido por consola el número y el mensaje en formato” <numero_telefono>-<mensaje>!”. Analizar esta cadena y separar en teléfono y mensaje y mandar mediante la función bool sendSms(char* number,char* text);

El primer análisis hacerlo con la clase String y luego pasar las variables teléfono y mensaje a char* que es lo que pide la librería.

Librería disponible en el gestor de librerías: https://github.com/VittorioEsposito/Sim800L-Arduino-Library-revised

HW: https://es.aliexpress.com/item/SIM800L-V2-0-5V-Wireless-GSM-GPRS-MODULE-Quad-Band-W-Antenna-Cable-Cap/32465895576.html

Solución: https://github.com/jecrespo/Aprendiendo-Arduino/tree/master/Ejercicio68-toCharArray

Ejercicio: Manejo de JSON mediante la librería disponible en el gestor de librerías ArduinoJson https://arduinojson.org y repositorio https://github.com/bblanchon/ArduinoJson

JSON: https://es.wikipedia.org/wiki/JSON

Abrir el ejemplo JsonParserExample de la librería y probarlo.

PROGMEM

El uso de strings como cadena de caracteres en Arduino, en lugar de usar la clase String, nos permite también almacenar los strings en la memoria flash en lugar de la SRAM gracias a PROGMEM https://arduino.cc/reference/en/language/variables/utilities/progmem/

A menudo es conveniente cuando se trabaja con grandes cantidades de texto, como un proyecto con una pantalla LCD o en comunicaciones, usar PROGMEM con arrays de strings.  Estos tienden a ser grandes estructuras, así que ponerlas en memoria de programa (flash) es a menudo deseable. El código siguiente ilustra la idea.

 
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "String 0";   // "String 0" etc are strings to store - change to suit.
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";

// Then set up a table to refer to your strings.

const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};

char buffer[30];    // make sure this is large enough for the largest string it must hold

void setup()
{
  Serial.begin(9600);
  while(!Serial);
  Serial.println("OK");
}

void loop()
{
   for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
    Serial.println(buffer);
    delay( 500 );
  }
}

Utilidades de PROGMEM: https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

Usar la tabla de cadenas en la memoria de programa (flash) requiere el uso de funciones especiales para recuperar los datos. La función strcpy_P copia un string desde el espacio del programa (flash) en un string en la memoria RAM (“buffer”). Debemos asegurarnos de que la cadena de recepción en la memoria RAM es lo suficientemente grande como para alojar cualquier string que está recuperando desde el espacio del programa

Las funciones para manejar PROGMEM están en http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html que podemos ver son iguales que las de <string.h>, pero seguidas de “_P”

Tener en cuenta que las variables deben ser definidas de forma global y como constantes, o definido con la palabra clave static, con el fin de trabajar con PROGMEM.

Recordar que podemos usar la macro F() junto con el métodos print y println de forma que todo lo que hay dentro de los métodos se guarda en la memoria flash.

Ejemplo: Serial.println(F(“This string will be stored in flash memory”));

Para saber como funciona PROGMEM ver  la pagina 347 y 354 de http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_datasheet.pdf y donde lo metes lo de MEMPROG

Prácticas Repaso Arduino

Práctica: Ejemplos Básicos con Arduino

Repasar cada uno de los ejemplos básicos:

  • Leer entradas digitales
  • Leer entrada digital sin referencia externa
  • Leer entradas analógicas
  • Leer entrada analógica mejorada
  • Escribir salida analógica
  • Escribir salida digital con acción de un botón
  • Mejora de botón para evitar rebotes
  • Contar pulsaciones

Ejemplos básicos con Arduino: http://jecrespo.github.io/ArduinoBasicExamples/

Práctica: Detectar Flanco

Hacer un sistema de encendido y apagado de un led mediante una pulsación. Con una pulsación enciende y con otra apaga el led. Para hacer esto debemos detectar flancos al encender y apagar.

Usar la resistencia interna de pull up de Arduino para detectar la pulsación de un botón en el pin 2 (leer estado de una entrada digital) y encender/apagar el led puesto en el pin 10 (no olvidar la resistencia) al detectar un flanco ascendente. Adicionalmente sacar por el monitor serie el estado de pulsación del botón con un 1 (pulsado) o un 0 (no pulsado) y en la misma línea el estado del led con un 3 (led encendido) y 0 (led apagado), de esta forma abriendo el Serial Plotter es posible ver cuando se enciende y apaga el led al detectar flancos.

Esquema de conexión:

Resultado:

Solución Ejercicio01: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio01-Detectar_Flanco

Solución a los Rebotes (Debounce)

Los rebotes son las falsas pulsaciones que se producen al hacer falsos contactos en el interruptor.

Para ello esperar un tiempo llamado debounceDelay para comprobar que el cambio de estado se mantiene y no son rebotes (ruido).

Para ello crear una variable “debounceDelay” que pueda cambiar su valor y sea el tiempo mínimo en ms que debe estar la señal estable para considerar que no es un rebote. En cada loop comprobar el tiempo desde el último cambio de estado de la señal digital y si es mayor que “debounceDelay” proceder a hacer las comprobaciones de flanco y encender o apagar el LED.

Más información https://www.arduino.cc/en/Tutorial/Debounce

Solución Ejercicio02: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio02-Detectar_Flanco_Debounce

Otra forma de solucionar los rebotes por código:

http://miarduinounotieneunblog.blogspot.com.es/2016/01/pulsador-antirrebote-con-contador-de.html ¿véis algún problema con esta solución? Si hay ruido o la señal cambia continuamente, nunca sale del bucle y el programa no puede hacer otras cosas.

Solución: El código puede quedarse durante mucho tiempo en la función antirrebote(), bloqueado Arduino para hacer otras tareas.

Solucionar rebotes por HW:

Calculadora de valores para debouncing: http://protological.com/debounce-calaculator/

Práctica: Medir valor de un Condensador

Usar un Arduino para medir el valor de un Condensador. En este ejercicio se usan pines digitales de entrada y salida para manejar las corrientes y una entrada analógica para leer el voltaje.

Ver: https://www.arduino.cc/en/Tutorial/CapacitanceMeter

Esquema de conexión:

¡ATENCIÓN! Poner un condensador de 100uF y asegurarse de poner correctamente la polaridad. Símbolo – (patilla con símbolo – – – -) a masa.

La resistencia R tiene un valor de 10Kohms.

Al conectar un condensador en serie con una resistencia, a una fuente de tensión eléctrica (o comúnmente, fuente de alimentación), la corriente empieza a circular por ambos. El condensador va acumulando carga entre sus placas. Cuando el condensador se encuentra totalmente cargado, deja de circular corriente por el circuito.

TC = R * C

  • R resistencia de carga en ohms
  • C capacidad del condensador en faradios

Explicación del sketch:

  • Configurar el pin de descarga a INPUT (alta impedancia de modo que no pueda descargar el condensador). Pin 11.
  • Registre el tiempo de inicio con millis ()
  • Establecer el pin de carga en OUTPUT y ponerlo a HIGH. Pin 13.
  • Compruebe la tensión repetidamente en un bucle hasta que llegue a 63.2% de la tensión total.
  • Después de cargar, restar el tiempo actual de la hora de inicio para averiguar cuánto tiempo le costó al condensador para cargar.
  • Dividir el Tiempo en segundos por la resistencia de carga en ohmios para encontrar la Capacitancia.
  • Imprimir por serial el valor con serial.print
  • Descargue el condensador. Para hacer esto:
    • Poner a LOW el pin de carga en la entrada
    • Configurar el de descarga en OUTPUT y haga que sea LOW
    • Leer el voltaje para asegurarse de que el condensador está completamente descargado
    • Loop y hacerlo de nuevo

Para asegurarse que el condensador está descargado, asegurarse de quitar alimentación cuando lo indique el sketch por pantalla.

Solución Ejercicio03: https://github.com/jecrespo/aprendiendoarduino-Curso_Arduino_Avanzado_2017/tree/master/Ejercicio03-Medidor_Condensadores

Para ampliar la explicación del ejercicio https://www.arduino.cc/en/Tutorial/CapacitanceMeter

Más Prácticas

Otros ejemplos sencillos de prácticas con Arduino en https://aprendiendoarduino.wordpress.com/2017/07/04/ejemplos-sencillos-arduino/, usando este montaje de prácticas https://aprendiendoarduino.wordpress.com/2017/07/02/montaje-practicas/

  • Leer LDR
  • Contar Pulsos
  • Mover Servo