lunes, 4 de julio de 2016

Sensor IR e interrupciones Arduino

En esta entrada hablaré de los sensores de infrarrojos o IR y de como declarar y utilizar las interrupciones del arduino.



Las interrupciones son partes del código que se ejecutan cuando se produce un cierto evento sin importar en la parte del ciclo de ejecución en el que se encuentre el código, volviendo a retomarlo cuando acabe de ejecutar el código de la interrupción.


Los sensores IR nos permiten leer los mandos a distancia o cualquier otro dispositivo que emita en la misma frecuencia, estos sensores son digitales con lo que la lectura la realizaremos desde un Pin digital, son ideales para proyectos de control a distancia.

Ejemplo completo: Sensor_IR
Librería necesaria para el sensor: NECIRrcv

En esta entrada al igual que en la anterior solo explicaré las funciones más utilizadas de la librería y como declarar y utilizar una interrupción:

Comencemos con el código:

Lo primero es declarar el pin en el que se encuentra el sensor IR:

#define IRPIN 2 
NECIRrcv ir(IRPIN);

Una vez incluidas las librerías necesarias dentro de nuestro programa tendremos que iniciar el sensor y la interrupción dentro del void setup():


void setup() 
{
  Serial.begin(9600);
  ir.begin();
  Serial.println("NEC IR code reception");
 attachInterrupt(0, LecturaIR, RISING); // Pin asociado, 0 = Pin 2 1 = Pin 3, nombre de la interrupción, evento que la activa RISING sería un flanco positivo en el pin 2.
}

Una vez iniciado todo ya podemos utilizar el sensor IR para hacer una lectura de un mando, esto lo haré dentro de la interrupción:

void LecturaIR()
{
    unsigned long ircode ;
    while (ir.available()) 
    {
    ircode = ir.read();
    Serial.print("got code: ");
    Serial.println(ircode,HEX);
  }
}

Esquema de conexiones:


lunes, 27 de junio de 2016

Reloj digital con Arduino y LCD I2C

En esta entrada os dejare un ejemplo de reloj digital con calendario creado con un arduino, con el modulo rtc y la pantalla lcd de entradas anteriores.



Programa completo: Reloj
Entrada sobre la RTC: RTC DS1302
Entrada sobre LCD: LCD I2C Arduino

Las conexiones se explican en las entradas que se encuentran en los links superiores.

En esta entrada seré mas breve que en las anteriores y solo explicare las partes más interesantes, bien comencemos con el código:

Para hacer la lectura de la hora tenemos que crear una variable de tipo Time en la cual cargaremos el valor actual de nuestra RTC, para ello utilizaremos las siguientes funciones:

 Time t; //Para crear la variable de tipo time a la cual llamaremos t
 rtc.getTime(); // Para actualizar el valor de la RTC, esto función deberemos cargarla en la variable t
 t = rtc.getTime();

Para acceder a los datos de la fecha y la hora tendremos que utilizar las siguientes funciones:

t.sec; // Segundos
t.min; // Minutos
t.hour // Horas
t.dow // Dia de la semana
t.date // Dia del mes
t.year //Año

viernes, 17 de junio de 2016

Lectura de mando clásico de WII con Arduino

En esta entrada os dejare la librería y un ejemplo que permite hacer una lectura del mando clásico de WII el cual podréis utilizar luego en futuros proyectos. Esta librería la cree yo modificando una ya existente destinada a la lectura del Nunchuk o Wiichuck.


Librería mando clásico: WiiClassic
Librería original nunchuck: Wiichuck
Ejemplo de lectura de ambas librerías: Ejemplos

Ahora os explicare por encima las funciones más comunes de estas librerías y como seria la conexión de los mando con el Arduino:

La comunicación del mando se realiza por el protocolo I2C, aquí os dejo una imagen con los pines correspondientes a DAT, CLK, VCC(conectar a 3.3V) y GND:

Comencemos con el código:

Como con todas las librerías nuevas lo primero es incluirla en la cabecera del programa, una vez incluida tendremos que declarar el nombre de nuestro mando:

#include <WiiClassic.h>
#include <Wire.h>
WiiClassic classic = WiiClassic();// En mi caso lo nombre como classic

Una vez nombrado tendremos que iniciarlo dentro del void setup():

void setup() 
{
  Serial.begin(9600);
  classic.begin();//Inicia la comunicación
  classic.update();//Actualiza el estado de los botones y sensores
  delay(2000);
}

Ahora que la comunicación ya esta iniciada podremos leer el estado de los botones y de los sensores dentro del void loop():

void loop() 
{  
  classic.update();
  Serial.println("-----------------------");
  Serial.print("Boton L: "); Serial.print((int)classic.LecturaLB()); Serial.println();
  Serial.print("Potenciómetro L: "); Serial.print((int)classic.readL()); Serial.println();
  Serial.print("Boton ZL: "); Serial.print((int)classic.LecturaZL()); Serial.println();
  Serial.println();
  Serial.print("Boton arriba: "); Serial.print((int)classic.LecturaArriba()); Serial.println();
  Serial.print("Boton abajo: "); Serial.print((int)classic.LecturaAbajo()); Serial.println();
  Serial.print("Boton derecha: "); Serial.print((int)classic.LecturaDerecha()); Serial.println();
  Serial.print("Boton izquierda: "); Serial.print((int)classic.LecturaIzquierda()); Serial.println();
  Serial.println();
  Serial.print("Joystick Derecho X: "); Serial.print((int)classic.readJoyRX()); Serial.println();
  Serial.print("Joystick Derecho Y: "); Serial.print((int)classic.readJoyRY()); Serial.println();
  Serial.println();
  Serial.println();
  Serial.print("Boton Menos: "); Serial.print((int)classic.LecturaMenos()); Serial.println();
  Serial.print("Boton Home: "); Serial.print((int)classic.LecturaHome()); Serial.println();
  Serial.print("Boton Mas: "); Serial.print((int)classic.LecturaMas()); Serial.println();
  Serial.println();
  Serial.print("Joystick Izquierdo X: "); Serial.print((int)classic.readJoyLX()); Serial.println();
  Serial.print("Joystick Izquierdo Y: "); Serial.print((int)classic.readJoyLY()); Serial.println();
  Serial.println();
  Serial.print("Boton a: "); Serial.print((int)classic.LecturaA()); Serial.println();
  Serial.print("Boton b: "); Serial.print((int)classic.LecturaB()); Serial.println();
  Serial.print("Boton x: "); Serial.print((int)classic.LecturaX()); Serial.println();
  Serial.print("Boton y: "); Serial.print((int)classic.LecturaY()); Serial.println();
  Serial.println();
  Serial.print("Boton R: "); Serial.print((int)classic.LecturaRB()); Serial.println();
  Serial.print("Potenciómetro R: "); Serial.print((int)classic.readR()); Serial.println();
  Serial.print("Boton ZR: "); Serial.print((int)classic.LecturaZR()); Serial.println();
  Serial.println("-----------------------");
  delay(500);
}

lunes, 13 de junio de 2016

Modulo RTC DS1302

Para emplear este modulo es necesario esta librería: DS1302

Este modulo nos permite trabajar con un reloj de tiempo real, el cual no perderá la hora a menos que la pila se le agote en este caso se perdería toda la configuración y volvería al estado de fabrica, este modulo es muy útil ya que en caso de apagarse el Arduino o de desconectarse no perderá la hora. Lo primero para poder trabajar con el seria ponerle una pila de tipo DL2032, y acto seguido se configurará la hora desde el arduino.

En esta entrada os dejare un ejemplo de como configurar la fecha y la hora del modulo.
Disposición de los pines:

RST-Pin 2
DAT-Pin 3
CLK-Pin 5
VCC-+5
GND-GND

Comencemos con el código:

Lo primero es incluir la librería y declarar los pines en los que conectaremos la rtc:

#include <DS1302.h>

DS1302 rtc(2, 3, 5);//Estos son los pines en los que conectaremos RST, DAT y CLK respectivamente

Una vez declarada la rtc ya podemos configurar la hora desde el void setup(), lo primero es desactivar la protección contra escritura, una vez desprotegido ya podemos comenzar con la configuración:

  void setup():
  {
    rtc.halt(false);
    rtc.writeProtect(false);

    rtc.setDOW(MONDAY);  //Configuramos el día de la semana debéis escribirlo en ingles por la           librería
    rtc.setTime(20, 28, 30);  // Configuramos la hora en formato 24h con minutos y segundos
    rtc.setDate(13, 6, 2016); // Configuramos la fecha en formato día/mes/año
  }

Con esto concluye el programa y ya estaría configurada nuestra rtc, mas adelante subiré un ejemplo de reloj utilizando el Arduino, la pantalla lcd y el modulo DS1302.

Aquí dejo el programa del ejemplo completo: ConfiguraciónRTC

miércoles, 8 de junio de 2016

Pantalla LCD I2C Arduino

En esta entrada comunicaremos una pantalla LCD con un arduino utilizando los pines de I2C, estos pines están situados en las entradas analógicas A4(SDA) y en A5(SCL) y en dos pines independientes situados después del pin de AREF en el lado de los pines digitales.


Lo primero para poder utilizar la pantalla es instalar la librería: LiquidCrystal_I2C

Una vez instalada la librería ya podremos empezar con nuestros proyectos, en el ejemplo que dejare más abajo mostrare las funciones de uso más frecuente cuando trabajamos con la pantalla, para ello en el ejemplo creare una secuencia de 16 números en formato hexadecimal del 0 a la F que irán recorriendo todas las posiciones de la pantalla, en mi caso es de 16x2.

Comencemos con el código:

Lo primero es incluir la librería en nuestro programa al igual que la librería que se encarga de la comunicación I2C:
 
  #include <LiquidCrystal_I2C.h> //Librería de la pantalla
  #include <Wire.h> //Librería de la comunicación I2C

Una vez incluidas las librerías tenemos que declarar el tipo de pantalla que vamos a utilizar, en mi caso, como ya comente antes, mi pantalla es de 16x2:

  LiquidCrystal_I2C lcd (0x27,16,2); //lcd sera el nombre de nuestra pantalla, 16 el número de caracteres por fila y 2 el numero de filas.

Ahora en el void setup() tendremos que iniciarla:

   void setup()
  {
    lcd.begin(); // Inicializa la pantalla
    lcd.clear(); // Limpia la pantalla
    lcd.backlight(); // Enciende la luz de fondo
    lcd.setCursor(2,0); // Posiciona el cursor en el carácter 2 de la fila 0
    lcd.print("Iniciando..."); // Escribe ne la pantalla, este comando es similar al utilizado con la                 función Serial
    delay(500);
  }

Dentro del void loop() creare el bucle que ira escribiendo los números en la pantalla indicando la posición de cada carácter en hexadecimal:

  void loop()
  {
    for(y=0;y<2;y++)
    {
      for(x=0;x<16;x++)
      {
        lcd.clear();
        lcd.setCursor(x,y);
        lcd.print(x,HEX);
        delay(1000);
      }
    }
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Final");
    delay(2000);

  }

Aquí os dejo el link con el código completo: Pantalla_LCD

jueves, 5 de mayo de 2016

Control de un servo con arduino

En esta entrada controlaremos un servo con el arduino.
Primero hablare de los servos:
Un Servo es un dispositivo pequeño que tiene un eje de rendimiento controlado. Este puede ser llevado a posiciones angulares específicas al enviar una señal codificada. Con tal de que una señal codificada exista en la línea de entrada, el servo mantendrá la posición angular del engranaje. Cuando la señala codificada cambia, la posición angular de los piñones cambia. En la práctica, se usan servos para posicionar superficies de control como el movimiento de palancas, pequeños ascensores y timones. Ellos también se usan en radio control, títeres, y por supuesto, en robots.
El Servo que utilizare en esta entrada se posiciona utilizando un potenciómetro para marcar el angulo de giro:



Programa en Arduino



Comencemos con el código:

Lo primero sera incluir la librería Servo.h, esta librería ya esta incluida en el paquete de instalación básico con lo que no es necesaria descargarla. Para incluirla lo haremos en el inicio del programa como con las variables globales:

  #include <Servo.h>

Luego añadimos nuestro servo:

  Servo "nombre de mi servo";

Una vez los incluyamos declararemos todas las variables globales que vallamos a utilizar en nuestro programa:

  int led180 = 10;
  int led0 = 9;
  int estado;
  int poten = 0;
  int analog = 0;

Ahora dentro del void setup() le indicaremos en que pin se encuentra el servo para poder controlarlo y declarare los pines de los leds que utilizare para indicar la posición máxima del servo:

 void setup()
{

  servo.attach(2);// Aquí le indicamos que el servo se encuentra en el pin 2
  pinMode(led180,OUTPUT);
  pinMode(led0,OUTPUT);

}

Para mover el servo utilizare un potenciómetro que leeré desde una entrada analógica, el valor de la entrada lo convertiré en un valor de 0 a 180, ya que el servo que utilizo no puede rotar mas de 180º, para esto utilizare la función map(), para escribir el valor en el servo se utiliza la función "nombre del servo".write("variable o valor"), también existe otra función que nos permite leer la posición actual del servo que seria "nombre del servo".read() pero esta función ya la utilizare en otra entrada:

void loop()
{
  analog = analogRead(poten);
  estado = map(analog,0,1023,0,180);
  servo.write(estado);// Esta es la función que le escribe el valor en el servo, es recomendable hacer una pequeña pausa despues de ella para dejar posicionarse al motor del servo.
  delay(50);
  if(estado == 180)
  {
    digitalWrite(led180,HIGH);
  }
  if(estado == 0)
  {
    digitalWrite(led0,HIGH);
  }
  else
  {
    digitalWrite(led0,LOW);
    digitalWrite(led180,LOW);
  }
}

Ahora os dejo el cableado:
Es importante utilizar una fuente de alimentación externa para no quemar el pin de alimentación del arudino ya que los servos grandes consumen mas de lo que el arduino es capaz de suministrar, si se utiliza una fuente externa es necesario unir los negativos para poder trabajar sino el servo no trabajaría correctamente.


Aquí os dejo el código completo:

#include <Servo.h>
Servo servo;
int led180 = 10;
int led0 = 9;
int estado;
int poten = 0;
int analog = 0;

void setup()
{
  servo.attach(2);
  pinMode(led180,OUTPUT);
  pinMode(led0,OUTPUT);
}

void loop()
{
  analog = analogRead(poten);
  estado = map(analog,0,1023,0,180);
  servo.write(estado);
  delay(50);
  if(estado == 180)
  {
    digitalWrite(led180,HIGH);
  }
  if(estado == 0)
  {
    digitalWrite(led0,HIGH);
  }
  else
  {
    digitalWrite(led0,LOW);
    digitalWrite(led180,LOW);
  }
}

jueves, 28 de abril de 2016

Array de salidas Arduino

En esta entrada utilizare una variable del tipo Array para guardar los pines de las salidas que utilizare, también utilizare la función switch case.
La aplicación de todo esto será un medidor de potencia que nos indicara el valor de la entrada analógica en función del número de leds encendidos siendo uno el mínimo y diez el máximo.


Comencemos por el código:

Primero declararemos la variable array como un array de enteros y añadiremos los valores que contendrá esta cadena:

   int Leds[]={2,3,4,5,6,7,8,9,10,11};

Luego declaramos otras variables de utilidad:

   int estado;
   int Poten = 0;
   int valorPoten = 0;
   int i;

Ahora configuraremos los pines del array Leds como pines de salida dentro del void setup(), para hacerlo de una manera mas rápida y sencilla utilizare un bucle for para configurar cada uno de los pines:

   void setup()
  {
     for(i=0;i<10;i++) // la variable i la iniciamos en 0 ya que la primera posición del array siempre es        // 0 posición que en nuestro caso equivale al valor 2 este bucle se ejecutara 10 veces con lo que el        // ultimo valor de i sera 9 que coincide con la ultima posición  del array
     {
       pinMode(Leds[i],OUTPUT);
     }
  }

Bien una vez configurados los pines como salidas digitales llega la parte de crea nuestro "indicador de potencia" con led, esto lo haremos dentro de una función propia que ejecutaremos dentro del void loop(). Primero escribiré el código dentro del void loop() y luego creare la función que se encargara de encender los led en la secuencia correcta cada vez que la llamemos desde el void loop:

  void loop()
  {
    valorPoten = analogRead(Poten);// guardamos el valor de la entrada analógica dentro de una               variable
    estado = map(valorPoten,0,1023,0,10);//Convertimos el valor de la variable en valores de 0 a 10
    Secuencia();// Llamamos a la función secuencia
  }

Una vez creado el codigo que se ejecutara en bucle creamos la función Secuencia, esta función es la encargada de crear la secuencia de leds, tendrá como característica que sera del tipo void y no recibirá ningún valor de la función principal ya que la variable estado es de carácter global. Dentro de ella habrá un switch case que sera el encargado de encender los leds en función del valor de estado:

  void Secuencia()
  {
    switch(estado)
    {
      case 0:
      digitalWrite(Leds[0],HIGH);
      for(i=1;i<10;i++)
     {
       digitalWrite(Leds[i],LOW);
      }
      delay(50);
      break;
    case 1:
    for(i=0;i<2;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=2;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 2:
    for(i=0;i<3;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=3;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 3:
    for(i=0;i<4;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=4;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 4:
    for(i=0;i<5;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=5;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 5:
    for(i=0;i<6;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=6;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 6:
    for(i=0;i<7;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=7;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 7:
    for(i=0;i<8;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=8;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 8:
    for(i=0;i<9;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=9;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 9:
    for(i=0;i<10;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    delay(50);
    break;
   
  }
}

Aquí abajo os dejo el esquema de cableado y el código completo:
Las resistencias de de 220 Ohm y el potenciómetro es de 10 kOhm.



Código completo:

int Leds[]={2,3,4,5,6,7,8,9,10,11};
int estado;
int Poten = 0;
int valorPoten = 0;
int i;
void setup()
{
  for(i=0;i<10;i++)
  {
    pinMode(Leds[i],OUTPUT);
  }
}

void loop() 
{
  valorPoten = analogRead(Poten);
  estado = map(valorPoten,0,1023,0,10);
  Secuencia();
}
void Secuencia()
{
  switch(estado)
  {
    case 0:
    digitalWrite(Leds[0],HIGH);
    for(i=1;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 1:
    for(i=0;i<2;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=2;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 2:
    for(i=0;i<3;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=3;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 3:
    for(i=0;i<4;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=4;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 4:
    for(i=0;i<5;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=5;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 5:
    for(i=0;i<6;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=6;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 6:
    for(i=0;i<7;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=7;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 7:
    for(i=0;i<8;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=8;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 8:
    for(i=0;i<9;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    for(i=9;i<10;i++)
    {
    digitalWrite(Leds[i],LOW);
    }
    delay(50);
    break;
    case 9:
    for(i=0;i<10;i++)
    {
    digitalWrite(Leds[i],HIGH);
    }
    delay(50);
    break;
    
  }
}