Proyecto 13.2 - RTC & PG24064A

31 de octubre de 2015

El tutorial anterior es una introducción a los displays gráficos de gran tamaño. En dicho tutorial vimos como mostrar texto, gráficos y como leer el valor de un potenciómetro y mostrarlo por pantalla.

En el siguiente tutorial vamos a ampliar las capacidades del display. Veremos como conectar un RTC DS3231 y convertir el display en un reloj-calendario-termómetro y además mostraremos algún icono por pantalla.

Como en proyectos anteriores de cierta envergadura, en éste también iremos paso a paso, desglosando el problema en sketchs sencillos para luego unirlo todo y conseguir el objetivo final.

Proyecto 13.2a - RTC & PG24064A Graphic LCD Module

Como decía más arriba, ya hemos aprendido a mostrar por pantalla texto y gráficos por separado. 

En este primer ejemplo vamos a unir ambos. Mostraremos a la vez un gráfico y una línea de texto.

Esquema

El esquema que se muestra más abajo, es válido para los tres ejemplos que componen este tutorial.

En el primer ejemplo todavía no es necesario conectar el RTC. Lo podéis hacer más adelante.

Hay una pequeña diferencia con respecto al esquema del Proyecto 13.1 y es que he cambiado el pin A4 de la señal Enable, ahora la he conectado en el pin D3. Esto es porque necesitamos conectar el RTC en las entradas SDA y SCL. Hay que trasladar este cambio al constructor del display: 

U8GLIB_LC7981_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7,  3, 14, 15, 17, 16); 

Sketch

/*

  Iconos meteo y texto

  

  >>> Before compiling: Please remove comment from the constructor of the 

  >>> connected graphics display (see below).

  

  Universal 8bit Graphics Library, http://code.google.com/p/u8glib/

  

  Copyright (c) 2012, olikraus@gmail.com

  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 

  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 

    of conditions and the following disclaimer.

    

  * Redistributions in binary form must reproduce the above copyright notice, this 

    list of conditions and the following disclaimer in the documentation and/or other 

    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 

  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 

  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 

  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 

  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 

  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 

  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 

  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 

  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 

  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 

  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  

  

*/

#include "U8glib.h"

// setup u8g object, please remove comment from one of the following constructor calls

// IMPORTANT NOTE: The following list is incomplete. The complete list of supported 

// devices with all constructor calls is here: http://code.google.com/p/u8glib/wiki/device

U8GLIB_LC7981_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7,  3, 14, 15, 17, 16); 

// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 enable=3, chip select=A0 ,command/data=A1, read/write=A3, reset=A2

#define u8g_logo_width 64

#define u8g_logo_height 64

//static unsigned char u8g_logo_bits[] = {

static unsigned char u8g_logo_bits[] U8G_PROGMEM = {

   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x1c, 0x00, 

0x00, 0x00, 0x7c, 0x00, 0x3c, 0x00, 0x3e, 0x00, 

0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0x00, 

0x00, 0x00, 0xfc, 0x01, 0x00, 0x80, 0x3f, 0x00, 

0x00, 0x00, 0xf8, 0x03, 0x00, 0xc0, 0x1f, 0x00, 

0x00, 0x00, 0xf0, 0x03, 0x00, 0xc0, 0x0f, 0x00, 

0x00, 0x00, 0xe0, 0x83, 0xff, 0xc1, 0x07, 0x00, 

0x00, 0x00, 0xc0, 0xe1, 0xff, 0x87, 0x03, 0x00, 

0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 

0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f, 0x00, 0x00, 

0x00, 0x00, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 

0x00, 0xc0, 0xff, 0xff, 0x81, 0x7f, 0x00, 0x00, 

0x00, 0xf0, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 

0x00, 0xf8, 0xff, 0xff, 0x01, 0xfc, 0x00, 0x00, 

0x00, 0xfc, 0xbf, 0xff, 0x03, 0xfc, 0x00, 0x00, 

0x00, 0xfe, 0x03, 0xfc, 0x07, 0xf8, 0x00, 0x00, 

0x00, 0xff, 0x00, 0xf0, 0x0f, 0xf8, 0xf0, 0x0f, 

0x00, 0x3f, 0x00, 0xe0, 0x0f, 0xf8, 0xf0, 0x0f, 

0x80, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xf0, 0x0f, 

0x80, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xf0, 0x0f, 

0xc0, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 

0xc0, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x06, 0xfe, 0x01, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0x80, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0x80, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0x00, 0x3f, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0x00, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 

0x00, 0xfe, 0x03, 0x00, 0x00, 0xfe, 0x01, 0x00, 

0x00, 0xfc, 0x1f, 0x00, 0x80, 0xff, 0x00, 0x00, 

0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 

0x00, 0xf0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 

0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 

0x00, 0x00, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

void draw(void) {

  // graphic commands to redraw the complete screen should be placed here  

  u8g.drawXBMP( 0, 0, u8g_logo_width, u8g_logo_height, u8g_logo_bits);

  u8g.setFont(u8g_font_unifont);

  //u8g.setFont(u8g_font_osb21);

  u8g.drawStr( 70, 11, "Hello World!");

}

void setup(void) {

  // flip screen, if required

  // u8g.setRot180();

}

void loop(void) {

  // picture loop

  u8g.firstPage();  

  do {

    draw();

  } while( u8g.nextPage() );

  

  // rebuild the picture after some delay

  delay(500);

}

Tras cargar el sketch al Arduino, esto será lo que muestre la pantalla:

Proyecto 13.2b - RTC & PG24064A Graphic LCD Module

Bien, ya hemos aprendido a mostrar gráficos y texto por pantalla. 

Ahora vamos a conectar el RTC como se indica en el esquema. Partiendo del sketch del ejemplo Hello World! añadimos los campos que corresponden al RTC del Proyecto 23 y tras hacer varias pruebas al final queda como sigue.

Recordad desmarcar la línea para poner en hora el RTC // parse_cmd("T004300631102015",16); solo la primera vez que subamos el sketch.

Sketch

/*

  Real Time Clock con Graphic LCD Module POWERTIP PG24064-A

  Sketch a pantalla completa

  _______________________________

  RTC with Graphic LCD Module

  Sabado   31  Octubre   2015

  1:14:40

  Temperatura 22.5ºC

  sites.google.com/site/angmuz

  ______________________________

  

  Se ha cambiado el pin para Enable A4 en el original por D3, para dejar libres las entradas SDA y SCL

  

  >>> Before compiling: Please remove comment from the constructor of the 

  >>> connected graphics display (see below).

  

  Universal 8bit Graphics Library, http://code.google.com/p/u8glib/

  

  Copyright (c) 2012, olikraus@gmail.com

  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 

  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 

    of conditions and the following disclaimer.

    

  * Redistributions in binary form must reproduce the above copyright notice, this 

    list of conditions and the following disclaimer in the documentation and/or other 

    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 

  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 

  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 

  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 

  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 

  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 

  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 

  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 

  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 

  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 

  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  

  

*/

#include "U8glib.h"

#include "ds3231.h"

#include <Wire.h>

#define BUFF_MAX 128

uint8_t time[8];

char recv[BUFF_MAX];

unsigned int recv_size = 0;

unsigned long prev, interval = 1000;

// setup u8g object, please remove comment from one of the following constructor calls

// IMPORTANT NOTE: The following list is incomplete. The complete list of supported 

// devices with all constructor calls is here: http://code.google.com/p/u8glib/wiki/device

U8GLIB_LC7981_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7,  3, 14, 15, 17, 16); 

// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 enable=3, chip select=A0 ,command/data=A1, read/write=A3, reset=A2

void draw(void) {

  // graphic commands to redraw the complete screen should be placed here  

  u8g.setFont(u8g_font_unifont);

  u8g.drawStr( 0, 11, "RTC with Graphic LCD Module");

  char in;

  char tempF[6]; 

  float temperature;

  char buff[BUFF_MAX];

  unsigned long now = millis();

  struct ts t;

  

  // show time once in a while

    //if ((now - prev > interval) && (Serial.available() <= 0)) {

        DS3231_get(&t); //Get time

        parse_cmd("C",1);

        temperature = DS3231_get_treg(); //Get temperature

        dtostrf(temperature, 5, 1, tempF);

        

        // dia de la semana

        u8g.setPrintPos(0, 23);

        printDay(t.wday);

        // dia del mes

        u8g.setPrintPos(72, 23);

        u8g.print(t.mday);

        // mes

        u8g.setPrintPos(100, 23);

        printMonth(t.mon);

        // año

        u8g.setPrintPos(180, 23);

        u8g.print(t.year);

        

        // hora

        if(t.hour<10)

        {

          u8g.setPrintPos(8, 34);

          u8g.print(t.hour);

        }

        else 

        {

        u8g.setPrintPos(0, 34);

        u8g.print(t.hour);

        }

        u8g.setPrintPos(16, 34);

        u8g.print(":");

        if(t.min<10)

        {

          u8g.setPrintPos(20, 34);

          u8g.print("0");

          u8g.setPrintPos(28, 34);

          u8g.print(t.min);

        }

        else

        {

          u8g.setPrintPos(22, 34);

          u8g.print(t.min);

        }

        u8g.setPrintPos(38, 34);

        u8g.print(":");

        if(t.sec<10)

        {

          u8g.setPrintPos(48, 34);

          u8g.print("0");

          u8g.setPrintPos(56, 34);

          u8g.print(t.sec);

        }

        else 

        {

        u8g.setPrintPos(48, 34);

        u8g.print(t.sec);

        }

        // temperatura

        u8g.setPrintPos(0, 45);

        u8g.print("Temperatura");

        u8g.setPrintPos(96, 45);

        u8g.print(tempF);

        u8g.setPrintPos(140, 45);

        u8g.print((char)176);

        u8g.setPrintPos(145, 45);

        u8g.print("C");

        

        // creditos

        u8g.setPrintPos(0, 62);

        u8g.print("sites.google.com/site/angmuz");

        

        //prev = now;

    //}

    

    if (Serial.available() > 0) {

        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {

            parse_cmd(recv, recv_size);

            recv_size = 0;

            recv[0] = 0;

        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]

        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long

            // drop

            recv_size = 0;

            recv[0] = 0;

        } else if (recv_size < BUFF_MAX - 2) {

            recv[recv_size] = in;

            recv[recv_size + 1] = 0;

            recv_size += 1;

        }

    }

  

}

void setup(void) {

  

    Serial.begin(9600);

    Wire.begin();

    DS3231_init(DS3231_INTCN);

    memset(recv, 0, BUFF_MAX);

    

    // (seconds,minutes,hour,week day,date, month,year)

    // parse_cmd("T004300631102015",16);

    

  

  // flip screen, if required

  // u8g.setRot180();

  

  // set SPI backup if required

  //u8g.setHardwareBackup(u8g_backup_avr_spi);

  // assign default color value

  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {

    u8g.setColorIndex(255);     // white

  }

  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {

    u8g.setColorIndex(3);         // max intensity

  }

  else if ( u8g.getMode() == U8G_MODE_BW ) {

    u8g.setColorIndex(1);         // pixel on

  }

  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {

    u8g.setHiColorByRGB(255,255,255);

  }

}

void loop(void) {

  

  

        

  // picture loop

  u8g.firstPage();  

  do {

    draw();

  } while( u8g.nextPage() );

  

    

  

  // rebuild the picture after some delay

  delay(50);

}

void parse_cmd(char *cmd, int cmdsize)

{

    uint8_t i;

    uint8_t reg_val;

    char buff[BUFF_MAX];

    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);

    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time

    if (cmd[0] == 84 && cmdsize == 16) {

        //T355720619112011

        t.sec = inp2toi(cmd, 1);

        t.min = inp2toi(cmd, 3);

        t.hour = inp2toi(cmd, 5);

        t.wday = inp2toi(cmd, 6);

        t.mday = inp2toi(cmd, 8);

        t.mon = inp2toi(cmd, 10);

        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);

        DS3231_set(t);

        //Serial.println("OK");

    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1

        DS3231_get_a1(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1

        DS3231_get_a2(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register

        //Serial.print("aging reg is ");

        //Serial.println(DS3231_get_aging(), DEC);

    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1

        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);

        //ASSMMHHDD

        for (i = 0; i < 4; i++) {

            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd

        }

        byte flags[5] = { 0, 0, 0, 0, 0 };

        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);

        DS3231_get_a1(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2

        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);

        //BMMHHDD

        for (i = 0; i < 4; i++) {

            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd

        }

        byte flags[5] = { 0, 0, 0, 0 };

        DS3231_set_a2(time[0], time[1], time[2], flags);

        DS3231_get_a2(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register

        //Serial.print("temperature reg is ");

        //Serial.println(DS3231_get_treg(), DEC);

    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags

        reg_val = DS3231_get_sreg();

        reg_val &= B11111100;

        DS3231_set_sreg(reg_val);

    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct

        reg_val = DS3231_get_addr(0x5);

        //Serial.print("orig ");

        //Serial.print(reg_val,DEC);

        //Serial.print("month is ");

        //Serial.println(bcdtodec(reg_val & 0x1F),DEC);

    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register

        DS3231_set_aging(0);

    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register

        //Serial.print("status reg is ");

        //Serial.println(DS3231_get_sreg(), DEC);

    } else {

        //Serial.print("unknown command prefix ");

        //Serial.println(cmd[0]);

        //Serial.println(cmd[0], DEC);

    }

}

void printDay(int wday)

{

  switch(wday)

  {

    case 1: u8g.print("Lunes");break;

    case 2: u8g.print("Martes");break;

    case 3: u8g.print("Miercoles");break;

    case 4: u8g.print("Jueves");break;

    case 5: u8g.print("Viernes");break;

    case 6: u8g.print("Sabado");break;

    case 7: u8g.print("Domingo");break;

    default: u8g.print("Error");break;

  } 

}

void printMonth(int month)

{

  switch(month)

  {

    case 1: u8g.print("Enero");break;

    case 2: u8g.print("Febrero");break;

    case 3: u8g.print("Marzo");break;

    case 4: u8g.print("Abril");break;

    case 5: u8g.print("Mayo");break;

    case 6: u8g.print("Junio");break;

    case 7: u8g.print("Julio ");break;

    case 8: u8g.print("Agosto");break;

    case 9: u8g.print("Septiempre");break;

    case 10: u8g.print("Octubre");break;

    case 11: u8g.print("Noviembre");break;

    case 12: u8g.print("Diciembre");break;

    default: u8g.print("Error");break;

  } 

}

A continuación la imagen correspondiente al sketch del ejemplo anterior.

Proyecto 13.2c - RTC & PG24064A Graphic LCD Module

Ahora que ya tenemos configurado el RTC, vamos a unir los sketchs de los ejemplos anteriores y a convertir el display en una auténtica estación meteorológica.

Modificando ligeramente el sketch anterior, mostraremos por pantalla la información proporcionada por el RTC junto a un pequeño icono meteorológico para hacer el resultado mucho mas vistoso.

Sketch

/*

  Real Time Clock con Graphic LCD Module POWERTIP PG24064-A

  Sketch con iconos de tiempo incluidos

  _______________________________

                Sab 31 Oct 2015

                3:49:18

                Temperatura 22.5ºC

                Intervalos nubosos

                Angel M. sites@angmuz

  _______________________________

  

  Se ha cambiado el pin para Enable A4 en el original por D3, para dejar libres las entradas SDA y SCL

  

  >>> Before compiling: Please remove comment from the constructor of the 

  >>> connected graphics display (see below).

  

  Universal 8bit Graphics Library, http://code.google.com/p/u8glib/

  

  Copyright (c) 2012, olikraus@gmail.com

  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 

  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 

    of conditions and the following disclaimer.

    

  * Redistributions in binary form must reproduce the above copyright notice, this 

    list of conditions and the following disclaimer in the documentation and/or other 

    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 

  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 

  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 

  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 

  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 

  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 

  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 

  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 

  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 

  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 

  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 

  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 

  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  

  

*/

#include "U8glib.h"

#include "ds3231.h"

#include <Wire.h>

#define BUFF_MAX 128

uint8_t time[8];

char recv[BUFF_MAX];

unsigned int recv_size = 0;

unsigned long prev, interval = 1000;

// setup u8g object, please remove comment from one of the following constructor calls

// IMPORTANT NOTE: The following list is incomplete. The complete list of supported 

// devices with all constructor calls is here: http://code.google.com/p/u8glib/wiki/device

U8GLIB_LC7981_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7,  3, 14, 15, 17, 16); 

// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 enable=3, chip select=A0 ,command/data=A1, read/write=A3, reset=A2

#define u8g_logo_width 64

#define u8g_logo_height 64

//static unsigned char u8g_logo_bits[] = {

static unsigned char u8g_logo_bits[] U8G_PROGMEM = {

   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x1c, 0x00, 

0x00, 0x00, 0x7c, 0x00, 0x3c, 0x00, 0x3e, 0x00, 

0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0x00, 

0x00, 0x00, 0xfc, 0x01, 0x00, 0x80, 0x3f, 0x00, 

0x00, 0x00, 0xf8, 0x03, 0x00, 0xc0, 0x1f, 0x00, 

0x00, 0x00, 0xf0, 0x03, 0x00, 0xc0, 0x0f, 0x00, 

0x00, 0x00, 0xe0, 0x83, 0xff, 0xc1, 0x07, 0x00, 

0x00, 0x00, 0xc0, 0xe1, 0xff, 0x87, 0x03, 0x00, 

0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 

0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f, 0x00, 0x00, 

0x00, 0x00, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 

0x00, 0xc0, 0xff, 0xff, 0x81, 0x7f, 0x00, 0x00, 

0x00, 0xf0, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 

0x00, 0xf8, 0xff, 0xff, 0x01, 0xfc, 0x00, 0x00, 

0x00, 0xfc, 0xbf, 0xff, 0x03, 0xfc, 0x00, 0x00, 

0x00, 0xfe, 0x03, 0xfc, 0x07, 0xf8, 0x00, 0x00, 

0x00, 0xff, 0x00, 0xf0, 0x0f, 0xf8, 0xf0, 0x0f, 

0x00, 0x3f, 0x00, 0xe0, 0x0f, 0xf8, 0xf0, 0x0f, 

0x80, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xf0, 0x0f, 

0x80, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xf0, 0x0f, 

0xc0, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 

0xc0, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x06, 0xfe, 0x01, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0xc0, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0x80, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 

0x80, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0x00, 0x3f, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 

0x00, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 

0x00, 0xfe, 0x03, 0x00, 0x00, 0xfe, 0x01, 0x00, 

0x00, 0xfc, 0x1f, 0x00, 0x80, 0xff, 0x00, 0x00, 

0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 

0x00, 0xf0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 

0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 

0x00, 0x00, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

void draw(void) {

  // graphic commands to redraw the complete screen should be placed here  

  u8g.drawXBMP( 0, 0, u8g_logo_width, u8g_logo_height, u8g_logo_bits);

  

  u8g.setFont(u8g_font_unifont);

  

  char in;

  char tempF[6]; 

  float temperature;

  char buff[BUFF_MAX];

  unsigned long now = millis();

  struct ts t;

  

  // show time once in a while

    //if ((now - prev > interval) && (Serial.available() <= 0)) {

        DS3231_get(&t); //Get time

        parse_cmd("C",1);

        temperature = DS3231_get_treg(); //Get temperature

        dtostrf(temperature, 5, 1, tempF);

        

        // dia de la semana

        u8g.setPrintPos(70, 11);

        printDay(t.wday);

        // dia del mes

        u8g.setPrintPos(142, 11);

        u8g.print(t.mday);

        // mes

        u8g.setPrintPos(166, 11);

        printMonth(t.mon);

        // año

        u8g.setPrintPos(200, 11);

        u8g.print(t.year);

        

        // hora

        if(t.hour<10)

        {

          u8g.setPrintPos(78, 23);

          u8g.print(t.hour);

        }

        else 

        {

        u8g.setPrintPos(70, 23);

        u8g.print(t.hour);

        }

        u8g.setPrintPos(86, 23);

        u8g.print(":");

        

        // minutos

        if(t.min<10)

        {

          u8g.setPrintPos(94, 23);

          u8g.print("0");

          u8g.setPrintPos(102, 23);

          u8g.print(t.min);

        }

        else

        {

          u8g.setPrintPos(94, 23);

          u8g.print(t.min);

        }

        u8g.setPrintPos(110, 23);

        u8g.print(":");

        

        // segundos

        if(t.sec<10)

        {

          u8g.setPrintPos(118, 23);

          u8g.print("0");

          u8g.setPrintPos(126, 23);

          u8g.print(t.sec);

        }

        else 

        {

          u8g.setPrintPos(118, 23);

          u8g.print(t.sec);

        }

        

        // temperatura

        u8g.setPrintPos(70, 35);

        u8g.print("Temperatura:");

        u8g.setPrintPos(166, 35);

        u8g.print(tempF);

        u8g.setPrintPos(210, 35);

        u8g.print((char)176);

        u8g.setPrintPos(215, 35);

        u8g.print("C");

        

        // pronostico

        u8g.setPrintPos(70, 49);

        u8g.print("Intervalos nubosos");

        

        // creditos

        u8g.setPrintPos(70, 62);

        u8g.print("Angel M. sites@angmuz");

        

        

    

    if (Serial.available() > 0) {

        in = Serial.read();

        if ((in == 10 || in == 13) && (recv_size > 0)) {

            parse_cmd(recv, recv_size);

            recv_size = 0;

            recv[0] = 0;

        } else if (in < 48 || in > 122) {;       // ignore ~[0-9A-Za-z]

        } else if (recv_size > BUFF_MAX - 2) {   // drop lines that are too long

            // drop

            recv_size = 0;

            recv[0] = 0;

        } else if (recv_size < BUFF_MAX - 2) {

            recv[recv_size] = in;

            recv[recv_size + 1] = 0;

            recv_size += 1;

        }

    }

  

}

void setup(void) {

  

    Serial.begin(9600);

    Wire.begin();

    DS3231_init(DS3231_INTCN);

    memset(recv, 0, BUFF_MAX);

    

    // (seconds,minutes,hour,week day,date, month,year)

    // parse_cmd("T004300631102015",16); 

    

  

  // flip screen, if required

  // u8g.setRot180();

  

  // set SPI backup if required

  //u8g.setHardwareBackup(u8g_backup_avr_spi);

  // assign default color value

  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {

    u8g.setColorIndex(255);     // white

  }

  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {

    u8g.setColorIndex(3);         // max intensity

  }

  else if ( u8g.getMode() == U8G_MODE_BW ) {

    u8g.setColorIndex(1);         // pixel on

  }

  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {

    u8g.setHiColorByRGB(255,255,255);

  }

}

void loop(void) {

  

  

        

  // picture loop

  u8g.firstPage();  

  do {

    draw();

  } while( u8g.nextPage() );

  

    

  

  // rebuild the picture after some delay

  delay(50);

}

void parse_cmd(char *cmd, int cmdsize)

{

    uint8_t i;

    uint8_t reg_val;

    char buff[BUFF_MAX];

    struct ts t;

    //snprintf(buff, BUFF_MAX, "cmd was '%s' %d\n", cmd, cmdsize);

    //Serial.print(buff);

    // TssmmhhWDDMMYYYY aka set time

    if (cmd[0] == 84 && cmdsize == 16) {

        //T355720619112011

        t.sec = inp2toi(cmd, 1);

        t.min = inp2toi(cmd, 3);

        t.hour = inp2toi(cmd, 5);

        t.wday = inp2toi(cmd, 6);

        t.mday = inp2toi(cmd, 8);

        t.mon = inp2toi(cmd, 10);

        t.year = inp2toi(cmd, 12) * 100 + inp2toi(cmd, 14);

        DS3231_set(t);

        //Serial.println("OK");

    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1

        DS3231_get_a1(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1

        DS3231_get_a2(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register

        //Serial.print("aging reg is ");

        //Serial.println(DS3231_get_aging(), DEC);

    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1

        DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);

        //ASSMMHHDD

        for (i = 0; i < 4; i++) {

            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd

        }

        byte flags[5] = { 0, 0, 0, 0, 0 };

        DS3231_set_a1(time[0], time[1], time[2], time[3], flags);

        DS3231_get_a1(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2

        DS3231_set_creg(DS3231_INTCN | DS3231_A2IE);

        //BMMHHDD

        for (i = 0; i < 4; i++) {

            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd

        }

        byte flags[5] = { 0, 0, 0, 0 };

        DS3231_set_a2(time[0], time[1], time[2], flags);

        DS3231_get_a2(&buff[0], 59);

        //Serial.println(buff);

    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register

        //Serial.print("temperature reg is ");

        //Serial.println(DS3231_get_treg(), DEC);

    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags

        reg_val = DS3231_get_sreg();

        reg_val &= B11111100;

        DS3231_set_sreg(reg_val);

    } else if (cmd[0] == 70 && cmdsize == 1) {  // "F" - custom fct

        reg_val = DS3231_get_addr(0x5);

        //Serial.print("orig ");

        //Serial.print(reg_val,DEC);

        //Serial.print("month is ");

        //Serial.println(bcdtodec(reg_val & 0x1F),DEC);

    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register

        DS3231_set_aging(0);

    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register

        //Serial.print("status reg is ");

        //Serial.println(DS3231_get_sreg(), DEC);

    } else {

        //Serial.print("unknown command prefix ");

        //Serial.println(cmd[0]);

        //Serial.println(cmd[0], DEC);

    }

}

void printDay(int wday)

{

  switch(wday)

  {

    case 1: u8g.print("Lunes");break;

    case 2: u8g.print("Martes");break;

    case 3: u8g.print("Miercoles");break;

    case 4: u8g.print("Jueves");break;

    case 5: u8g.print("Viernes");break;

    case 6: u8g.print("Sabado");break;

    case 7: u8g.print("Domingo");break;

    default: u8g.print("Error");break;

  } 

}

void printMonth(int month)

{

  switch(month)

  {

    case 1: u8g.print("Ene");break;

    case 2: u8g.print("Feb");break;

    case 3: u8g.print("Mar");break;

    case 4: u8g.print("Abr");break;

    case 5: u8g.print("May");break;

    case 6: u8g.print("Jun");break;

    case 7: u8g.print("Jul");break;

    case 8: u8g.print("Ago");break;

    case 9: u8g.print("Sep");break;

    case 10: u8g.print("Oct");break;

    case 11: u8g.print("Nov");break;

    case 12: u8g.print("Dic");break;

    default: u8g.print("Error");break;

  } 

}


Esta es una imagen de nuestra flamante estación meteorológica.

Links

Special thanks to:

Olikraus for the U8g Arduino Monochrom Graphics Library.

Petre Rodan for the arduino library for DS3231 RTC.

Adam Whitcroft for the weather icons.