Proyecto 13.2 - RTC & PG24064A
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.