Mostrando entradas con la etiqueta temperatura. Mostrar todas las entradas
Mostrando entradas con la etiqueta temperatura. Mostrar todas las entradas

11/19/2012

Conectar pantalla LCD a Arduino UNO e interactuar con ella, mostrar temperatura



Explicamos en este tutorial cómo conectar una pantalla LCD a Arduino UNO. Mostramos varios ejemplos de código para interacturar con los botones del shield LCD (keypad) de la pantalla LCD para movernos por los menús. Explicamos también cómo cambiar la luminosidad de la pantalla LCD (intensidad de la retroiluminación) desde el menú (con los keypad) y cómo conectar un sensor de temperatura y mostrarla en la pantalla LCD.



Cómo conectar display LCD Keypad Shield a Arduino UNO

En este tutorial explicaremos y mostraremos ejemplos para trabajar con una pantalla LCD (display LCD Keypad Shield) conectada a Arduino. Para ello necesitaremos una pantalla LCD (Display LCD Keypad Shield), en concreto usaremos un Arduino LCD Keypad Shield 16x2 HD44780 con un coste aproximado de 18 euros:
Cómo conectar display LCD Keypad Shield a Arduino UNO
Por supuesto necesitaremos un Arduino UNO, en el siguiente tutorial explicamos cómo adquirirlo y cómo conectarlo al PC para transferir el programa:
Conectaremos el LCD a Arduino como mostramos en la imagen:
Cómo conectar display LCD Keypad Shield a Arduino UNO
En el siguiente tutorial explicamos cómo descargar el software para realizar programas y enviarlos a Arduino, también explicamos cómo conectar Arduino a un PC para el envío de programas:

Programa Arduino para mostrar texto en display LCD y contador que se va incrementando

Una vez conectado el display LCD a Arduino y conectado Arduino al PC por el puerto USB, desde el IDE de desarrollo de Arduino pegaremos el siguiente programa:
/*
 Ejemplo de uso de display LCD 16x2.  Usando la librería LiquidCrystal
 library compatible con el driver de Hitachi HD44780 driver 
*/

// incluimos la libreria LiquidCrystal
#include 

// inicializamos la librería con los numeros pins del interfaz
// cada LCD puede llevar sus propios numeros
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

void setup() {
  // establecemos el numero de columnas y filas del display 
  lcd.begin(16, 2);
  // enviamos el mensaje a mostrar en el display
  lcd.print("www.ajpdsoft.com");
}

void loop() {
  // enviamos la posicion del cursor al display
  // (nota: la linea 1 es la segunda fila, empieza a contar en 0
  lcd.setCursor(0, 1);
  // mostramos el numero de segundos desde el inicio del programa
  lcd.print(millis()/1000);
}
Programa Arduino para mostrar texto en display LCD y contador que se va incrementando
Comprobaremos la sintaxis pulsando en "Verificar":
Programa Arduino para mostrar texto en display LCD y contador que se va incrementando
Si todo es correcto pulsaremos en el botón "Cargar" para enviar el programa a Arduino:
Programa Arduino para mostrar texto en display LCD y contador que se va incrementando
Si todo es correcto el programa quedará transferido a la memoria de Arduino y se iniciará, mostrando el texto indicando en el display LCD (en nuestro caso "www.ajpdsoft.com") y un contador de segundos en la segunda línea:
Programa Arduino para mostrar texto en display LCD y contador que se va incrementando


Programa Arduino para mostrar texto en scroll en display LCD

Un ejemplo de programa Arduino para mostrar un texto en movimiento en un display LCD:
// include the library code:
#include 

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("www.ajpdsoft.com");
  delay(1000);
}

void loop() {
  // scroll 13 positions (string length) to the left 
  // to move it offscreen left:
  for (int positionCounter = 0; positionCounter < 13; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft(); 
    // wait a bit:
    delay(150);
  }

  // scroll 29 positions (string length + display length) to the right
  // to move it offscreen right:
  for (int positionCounter = 0; positionCounter < 29; positionCounter++) {
    // scroll one position right:
    lcd.scrollDisplayRight(); 
    // wait a bit:
    delay(150);
  }
  
    // scroll 16 positions (display length + string length) to the left
    // to move it back to center:
  for (int positionCounter = 0; positionCounter < 16; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft(); 
    // wait a bit:
    delay(150);
  }
  
  // delay at the end of the full loop:
  delay(1000);
}


Programa Arduino para introducir texto en el LDC con las teclas de desplazamiento

Un ejemplo de programa Arduino para mostrar un texto en la primera línea de una pantalla LCD y en la segunda permite que el usuario introduzca un texto usando las teclas de desplazamiento del display LCD:
#include 

LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

int adc_key_val[5] = {50, 200, 400, 600, 800 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
boolean luzEncendida=true;
boolean cursorActivo=false;
unsigned long time;
int x=0;
char caracterActual = 'A';

void setup()
{
  lcd.clear(); 
  lcd.begin(16, 2);
  lcd.setCursor(0,0); 
  lcd.print("www.ajpdsoft.com");
  time = millis();
  //  pinMode(10, OUTPUT);
}

void loop()
{
  if (millis()-time > 10000) {  // Si han pasado mas de 10 segundos apagamos la luz
    pinMode(10, OUTPUT);
    digitalWrite(10, LOW);
    luzEncendida=false;
  }
  if (millis()-time > 5000) {  // Si han pasado mas de 5 segundos apagamos el cursor
    lcd.noBlink();
    cursorActivo=false;
  } 

  adc_key_in = analogRead(0);    // Leemos el valor de la pulsacion
  key = get_key(adc_key_in);    // Obtenemos el boton pulsado

  if (key != oldkey)   // if keypress is detected
  {
    delay(50);  // Espera para evitar los rebotes de las pulsaciones
    adc_key_in = analogRead(0);    // Leemos el valor de la pulsacion
    key = get_key(adc_key_in);    // Obtenemos el boton pulsado
    if (key != oldkey)    
    {
      time = millis();  // TODO: falta la comprobacion de si se ha desbordado el tiempo
      if (!luzEncendida) {  // Al pulsar cualquier tecla encendemos la pantalla
        pinMode(10, INPUT);
        luzEncendida=true;
      } 
      else {  // si la pantalla esta encendida seguimos funcionando normalmente
        lcd.setCursor(x, 1);
        oldkey = key;
        if (key >=0){  // Si se ha pulsado cualquier tecla
          lcd.blink();  // Mostramos el cursor parpadeando
          cursorActivo=true;
        }
        if (key == 0){  // Se ha pulsado la tecla derecha
          x++;
          if (x>15) x=15;
          caracterActual='A';
        }
        if (key == 1) {  // Se ha pulsado la tecla arriba
          caracterActual++;
          if (caracterActual > 'Z') caracterActual='Z';
          lcd.write(caracterActual);
        }
        if (key == 2) {  // Se ha pulsado la tecla abajo
          caracterActual--;
          if (caracterActual < 'A') caracterActual='A';
          lcd.write(caracterActual);
        }
        if (key == 3) {  // Se ha pulsado la tecla izquierda
          x--;
          if (x<0) x=0;
          caracterActual='A';
        }
        if (key == 4){  // Se ha pulsado la tecla de seleccion
        }
        lcd.setCursor(x, 1);
      }
    }
  }
  delay(100);
}

// Convertimos el valor leido en analogico en un numero de boton pulsado
int get_key(unsigned int input)
{
  int k;

  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }

  if (k >= NUM_KEYS)k = -1;  // Error en la lectura
  return k;
}



Programa Arduino para mostrar menús y submenús en display LCD

Un ejemplo de programa Arduino para mostrar un menú y sus submenús correspondientes en una pantalla LCD:
#include 

LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

const int numeroDeMenus=5;
const int numeroMaximoDeSubmenus=4;

char tituloMenu[numeroDeMenus][16] = {
  "1  Menu 1    ",
  "2  Menu 2    ",               
  "3  Menu 3    ",
  "4  Menu 4    ",
  "5  Menu 5    " };
  
byte numeroDeSubmenus[numeroDeMenus] = {4,3,2,1,4};

char tituloSubmenu[numeroDeMenus][numeroMaximoDeSubmenus][16] = 
{
  "1.1 Submenu 1","1.2 Submenu 2","1.3 Submenu 3","1.4 Submenu 4",
  "2.1 Submenu 1","2.2 Submenu 2","2.3 Submenu 3","",
  "3.1 Submenu 1","3.2 Submenu 2","","",
  "4.1 Submenu 1","","","",
  "5.1 Submenu 1","5.2 Submenu 2","5.3 Submenu 3","5.4 Submenu 4"};

int adc_key_val[5] ={
  50, 200, 400, 600, 800 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
boolean luzEncendida=true;
boolean cursorActivo=false;
unsigned long time;
int x=0;
int y=0;

void setup()
{
  lcd.clear(); 
  lcd.begin(16, 2);
  lcd.setCursor(0,0); 
  lcd.print("www.ajpdsoft.com");
  lcd.setCursor(0,1); 
  lcd.print("Menu version 0.1");
  delay(5000);
  lcd.setCursor(0,0); 
  lcd.print("Muevase con las ");
  lcd.setCursor(0,1); 
  lcd.print("teclas direccion");
  delay(4000);
  lcd.clear();
  lcd.setCursor(0,0); 
  lcd.print("Menu principal");
  lcd.setCursor(0,1); 
  lcd.print(tituloMenu[x]);
  time = millis();
  //  pinMode(10, OUTPUT);
}

void loop()
{
  // Si han pasado mas de 10 segundos apagamos la luz
  if (millis()-time > 10000) {
    pinMode(10, OUTPUT);
    digitalWrite(10, LOW);
    luzEncendida=false;
  }
  // Si han pasado mas de 5 segundos apagamos el cursor
  if (millis()-time > 5000) {
    lcd.noBlink();
    cursorActivo=false;
  } 

  adc_key_in = analogRead(0);    // Leemos el valor de la pulsacion
  key = get_key(adc_key_in);    // Obtenemos el boton pulsado

  if (key != oldkey)   // if keypress is detected
  
    delay(50);  // Espera para evitar los rebotes de las pulsaciones
    adc_key_in = analogRead(0);    // Leemos el valor de la pulsacion
    key = get_key(adc_key_in);    // Obtenemos el boton pulsado
    if (key != oldkey)    
    {
      // TODO: falta la comprobacion de si se ha desbordado el tiempo
      time = millis();  
      if (!luzEncendida) {  // Al pulsar cualquier tecla encendemos la pantalla
        pinMode(10, INPUT);
        luzEncendida=true;
      } 
      else {  // si la pantalla esta encendida seguimos funcionando normalmente
        oldkey = key;
        if (key >=0){  // Si se ha pulsado cualquier tecla
          lcd.blink();  // Mostramos el cursor parpadeando
          cursorActivo=true;
        }
        if (key == 0){  // Se ha pulsado la tecla derecha
          x++;
          if (x>numeroDeMenus-1) x=numeroDeMenus-1;
          y=0;
        }
        if (key == 1) {  // Se ha pulsado la tecla arriba
          y++;
          if (y > numeroDeSubmenus[x]-1) y=numeroDeSubmenus[x]-1;
        }
        if (key == 2) {  // Se ha pulsado la tecla abajo
          y--;
          if (y < 0) y=0;
        }
        if (key == 3) {  // Se ha pulsado la tecla izquierda
          x--;
          if (x<0) x=0;
          y=0;
        }
        if (key == 4){  // Se ha pulsado la tecla de seleccion
        }
        lcd.clear();
        lcd.setCursor(0,0); 
        lcd.print(tituloMenu[x]);
        lcd.setCursor(0,1); 
        lcd.print(tituloSubmenu[x][y]);
      }
    }
  }
  delay(50);
}

// Convertimos el valor leido en analogico en un numero de boton pulsado
int get_key(unsigned int input)
{
  int k;

  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }

  if (k >= NUM_KEYS)k = -1;  // Error en la lectura
  return k;
}

Programa Arduino para mostrar temperatura, opciones modificables, luminosidad en display LCD

Un ejemplo de programa Arduino para mostrar la temperatura de un habitáculo usando un sensor de temperatura (NTC o resistencia variable con la temperatura de coeficiente negativo) en una pantalla LCD Keypad Shield. El programa también permite modificar la luminosidad (intensidad de la retroiluminación) del display LCD, cambiar parámetros, guardar valores en memoria EEPROM, etc.
Para conectar el sensor de temperatura (NTC o resistencia variable con la temperatura de coeficiente negativo) se pueden seguir las intrucciones del siguiente tutorial:
Con la diferencia de que hemos conectado el sensor de temperatura a la entrada analógica 1 porque la 0 la usa el LCD.
El código del programa completo Arduino:

#include 
#include 
#define ThermistorPIN 1  // Analog Pin 1
#define NUM_KEYS 5

/*
  Circuito del dispaly LCD:
 * LCD RS pin to digital pin 8
 * LCD Enable pin to digital pin 9
 * LCD D4 pin to digital pin 4
 * LCD D5 pin to digital pin 5
 * LCD D6 pin to digital pin 6
 * LCD D7 pin to digital pin 7
 * LCD BL pin to digital pin 10
 * KEY pin to analogl pin 0
 *
 * Esquema del sensor de temperatura:
 *   [Ground] -- [10k-pad-resistor] -- | -- [10k thermistor] --[Vcc (5v)]
 *                                     |
 *                                Analog Pin 1
 */


LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

const int numeroDeMenus=6;

char tituloMenu[numeroDeMenus][16] = {
  "Fijar Temp.: ",
  "Fijar Tiempo:",               
  "Kp:          ",
  "Kd:          ",
  "Ki:          ",
  "Intensidad:  " };

int adc_key_val[5] ={
  50, 200, 400, 600, 800 };
int adc_key_in;
int key=-1;
int oldkey=-1;
boolean luzEncendida=true;
boolean cursorActivo=false;
boolean enMenu=false;
unsigned long time;
unsigned long tiempoPID;
byte numeroLecturas=0;
int x=0;
int signo=0;
char temp[10];
int lecturas[100];
byte numeroLectura=0;
//int lectura=0;
int maximo, minimo, diferencia, t1, t2, t3;
byte consigna=25;
byte tiempo=1;
byte kp=1;
byte kd=1;
byte ki=1;
byte intensidad=10;


void setup()
{
  cargarConfig();
  pinMode(10, OUTPUT);
  analogWrite(10,intensidad*25);
  Serial.begin(9600); 
  lcd.clear(); 
  lcd.begin(16, 2);
  lcd.setCursor(0,0); 
  lcd.print("www.ajpdsoft.com");
  lcd.setCursor(0,1); 
  lcd.print("C.Ventanas v1.0 ");
  delay(2000);
  //  lcd.setCursor(0,0); 
  //  lcd.print("Muevase con las ");
  //  lcd.setCursor(0,1); 
  //  lcd.print("teclas direccion");
  //  delay(4000);
  lcd.clear();
  lcd.setCursor(0,0); 
  lcd.print("Temperatura:    ");
  lcd.setCursor(0,1);
  int lectura=getTemp(1);
  sprintf(temp, "%3d%c%1d%cC", lectura/100, '.', lectura/10%10,223);
  lcd.print(temp);
  time = millis();
  tiempoPID = millis();
}

void loop()
{
  int lectura = getTemp(ThermistorPIN);
  lecturas[numeroLectura++] = lectura;
  if (millis()-time > 20000) {  // Si han pasado mas de 20 segundos apagamos la luz
    digitalWrite(10, LOW);
    luzEncendida=false;
  }
  if (millis()-time > 7000) {  // Si han pasado mas de 7 segundos salimos del menu
    if (enMenu) guardarConfig();
    enMenu = false;
    x=0;
    time = millis();
    //  }
    //  if (!enMenu) {
    lcd.clear();
    lcd.setCursor(0,0); 
    lcd.print("Temperatura:    ");
    lcd.setCursor(0,1);
    sprintf(temp, "%3d%c%1d%cC", lectura/100, '.', lectura/10%10,223);
    lcd.print(temp);
    //    Serial.print("Temperatura[");
    //    Serial.print(numeroLectura);
    //    Serial.print("]: "); 
    //    Serial.println(temp); 
  }
  if (millis()-time > 5000) {  // Si han pasado mas de 5 segundos apagamos el cursor
    lcd.noBlink();
    cursorActivo=false;
  } 

  adc_key_in = analogRead(0);    // Leemos el valor de la pulsacion
  key = get_key(adc_key_in);    // Obtenemos el boton pulsado

  if (key != oldkey)   // if keypress is detected
  {
    delay(50);  // Espera para evitar los rebotes de las pulsaciones
    adc_key_in = analogRead(0);    // Leemos el valor de la pulsacion
    key = get_key(adc_key_in);    // Obtenemos el boton pulsado
    if (key != oldkey)    
    {
      time = millis();  // TODO: falta la comprobacion de si se ha desbordado el tiempo
      if (!luzEncendida) {  // Al pulsar cualquier tecla encendemos la pantalla
        analogWrite(10,intensidad*25);
        luzEncendida=true;
      } 
      else {  // si la pantalla esta encendida seguimos funcionando normalmente
        oldkey = key;
        char accion = 0;
        if (key >=0){  // Si se ha pulsado cualquier tecla
          lcd.blink();  // Mostramos el cursor parpadeando
          cursorActivo=true;
        }
        if ((key == 0) && (enMenu)){  // Se ha pulsado la tecla derecha
          x++;
          if (x>numeroDeMenus-1) x=numeroDeMenus-1;
        }
        if ((key == 1) && (enMenu)) {  // Se ha pulsado la tecla arriba
          accion++;
        }
        if ((key == 2) && (enMenu)) {  // Se ha pulsado la tecla abajo
          accion = accion-1;
        }
        if ((key == 3) && (enMenu)) {  // Se ha pulsado la tecla izquierda
          x--;
          if (x<0) x = 0;
        }
        if (key == 4){  // Se ha pulsado la tecla de seleccion
        }
        enMenu = true;
        lcd.clear();
        lcd.setCursor(0,0); 
        lcd.print(tituloMenu[x]);
        lcd.setCursor(0,1); 
        switch (x) {
        case 0: // Estamos en fijar temperatura
          consigna += accion;
          lcd.print(consigna);
          lcd.print((char)223);
          lcd.print("C");
          break;
        case 1:  // Estamos en fijar tiempo
          tiempo += accion;
          lcd.print(tiempo);
          lcd.print("0 seg.");
          break;
        case 2:  // Estamos en Kp.
          kp += accion;
          lcd.print(kp);
          break;
        case 3:  // Estamos en Kd.
          kd += accion;
          lcd.print(kd);
          break;
        case 4:  // Estamos en Ki.
          ki += accion;
          lcd.print(ki);
          break;
        case 5:  // Estamos en Ki.
          intensidad += accion;
          if (intensidad > 254) intensidad = 0;
          if (intensidad > 10) intensidad = 10;
          lcd.print(intensidad);
          lcd.print("0%");
          analogWrite(10,intensidad*25);
          break;
        } 
      }
    }
  }
  if ((numeroLectura > 99) && (numeroLecturas < 2)) {
    long suma = 0;
    maximo = -10000;
    minimo = 10000;
    for (int i=0; i < 100; i++){
      suma = suma + lecturas[i];
      if (lecturas[i] > maximo) {
        maximo = lecturas[i];
      }
      if (lecturas[i] < minimo) {
        minimo = lecturas[i];
      }

      //      Serial.print("Temperatura[");
      //      Serial.print(i);
      //      Serial.print("]: "); 
      //      Serial.println(lecturas[i]); 
    }
    diferencia = maximo - minimo;
    suma = suma / 100;
    // Si la diferencia es superior a un grado 
    //es que ha habido un error en la lectura
    if (diferencia > 100) {  
      Serial.println("Lectura no valida");
      // TODO: Descartar lectura y repetir la medida
    } 
    else {
      numeroLecturas++;
      t3=t2;
      t2=t1;
      t1=suma;
    }
    Serial.print("Suma: "); 
    Serial.println(suma); 
/*    Serial.print("Media: "); 
    Serial.print(suma/100); 
    Serial.print(","); 
    Serial.println(suma/10%10); 
    Serial.print("Maximo: "); 
    Serial.print(maximo/100); 
    Serial.print(","); 
    Serial.print(maximo/10%10); 
    Serial.print(" - Minimo: "); 
    Serial.print(minimo/100); 
    Serial.print(","); 
    Serial.print(minimo/10%10); 
    Serial.print(" - Diferencia: "); 
    Serial.print(diferencia/100); 
    Serial.print(","); 
    Serial.println(diferencia/10%10); */
  }
  if (numeroLectura > 99) {
    // Cuando se termina de tomar las 100 
    //lecturas empezamos de nuevo por la primera
    numeroLectura = 0;
  }
  PID();
  delay(10);
  // Si se desborda millis() empieza otra 
  //vez por cero, ocurre cada 50 dias
  if (millis() < time){   
    time = millis();
  }
}

void PID(){
  // Si se desborda millis() empieza otra 
  // vez por cero, ocurre cada 50 dias
  if (millis() < tiempoPID){   
    tiempoPID = millis();
  }
  // Si no ha pasado todavía el timepo de ciclo del PID
  if (millis() < tiempoPID + (tiempo*10*1000)){  
    // entonces mantenemos la fuerza y esperamos mas tiempo
    // s = sActualPID;  
  } 
  else if (numeroLecturas >= 2){
    numeroLecturas--;
    Serial.print("Distancia a la consigna: ");
    Serial.print(t1-consigna*100);
    Serial.print(" - Velocidad: ");
    Serial.println(t1-t2);
    tiempoPID = millis();
  }

}

// Convertimos el valor leido en analogico 
// en un numero de boton pulsado
int get_key(unsigned int input)
{
  int k;

  for (k = 0; k < NUM_KEYS; k++)
  {
    if (input < adc_key_val[k])
    {
      return k;
    }
  }

  if (k >= NUM_KEYS)k = -1;  // Error en la lectura.
  return k;
}

int temperaturaFicticia = 2450;
int ptf= 0;
int getTemp(byte input)
{
  int  celsius = Thermistor(analogRead(input))*100; 
  return celsius;
  temperaturaFicticia += (random(7)-3-ptf);
  if (temperaturaFicticia > 2800) ptf = 1;
  if (temperaturaFicticia < 2000) ptf = 0;
  return temperaturaFicticia;
}

float pad = 10000;  // balance/pad resistor value, set this to
                   // the measured resistance of your pad resistor
// float thermr = 10000; // thermistor nominal resistance

float Thermistor(int RawADC) {
  long Resistance;  
  float Temp;  // Dual-Purpose variable to save space.

  Resistance=((1024 * pad / RawADC) - pad); 
  // Saving the Log(resistance) so not to calculate  it 4 times later
  Temp = log(Resistance); 
  Temp = 1 / (0.001129148 + (0.000234125 * Temp) + 
         (0.0000000876741 * Temp * Temp * Temp));
  Temp = Temp - 273.15;  // Convert Kelvin to Celsius                      

  return Temp;    // Devolver temperatura
}

boolean cargarConfig(){
  if ((EEPROM.read(0) == 27) && (EEPROM.read(1) == 28) && 
     (EEPROM.read(2) == 13) && (EEPROM.read(3) == 18)) {
    // Comprobamos que la eeprom tenga una 
    // configuracion valida con numeros concretos
    // solo cargamos el valor de la configuracion si los valores coinciden
    if (EEPROM.read(4) == EEPROM.read(5)) consigna = EEPROM.read(4);  
    if (EEPROM.read(6) == EEPROM.read(7)) tiempo = EEPROM.read(6);
    if (EEPROM.read(8) == EEPROM.read(9)) kp = EEPROM.read(8);
    if (EEPROM.read(10) == EEPROM.read(11)) kd = EEPROM.read(10);
    if (EEPROM.read(12) == EEPROM.read(13)) ki = EEPROM.read(12);
    if (EEPROM.read(14) == EEPROM.read(15)) intensidad = EEPROM.read(14);
    return true;
  }
  return false;
}

void guardarConfig(){
  EEPROM.write(0,27);
  EEPROM.write(1,28);
  EEPROM.write(2,13);
  EEPROM.write(3,18);
  // Ponemos nmeros concretos en el comienzo 
  // de la EEPROM para confirmar que tiene valores correctos.
  EEPROM.write(4,consigna);
  EEPROM.write(5,consigna);  // almacenamos los valores 2 veces
  EEPROM.write(6,tiempo);
  EEPROM.write(7,tiempo);  // almacenamos los valores 2 veces
  EEPROM.write(8,kp);
  EEPROM.write(9,kp);  // almacenamos los valores 2 veces
  EEPROM.write(10,kd);
  EEPROM.write(11,kd);  // almacenamos los valores 2 veces
  EEPROM.write(12,ki);
  EEPROM.write(13,ki);  // almacenamos los valores 2 veces
  EEPROM.write(14,intensidad);
  EEPROM.write(15,intensidad);  // almacenamos los valores 2 veces
}


Artículos relacionados


Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del Proyecto AjpdSoft, con la inestimable colaboración de Antonio RN de RS.

10/16/2011

Obtener temperatura con sensor SEN118A2B de cabeza de acero y Arduino



Explicamos cómo obtener la temperatura con un sensor SEN118A2B de cabeza de acero y con la placa Arduino UNO. Indicamos todos los requisitos hardware (Arduino, sensor, resistencia, ...) y el programa necesario para mostrar los grados Celsius (centígrados), Kelvin y Fahrenheit.



Requisitos para proyecto hardware con Arduino y sensor de temperatura SEN118A2B

Para realizar un proyecto hardware para obtener la temperatura usando Arduino UNO y un sensor Temperature sensor with steel head SEN118A2B necesitaremos los siguientes componentes:
  • Arduino UNO:
Requisitos para proyecto hardware con Arduino y sensor de temperatura SEN118A2B
  • Sensor de temperatura, en nuestro caso usaremos un Temperature sensor with steel head SEN118A2B:
Requisitos para proyecto hardware con Arduino y sensor de temperatura SEN118A2B
  • Resistencia de 10K:
Requisitos para proyecto hardware con Arduino y sensor de temperatura SEN118A2B
  • Cable para conectar sensor con resistencia y GND, en nuestro caso, usaremos un cable normal con las dos puntas "peladas":
Requisitos para proyecto hardware con Arduino y sensor de temperatura SEN118A2B
En el siguiente artículo explicamos cómo conectar Arduino a un PC, cómo compilar un programa y cómo enviarlo al Arduino. Explicamos también cómo instalar el IDE de desarrollo de Arduino:


Conexión de sensor de temperatura con Arduino UNO

Conectaremos el sensor de temperatura a la placa Arduino UNO, este sensor tiene dos hilos, uno de ellos irá directamente conectado al pin 5V de Ardunio (alimentación) y el otro irá conectado al pin analógico A0 y a una resistencia de 10K y la resistencia irá conectada a masa (al ping GND de Arduino). Mostramos el esquema a continuación:
Conexión de sensor de temperatura con Arduino UNO
Mostramos los dos hilos del sensor conectados al pin A0 y al 5V (es indiferente el hilo del sensor a conectar a cada pin). Como veremos en la imagen hemos conectado la resistencia de 10K directamente al mismo pin que el hilo del A0 analógico y el otro extremo de la resistencia conectado con un cable al GND del Arduino:
Conexión de sensor de temperatura con Arduino UNO
Lo ideal es usar una placa prototipo, así sería más cómoda la conexión, en nuestro caso no la hemos usado, por ello hemos conectado directamente la resistencia al mismo pin que el hilo del sensor A0.
En esta imagen mostramos los cables conectados desde otra posición, para que se aprecien mejor:
Conexión de sensor de temperatura con Arduino UNO
Mostramos ahora todo el hardware conectado (Arduino UNO, sensor temperatura, resistencia) y conectado al PC mediante el cable USB:
Conexión de sensor de temperatura con Arduino UNO
Obviamente esta conexión la hemos realizado para hacer pruebas y comprobar que el sensor funciona adecuadamente. Si vamos a comercializar el sistema hardware o queremos usarlo definitivamente debemos colocarlo en una caja adaptada para que quepa la placa y los sensores y soldarlos adecuadamente.

Enviar programa a Arduino para obtener y mostrar la temperatura por el puerto serie

Tras conectar el sensor a Arduino y conectar Arduino al PC, abriremos el IDE de desarrollo de Arduino y escribiremos el siguiente programa:
/*
 * Inputs ADC Value from Thermistor and outputs Temperature in Celsius
 *  requires: include 
 * Utilizes the Steinhart-Hart Thermistor Equation:
 *    Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]3}
 *    where A = 0.001129148, B = 0.000234125 and C = 8.76741E-08
 *
 * These coefficients seem to work fairly universally, which is a bit of a 
 * surprise. 
 *
 * Schematic:
 *   [Ground] -- [10k-pad-resistor] -- | -- [thermistor] --[Vcc (5v)]
 *                                     |
 *                                Analog Pin 0
 *
 * In case it isn't obvious (as it wasn't to me 
 * until I thought about it), the analog ports
 * measure the voltage between 0v -> Vcc which for 
 * an Arduino is a nominal 5v, but for (say) 
 * a JeeNode, is a nominal 3.3v.
 *
 * The resistance calculation uses the ratio of the 
 * two resistors, so the voltage
 * specified above is really only required for 
 * the debugging that is commented out below
 *
 * Resistance = (1024 * PadResistance/ADC) - PadResistor 
 */

#include 

#define ThermistorPIN 0  // Analog Pin 0

float vcc = 4.91;  // only used for display purposes, if used
                   // set to the measured Vcc.
float pad = 9850;  // balance/pad resistor value, set this to
                   // the measured resistance of your pad resistor
float thermr = 10000; // thermistor nominal resistance

float Thermistor(int RawADC) {
  long Resistance;  
  float Temp;  // Dual-Purpose variable to save space.

  Resistance=((1024 * pad / RawADC) - pad); 
  // Saving the Log(resistance) so not to calculate  it 4 times later
  Temp = log(Resistance); 
  Temp = 1 / (0.001129148 + (0.000234125 * Temp) + 
         (0.0000000876741 * Temp * Temp * Temp));
  Temp = Temp - 273.15;  // Convert Kelvin to Celsius                      

  return Temp;    // Devolver temperatura
}

void setup() {
  Serial.begin(9200);
}

void loop() {
  float temp;
  float celsius;
  
  // read ADC and  convert it to Celsius
  celsius = Thermistor(analogRead(ThermistorPIN)); 
  Serial.print("Celsius: "); 
  Serial.print(celsius,1);  // display Celsius

  temp = celsius + 273.15;  // converts to  Kelvin
  Serial.print(", Kelvin: "); 
  Serial.print(temp,1);   // display  Kelvin

  temp = (celsius * 9.0)/ 5.0 + 32.0;  // converts to  Fahrenheit
  Serial.print(", Fahrenheit: "); 
  Serial.print(temp,1);     // display  Fahrenheit
  Serial.println("");                                   
  delay(3000);              // Delay a bit... 
}
Tras escribir el programa, pulsaremos en el botón "Verify" para compilarlo y verificar que la sintaxis es correcta:
Enviar programa a Arduino para obtener y mostrar la temperatura por el puerto serie
Ahora enviaremos el programa a la memoria Flash de Arduino para testearlo, para ello pulsaremos en el botón "Upload":
Enviar programa a Arduino para obtener y mostrar la temperatura por el puerto serie
Si todo es correcto, el programa ya estará ejecutándose en Arduino UNO, se ejecutará cada tres segundos y enviará por el puerto serie los valores de temperatura obtenidos. Para ver los valores devueltos (pues así lo hemos programado) pulsaremos en el botón "Serial Monitor":
Enviar programa a Arduino para obtener y mostrar la temperatura por el puerto serie
Si hemos realizado correctamente la conexión del sensor de temperatura a Arduino y si lo hemos programado correctamente, nos devolverá los valores de temperatura actuales en grados Celsius (centígrados), Kelvin y Fahrenheit:
Enviar programa a Arduino para obtener y mostrar la temperatura por el puerto serie
Obviamente, este código nos sirve para verificar el correcto funcionamiento de nuestra placa Arduino y del sensor de temperatura. Para realizar alguna aplicación profesional y comercializarla deberemos, por ejemplo, guardar los valores de temperatura en la memoria EEPROM para, posteriormente, poder ser consultados. En el siguiente artículo explicamos cómo escribir en la memoria EEPROM de Arduino:
En este otro artículo explicamos cómo escribir valores de temperatura y humedad en la memoria EEPROM:
Nuestro proyecto hardware para comercialización debería incluir opciones más profesionales, por ejemplo añadiendo un módulo GPRS para permitir a Arduino enviar los datos obtenidos vía web de forma automática, también para avisar por SMS en caso de que se produzcan determinados eventos, por ejemplo si la temperatura sube o baja de unos determinados valores.

Artículos relacionados


Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del Proyecto AjpdSoft.

10/13/2011

Obtener temperatura y humedad con Arduino



Explicamos en este proyecto hardware cómo conectar un sensor de temperatura y humedad a Arduino UNO. Indicamos cómo visualizar los valores en el propio IDE de desarrollo de Arduino (usando la ventana de Serial Monitor). Mostramos también cómo guardar los valores obtenidos en la memoria EEPROM de Arduino.



Requisitos para proyecto hardware con Arduino y sensor de temperatura y humedad

Para realizar un proyecto hardware para obtener la temperatura y humedad usando Arduino UNO necesitaremos los siguientes componentes:
  • Arduino UNO:
Requisitos para proyecto hardware con Arduino y sensor de temperatura y humedad
  • Sensor de temperatura y humedad, en nuestro caso usaremos un Twig Temp&Humi Sensor SEN11301P.
Requisitos para proyecto hardware con Arduino y sensor de temperatura y humedad
  • Cable para conectar sensor con Arduino, en nuestro caso, este cable lo hemos obtenido de un clabe del audio de un lector de CD. El sensor de temperatura y humedad requiere de un cable de cuatro hilos: GND, VCC, NC y SIG. Aunque el hilo del NC no se usa:
Requisitos para proyecto hardware con Arduino y sensor de temperatura y humedad
En el siguiente artículo explicamos cómo conectar Arduino a un PC, cómo compilar un programa y cómo enviarlo al Arduino. Explicamos también cómo instalar el IDE de desarrollo de Arduino:


Conexión de sensor de temperatura y humedad con Arduino UNO

Para realizar la conexión del sensor de temperatura y humedad con el Arduino UNO, en primer lugar insertaremos el conector hembra del cable al zócalo a tal efecto del sensor, como mostramos en la siguiente imagen:
Conexión de sensor de temperatura y humedad con Arduino UNO
En la parte del sensor de temperatura, para conectarlo al Arduino, en nuestro caso hemos usado un cable que contiene tres hilos: uno rojo que va al SIG (datos), otro blanco que va al VCC (alimentación) y otro negro que va al GND (masa). El conector NC no se usa por lo que no necesita cable. Es importante tener bien identificado cada hilo para conectarlo en su pin correspondiente del Arduino:
Conexión de sensor de temperatura y humedad con Arduino UNO
En la parte del Arduino UNO conectaremos el cable rojo (SIG) al pin A0 analógico, como se muestra en la imagen:
Conexión de sensor de temperatura y humedad con Arduino UNO
El cable blanco (VCC) lo conectaremos al ping 5V, el de alimentación, como se muestra en la imagen:
Conexión de sensor de temperatura y humedad con Arduino UNO
Y el cable negro (GND) lo conectaremos a cualquier de los pines GND del Arduino (en la imagen el cable del medio, que en su origen era negro y en este extremo está "pelado"):
Conexión de sensor de temperatura y humedad con Arduino UNO
El sensor de temperatura y humedad conectado al Arduino UNO quedará como mostramos en la imagen:
Conexión de sensor de temperatura y humedad con Arduino UNO
Por supuesto, podríamos haber usado un cable específico y una placa prototipo para realizar la conexión del sensor con Arduino, aunque para el ejemplo que nos ocupa no es necesario.

Enviar programa para obtener temperatura y humedad a Arduino y testear resultado

Una vez conectado el sensor de temperatura y humedad a Arduino UNO, el siguiente paso será realizar un programa que obtenga los valores de temperatura y humedad y los muestre por el puerto serie, de esta forma podremos testear y verificar que el hardware (sensor y Arduino) funcionan correctamente.
Instalaremos los drivers necesarios, instalaremos el IDE de desarrollo de Arduino y conectaremos Arduino al PC por el puerto USB, como indicamos aquí:
A continuación escribiremos el siguiente programa:
#define DHT11_PIN 0      // ADC0

byte read_dht11_dat()
{
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++)
  {
    while(!(PINC & _BV(DHT11_PIN)));  // wait for 50us
    delayMicroseconds(30);

    if(PINC & _BV(DHT11_PIN)) 
      result |=(1<<(7-i));
    while((PINC & _BV(DHT11_PIN)));  // wait '1' finish
  }
  return result;
}

void setup()
{
  DDRC |= _BV(DHT11_PIN);
  PORTC |= _BV(DHT11_PIN);

  Serial.begin(9600);
  Serial.println("Ready");
}

void loop()
{
  byte dht11_dat[5];
  byte dht11_in;
  byte i;
  // start condition
  // 1. pull-down i/o pin from 18ms
  PORTC &= ~_BV(DHT11_PIN);
  delay(18);
  PORTC |= _BV(DHT11_PIN);
  delayMicroseconds(40);

  DDRC &= ~_BV(DHT11_PIN);
  delayMicroseconds(40);

  dht11_in = PINC & _BV(DHT11_PIN);

  if(dht11_in)
  {
    Serial.println("dht11 start condition 1 not met");
    return;
  }
  delayMicroseconds(80);

  dht11_in = PINC & _BV(DHT11_PIN);

  if(!dht11_in)
  {
    Serial.println("dht11 start condition 2 not met");
    return;
  }
  delayMicroseconds(80);
  // now ready for data reception
  for (i=0; i<5; i++)
    dht11_dat[i] = read_dht11_dat();

  DDRC |= _BV(DHT11_PIN);
  PORTC |= _BV(DHT11_PIN);

  byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
  // check check_sum
  if(dht11_dat[4]!= dht11_check_sum)
  {
    Serial.println("DHT11 checksum error");
  }

  Serial.print("Humedad = ");
  Serial.print(dht11_dat[0], DEC);
  Serial.print(".");
  Serial.print(dht11_dat[1], DEC);
  Serial.print("%  ");
  Serial.print("Temperatura = ");
  Serial.print(dht11_dat[2], DEC);
  Serial.print(".");
  Serial.print(dht11_dat[3], DEC);
  Serial.println("C  ");

  delay(2000);
}
Lo compilaremos para verificar que la sintaxis del código C++ es correcta, para ello pulsaremos el botón "Verify". Si el código es correcto devolverá "Done compiling", si hay algún error en el código lo indicará:
Enviar programa para obtener temperatura y humedad a Arduino y testear resultado
Una vez verificado el código pulsaremos en el botón "Upload" para enviar el programa a Arduino UNO. Si Arduino está correctamente conectado al PC por el puerto USB, el programa será subido y el IDE de Arduino mostrará "Done uploading"
Enviar programa para obtener temperatura y humedad a Arduino y testear resultado
Para testear el programa que hemos enviado a Arduino, abriremos la ventana de Serial Monitor del IDE de Arduino, pulsando en el botón "Serial Monitor":
Enviar programa para obtener temperatura y humedad a Arduino y testear resultado
Si tenemos correctamente conectado el sensor de temperatura y humedad a Arduino y si el programa enviado es correcto, nos devolverá la humedad y temperatura actuales a la ventana de puerto serie:
Enviar programa para obtener temperatura y humedad a Arduino y testear resultado
 

Guardar resultados de temperatura y humedad en EPROM de Arduino

En Arduino el EEPROM es un espacio de memoria que puede ser utilizada por los programadores para almacenar información a largo plazo. Esta memoria es no volátil, por lo tanto aunque dejemos de alimentar eléctricamente Arduino los valores de esta memoria seguirán estando almacenados. En el siguiente artículo mostramos más información sobre el tipo de memorias del chip de Arduino y sobre para qué sirven y cómo usarlas:
Modificaremos el programa anterior que obtiene la temperatura y humedad usando el sensor Twig Temp&Humi Sensor SEN11301P para guardar los valores obtenidos en la memoria EEPROM interna de Arduino UNO (con capacidad para 1024 valores):
#define DHT11_PIN 0      // ADC0

//Para EEPROM
#include  
int addr = 0;

int repeticiones = 0;

byte read_dht11_dat()
{
  byte i = 0;
  byte result=0;
  for(i=0; i< 8; i++)
  {
    while(!(PINC & _BV(DHT11_PIN)));  // wait for 50us
    delayMicroseconds(30);

    if(PINC & _BV(DHT11_PIN)) 
      result |=(1<<(7-i));
    while((PINC & _BV(DHT11_PIN)));  // wait '1' finish
  }
  return result;
}

void setup()
{
  //para encender el LED de Arduino
  pinMode(13, OUTPUT);
  
  //para el sensor de temperatura y humedad
  DDRC |= _BV(DHT11_PIN);
  PORTC |= _BV(DHT11_PIN);

  //para iniciar el puerto serie, para las comunicaciones
  Serial.begin(9600);
  Serial.println("Iniciando lectura de datos...");
}

void loop()
{
  byte dht11_dat[5];
  byte dht11_in;
  byte i;
  int val = analogRead(0) / 4; //para EEPROM
  
  // start condition
  // 1. pull-down i/o pin from 18ms
  PORTC &= ~_BV(DHT11_PIN);
  delay(18);
  PORTC |= _BV(DHT11_PIN);
  delayMicroseconds(40);

  DDRC &= ~_BV(DHT11_PIN);
  delayMicroseconds(40);

  dht11_in = PINC & _BV(DHT11_PIN);

  if(dht11_in)
  {
    Serial.println("dht11 start condition 1 not met");
    return;
  }
  delayMicroseconds(80);

  dht11_in = PINC & _BV(DHT11_PIN);

  if(!dht11_in)
  {
    Serial.println("dht11 start condition 2 not met");
    return;
  }
  delayMicroseconds(80);
  // now ready for data reception
  for (i=0; i<5; i++)
    dht11_dat[i] = read_dht11_dat();

  DDRC |= _BV(DHT11_PIN);
  PORTC |= _BV(DHT11_PIN);

  byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
  // check check_sum
  if(dht11_dat[4]!= dht11_check_sum)
  {
    Serial.println("DHT11 checksum error");
  }

  //guardaremos los valores de humedad y temperatura
  //cada 10 minutos aproximadamente
  //Si tenemos 1024 valores y usamos dos por cada captura
  //uno para la humedad y otro para la temperatura
  //tendremos espacio en memoria EEPROM para dos días aproximadamente
  repeticiones = repeticiones + 1;
    
  if (repeticiones == 10)
  {
    //guardar valores en EEPROM
    Serial.print("Guardando valores en EEPROM");
    Serial.println(" ");
    EEPROM.write(addr, dht11_dat[0]); //humedad
    addr = addr + 1;
    EEPROM.write(addr, dht11_dat[2]); //temperatura
    addr = addr + 1;
    repeticiones = 0;
    if (addr == 1024)
    {
      addr = 0;
      Serial.print("EEPROM llena, se reescribirá...");
      Serial.println(" ");
      digitalWrite(13, HIGH);   // encendemos el LED para avisar
      delay(3000);              // esperamos tres segundos
      digitalWrite(13, LOW);    // apagamos el LED
    }  
  }
  
  //enviar valores a puerto serie para depuración
  Serial.print("Humedad = ");
  Serial.print(dht11_dat[0], DEC);
  Serial.print(".");
  Serial.print(dht11_dat[1], DEC);
  Serial.print("%  ");
  Serial.print("Temperatura = ");
  Serial.print(dht11_dat[2], DEC);
  Serial.print(".");
  Serial.print(dht11_dat[3], DEC);
  Serial.println("  ");

  //esperamos un minuto
  delay(60000);
}


Artículos relacionados


Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del Proyecto AjpdSoft.