⚡Electronario II⚡
ELECTRÓNICA BÁSICA PARA LA ENSEÑANZA EN DISEÑO
Julían Pérez Romero
info@julian-perez.com
Escuela Superior de Diseño de Madrid
27-31 Enero 2019
Resumen Curso
-
Procesos avanzados:
-
multi-tarea, interruptores, temporizador, eeprom
-
Resistencias pull-down, pull-up
-
Comunicación serial, datalogger, módulo Bluetooth
-
-
Conexión con datos y servicios, Internet of things: nodeMCU, raspberry Pi
Breve repaso
PWM
Analog / Digital
Servomotor / Motor DC
Comunicación serial
Firmata
¿?

Pad con anotaciones
DÍA1
- Tiempo: delay() vs millis()
- Entrada digital: pull-up/-down
Nuevos métodos de trabajo con Arduino
delay(1000)
¿Cómo gestionamos el tiempo en arduino?
Para comenzar está bien, pero conforme avanzamos hay que aprender otras formas de trabajar con el tiempo. El delay lo utilizaremos para ralentizar lecturas y evitar rebotes
¿Cómo gestionamos el tiempo en arduino?
millis()
- Devuelve número en milisegundos desde que arranca el programa
- Puede durar hasta casi 50 días (y vuelve a cero)
-
variable unsigned long (de 0 a 4,294,967,295)
delay() VS millis()
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}
unsigned long tiempo=0;
unsigned long tiempoLed=0;
int blink=500;
boolean estado=false;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
tiempo = millis();
if(tiempo >= (tiempoLed+blink)){
tiempoLed=tiempo;
estado = !estado;
digitalWrite(LED_BUILTIN,estado);
}
}
lineal :(
multi-tarea :)
ejemplo blink led
*síncrono
Ejercicio millis()
blink de un segundo LED parpadeando al doble de velocidad del primer LED
10 minutos
Ejercicio millis()
Diferentes tiempos de encendido y apagado que no se podrían conseguir con delay().
Ejercicio millis()
Entrada digital
No vale con conectar un interruptor a un pin digital de entrada. Probémoslo

int val;
void setup() {
Serial.begin(9600);
pinMode(7,INPUT);
}
void loop() {
val=digitalRead(7);
if(val == HIGH){
Serial.println("1");
}else{
Serial.print("0");
}
}
Conectando un led lo veremos mejor

int val;
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT);
pinMode(7,INPUT);
}
void loop() {
val=digitalRead(7);
if(val == HIGH){
digitalWrite(13,HIGH);
Serial.println("1");
}else{
digitalWrite(13,LOW);
Serial.print("0");
}
}
Entrada digital
¿Por qué ocurre esto? --> ENTRADA FLOTANTE

Las entradas flotantes en digital no da resultados fiables. Actúa de antena y recibe mucho ruido, pudiendo dar 0 y 1
Entrada digital
¿Cómo podemos hacer que funcione bien?
Circuito pull-up / pull-down
Entrada digital: circuito pull-up / pull-down

Referencia de voltaje
Entrada digital: circuito pull-up / pull-down



Entrada digital: circuito pull-up / pull-down
El chip ATmega trae integradas resistencias de 20Kohm que podemos utilizar para definir los puertos como entradas con resistencia Pull-Up
Para ello tendremos que definirlo en el código: pinMode(7, INPUT_PULLUP);
INPUT_PULLUP
Entrada digital: circuito pull-up / pull-down
int inputPin = 8;
void setup(){
Serial.begin(9600);
pinMode(inputPin, INPUT_PULLUP); //Cambiamos a INPUT
}
void loop(){
Serial.println(digitalRead(inputPin));
}
INPUT_PULLUP
Entrada digital: circuito pull-up / pull-down
pull-down
pull-up


10 Kohm
Entrada digital: circuito pull-up / pull-down
Ejercicio pull-up/pull-down
Programamos arduino en función de cada circuito
20 minutos
DÍA2
- Interrupciones externas (ISR)
- Memoria EEPROM
Nuevos métodos de trabajo con Arduino
Interrupciones

ISR (Interruption Service Rutine)
Interrupciones

Microcontrolador: ATmega 328p

Interrupciones
- Para qué sirven? para tener una atención inmediata de una entrada. Por ejemplo, un mando de juego, una colisión, etc.
- Con el sistema pullup puede que el tiempo que tarda hasta que el programa llega para leer la entrada sea inaceptable..
-
..y si el pulso es muy corto, o si el procesador está ocupado haciendo otra tarea mientras se produce, es posible que nos saltemos el disparo y nunca lleguemos a verlo.
-
Nos permite lanzar una serie de instrucciones independientemente de lo que esté pasando en el código principal
Tipos de Interrupciones
-
Interrupciones HW o externas: se pueden producir en cualquier momento independientemente de lo que esté haciendo el MCU en ese momento. Las causas que las producen son externas al procesador y a menudo suelen estar ligadas con los distintos dispositivos de entrada o salida.
-
Interrupciones SW: Arduino no soporta las interrupciones por software
-
Timer (interno). Son las interrupciones asociadas a los timers y gracias a ellas funciona millis().
- Excepciones: Normalmente son causadas al realizarse operaciones no permitidas tales como la división entre 0, el desbordamiento, el acceso a una posición de memoria no permitida, etc.
Interrupciones en Arduino
2 tipos de interrupciones en Arduino
- Externas
- Cambio de pin
Interrupciones externas en Arduino
Definimos una Interrupción:
-
Pin que recibe la señal de disparo
-
Condición de disparo
- Función que se ejecuta cuando recibe el disparo (callback function)
Condiciones de disparo:
-
LOW, La interrupción se dispara cuando el pin es LOW
-
CHANGE, Se dispara cuando pase de HIGH a LOW o viceversa
-
RISING, Dispara en el flanco de subida (Cuando pasa de LOW a HIGH)
-
FALLING, Dispara en el flanco de bajada (Cuando pasa de HIGH a LOW)
- *solo para Arduino DUE: HIGH se dispara cuando el pin esta HIGH.
Interrupciones externas en Arduino

Sólo hay 2 pines que soportan las interrupciones externas que son INT0 e INT1, mapeados al pin 2 y al pin 3
Si necesitas más interrupciones externas --> Arduino MEGA o DUE
En el pin de reset también hay otra interrupción que sólo se dispara cuando detecta voltaje LOW y provoca el reinicio del microcontrolador
Interrupciones externas en Arduino
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)
Interrupciones externas en Arduino
Ej.: attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
Arduino Reference (ver tabla): attachInterrupt()
Función para utilizar interrupciones
Interrupciones externas en Arduino
-
Las variables que se vayan a utilizar dentro y fuera de la ISR se tienen que declarar como "volatile"
-
No se pueden recibir ni devolver parámetros
-
delay() y millis() no se recomiendan dentro de una ISR ya que dependen de otras interrupciones. Serial también, va muy lenta.
-
no pueden funcionar varias ISRs a la vez, van una detrás de otra y hay una tabla de prioridad de ISRs
- Una ISR tiene que ser tan corta y rápida como sea posible, entrar y salir
Cosas a tener en cuenta:
Interrupciones externas en Arduino
Ejercicio interruptor
Hacemos un contador que vaya sumando en función de las veces que se pulse el botón. Mostramos el resultado por monitor serie
ó
Cambiamos el estado de encendido o apagado con cada pulsación
Interrupciones externas en Arduino
Ejercicio Multitasking
3 leds. 2 leds parpadean a tiempos diferentes, y el tercer led tiene que encenderse y apagarse con una interrupción externa mediante botón.
Interrupciones externas en Arduino
Ejercicio Interrupción
Utilizamos módulos que permitan una interrupción externa como por ejemplo:
- FotoInterruptor
- Sensor de llama
- Sensor de sonido
- Sensor de inclinación (tilt)
- Sensor Efecto Hall (imán)
- Sensor de Knock-knock
...
Memoria EEPROM
Electrically Erasable Programmable Read Only Memory

Memoria EEPROM
Qué tipos de memoria tenemos en Arduino?
-
FLASH, no volátil, donde grabamos el sketch (incluido el bootloader)
-
SRAM (static random access memory), volátil, donde se almacenan las variables durante el funcionamiento
- EEPROM, no volátil, que podemos usar para almacenar información entre reinicios.
Memoria EEPROM
Características EEPROM
- Mantiene los valores almacenados cuando se pierde la alimentación
- Arduino UNO: 1KB. MEGA: 4KB. Poca memoria
- Tiene una vida limitada de escritura: 100.000 cada celda. En realidad 100.000 es lo garantizado por fabricante pero se puede hasta casi 1 millón. Las lecturas son ilimitadas
- Está pensada para realizar escrituras con tiempos largos entre ellas, no un uso constante de la misma
Memoria EEPROM
Tiempos de uso EEPROM
- Apenas 5 minutos si, por error, grabamos constantemente
- Aproximadamente un día, si grabamos cada segundo
- Unos 27 años si grabamos 10 veces al día
Tiempo de escritura: 3.3ms
Tiempo de lectura: 3.3ms
Memoria EEPROM
Qué pasa si agotamos la vida útil de la EEPROM de nuestro Arduino?
NO PASA NADA
Existen módulos con memorias EEPROM externas

Memoria EEPROM
Algunos ejemplos de la memoria EEPROM
- Guardar una contraseña personalizada
- Grabar una secuencia de valores corta en el tiempo
- Lista HighScores en un videojuego arcade
- Salvar una serie de configuraciones específicas, por ejemplo una alarma de reloj
- Etc..
Memoria EEPROM
................................
0 1 2 3 4 5 6 7
1023
Dirección
1 Byte
=
8 bits
- 0 - 255 valores (decimal)
- 00 - FF (hexadecimal)
- 00000000 - 11111111 (binario)
Por defecto todas las casillas vienen con valor 1 lógico ( o 255)
Memoria EEPROM


Memoria EEPROM
- EEPROM.length() --> Tamaño en bytes de nuestra memoria
- EEPROM.read(dirección) --> lee el valor de la celda (dirección)
- EEPROM.write(dirección, valor) --> escribe el valor en la celda
Memoria EEPROM
#include <EEPROM.h>
void setup() {
Serial.begin(9600);
Serial.print("Capacidad de memoria: ");
Serial.println( EEPROM.length() );
Serial.println(" ");
Serial.print("Valor almacenado en direccion 0: ");
Serial.println( EEPROM.read(0) );
Serial.print("Almacenando numero 39 en direccion 0");
EEPROM.write(0, 39);
}
void loop() {
}
Ejemplo 1
Autor código: Bitwise Ar
Memoria EEPROM
Memoria EEPROM
................................
0 1 2 3 4 5 6 7
1023
Dirección
1 Byte
=
8 bits
- int: 2 bytes - 16bits (-32,768 a 32,767)
- float: 4 bytes - 32bits (3.4028235E+38 a -3.4028235E+38)
- char [n]: n bytes (cadena de caracteres)
Memoria EEPROM
- EEPROM.get(dirección de inicio, valor) --> Leer
- EEPROM.put(dirección de inicio, valor) --> Escribir
Memoria EEPROM
#include <EEPROM.h>
float temperatura = 27.50;
char cadena[] = "Hola esta es una prueba";
void setup() {
Serial.begin(9600);
EEPROM.put(0, temperatura);
EEPROM.put(10, cadena);
Serial.println("Valor de punto flotante en direccion 0:");
Serial.println( EEPROM.get(0, temperatura) );
Serial.println(" ");
Serial.println("Valor de la cadena en direccion 10:");
Serial.println( EEPROM.get(10, cadena) );
}
void loop() {
}
Ejemplo 2
Autor código: Bitwise Ar
Memoria EEPROM
- EEPROM.update(dirección de inicio, valor) --> Actualiza. Si la celda tiene el mismo valor no sobreescribe
Memoria EEPROM
Ejercicio EEPROM
- Con un potenciómetro movemos un servo
- los valores de movimiento los guardamos en la eeprom para hacer un playback después de que usemos todas las direcciones de la memoria
- Importante: hacerlo todo dentro del void setup
DÍA3
- Comunicación Puerto Serie
- Comunicación I2C
- Módulo Bluetooth HC-05
Conectividad entre arduinos
Comunicación Puerto Serie

TX -> 1
RX <- 0
Comunicación Serial

Librería SoftwareSerial
Comunicación I2C
-
Es un protocolo serial para una comunicación de baja velocidad con una interfaz de dos conexiones
-
Se desarrolló mayormente en la industria de los televirores pero la podemos encontrar en la mayoría de MCUs. Phillips 1982
-
Pequeñas distancias: 1 metro a 1Kbaudio de velocidad
- Los módulos que trabajan con i2c suelen tener 4 pines: VCC, GND, SCL, SDA
Inter Integrated Circuit Bus
Comunicación I2C
Inter Integrated Circuit Bus

Comunicación I2C
Inter Integrated Circuit Bus
Código Arduino MASTER
#include <Wire.h>
#define SLAVE_ADDR 9 // Define Slave I2C Address
int analogPin = 0;
int val = 0;
void setup() {
Wire.begin(); //Al iniciar sin datos, arduino sabe que es el master
}
void loop() {
delay(50);
val = analogRead(analogPin)/4;
Wire.beginTransmission(SLAVE_ADDR); //Conectamos al Slave en su address
Wire.write(val); // Escribimos el valor mapeado
Wire.endTransmission(); //Cerramos comunicación
}
Comunicación I2C
Código Arduino SLAVE
#include <Wire.h>
#define SLAVE_ADDR 9
int LED = 13;
int rd; // Variable para los datos recibidos
int br; // Variable para la freq del blink
void setup() {
pinMode(LED, OUTPUT);
Wire.begin(SLAVE_ADDR);
// Funcion que se ejecuta cuando recibe datos desde el Master
Wire.onReceive(receiveEvent);
Serial.begin(9600);
Serial.println("I2C Slave");
}
void receiveEvent() {
rd = Wire.read();
Serial.println(rd);
}
void loop() {
delay(50);
// Calculate blink value
br = map(rd, 1, 255, 100, 2000);
digitalWrite(LED, HIGH);
delay(br);
digitalWrite(LED, LOW);
delay(br);
}
Módulo HC-05 Bluetooth

Módulo HC-05 Bluetooth
- Comunicación de radiofrequencia en una banda de 2.4Ghz de corto alcance (5 a 10 mts.)
- La comunicación funciona a 38400 Baudios (bps)
- Bajo consumo
- Nos comunicamos a través de él serialmente
- Master/Slave
- Modo Configuración / Usuario
- Comandos AT (Hayes)
- Pin Layout

Módulo HC-05 Bluetooth
Módulo HC-05 Bluetooth
Entramos en modo Configuración
Para entrar en el modo configuración, tenemos que dejar pulsado el botón del módulo con el pin vcc quitado, conectar el pin vcc y esperar 5s hasta que comience a parpadear. Si parpadea más lento que en el modo usuario sabremos que hemos entrado
Módulo HC-05 Bluetooth
Comandos AT que usaremos
*En el monitor serie indicamos "Ambos NL & RC" para ver correctamente los mensajes de vuelta del módulo
- AT --> OK (Este es el hello world, con esto sabemos que la conexión está establecida entre arduino y el módulo)
- AT+NAME? --> Preguntamos el nombre que tiene fijado
-
AT+NAME=MiBluetooth --> Asignamos un nombre al módulo
- AT+PSWD --> Contraseña
- AT+UART -->Velocidad de transmisión
- AT+ROLE --> Maestro=1, Esclavo=0
- AT+ORGL --> Restaura a valores de fábrica
- AT+RESET --> Sale del modo configuración y pasa al modo Usuario
- AT+ADDR --> Dirección única de nuestro módulo
- AT+CMODE=0 --> Conexión fija a una dirección
-
AT+BIND=address(con comas) --> Conexión a una dirección que le indiquemos
Módulo HC-05 Bluetooth
Conexión con App Bluetooth Serial Controller
- Instalamos la app desde el Play Store
- Vinculamos dispositivos a través de bluetooth. Debe aparecer el nombre que le hayamos indicado previamente
- Ajustamos parámetros: Name, Command, Repeatable para cada botón
Módulo HC-05 Bluetooth
Ejercicio1: configuramos la interfaz de la app para enviar on/off a un par de leds
Ejercicio2: el segundo led controlamos PWM para subir o bajar el brillo
Módulo HC-05 Bluetooth
Conexión entre 2 Arduinos

MASTER(1)
SLAVE(0)
Módulo HC-05 Bluetooth
Código MASTER
#include <SoftwareSerial.h>
SoftwareSerial miBT(10, 11);
int led1 = 13;
int stateLed = 0;
int potVal = 0;
void setup() {
pinMode(led1, OUTPUT);
digitalWrite(led1, LOW);
miBT.begin(38400);
}
void loop() {
if(miBT.available() > 0){ // Están entrando datos por el puerto serie?
stateLed = miBT.read(); // Lee los datos que están entrando: 0 ó 1
}
if (stateLed == '1') {
digitalWrite(led1, HIGH);
stateLed = 0;
}else if (stateLed == '0') {
digitalWrite(led1, LOW);
stateLed = 0;
}
potVal = analogRead(A0)/4;
miBT.write(potVal); // Enviamos valores al servo
delay(10);
}
Módulo HC-05 Bluetooth
Código SLAVE
#include <Servo.h>
#include <SoftwareSerial.h>
SoftwareSerial miBT(10, 11);
Servo myServo;
int button = 8;
int state = 20;
int buttonState = 0;
void setup() {
pinMode(button, INPUT);
myServo.attach(9);
miBT.begin(38400);
}
void loop() {
if(miBT.available() > 0){
state = miBT.read();
}
myServo.write(state);
delay(10);
buttonState = digitalRead(button);
if (buttonState == HIGH) {
miBT.write('1');
}
else {
miBT.write('0');
}
}
DÍA4
- NodeMCU v3
- Adafruit.io+IFTTT
Internet of Things
NodeMCU v3
Placa de desarrollo sobre ESP



Versiones Módulo ESP
Versiones Kit NodeMCU
Fuente Imagen: programarfacil.com
NodeMCU
NodeMCU

- 32bits
- 80-160MHz
- wifi 2.4GHz
- RAM 50KB
- 1ADC
- 17GPIO
- acceso fácil
- Antena
- Led
- Prototipado
- Conversor USB-Serie
- Acceso pines
- 3 pines 3,3V
- 1 pin 5V
- 4 pin GND
- Leds de estado
- Botón reset y flash
Fuente Imagen: programarfacil.com
NodeMCU

Fuente Imagen: programarfacil.com
NodeMCU
PINOUT
Pines digitales
La referencia en el Arduino IDE corresponde al valor GPIO

Fuente Imagen: programarfacil.com
NodeMCU
LEDS
- Led módulo ESP8266 > D4 = GPIO 2
- Led Kit NodeMCU > D9= GPIO16

Importante! Para encender leds mandar estado LOW o 0 y viceversa
NodeMCU
Drivers USB
Probar sin instalar driver, por si acaso nuestro pc lo tiene instalado ya
NodeMCU
Placa NodeMCU en Arduino IDE
https://arduino.esp8266.com/stable/package_esp8266com_index.json
Preferencias > pegar link en campo "Gestor de URLs adicionales de tarjetas", Ok
NodeMCU
-
Prueba 1: hello world
-
Prueba 2: encendemos led desde un navegador
NodeMCU

- Creamos una cuenta
- Creamos un "feed"
NodeMCU

- Creamos una cuenta
- Creamos un "feed" (p.ej.: command)
- Ajustamos parámetros del código
NodeMCU

- Creamos una cuenta
- Conectamos servicios que queramos usar
- Creamos una receta conectando con applet Adafruit.io
Conclusiones
- Qué os ha parecido el curso?
- Habéis echado algo en falta?
- Con qué cosas os habéis quedado que podáis poner en práctica con vuestros alumnos?
- Alguna idea de proyecto personal o colectivo?
Gracias!!
info@julian-perez.com
twitter: @largocreatura
Electronario II - ESDM
By Julián Pérez
Electronario II - ESDM
- 880