
Introduction
Some months ago in Kawasemi Corp., after the release of the iPhone and iPad app quartsd15, we thought... why working just with iDevices? Why not making a desktop clock with the same functions?
The end result is Pallars, a clock based on Arduino and the software developed for quartsd15 that gives the time following the traditional Catalan system, and with time adjust buttons.
The Traditional System
The time units in the traditional system are the quart (15 minutes) and the mig quart (7 minutes and a half), and the time is based in the current hour, nor the past hour. So, 02:07 are mig quart de tres, half a quarter of three; 02:15, un quart de tres, a quarter of three; 02:22, un quart i mig de tres, a quarter and a half of three, etc.
Minutes don't make too much sense in this system, born in the era of sundials. The space between hours of a sundial were divided in four quarters, and these quarters were divided in two parts for the half quarter.
Times near a quarter or a half quarter are expressed approximatively. If it's a minute before a quarter, we use the expressión gairebé un quart, almost a quarter. If it's two or three minutes, vora un quart, near a quarter. So, 02:14 are gairebé un quart de tres, almost a quarter of three, and 02:13 or 02:12 are vora un quart de tres, near a quarter of three.
If it's one or two minutes after a quarter, the right expression is un quart tocat, "a touched quarter", and if it's three or four minutes, un quart ben tocat, "a well-touched quarter". These expressions are a reminiscence of the "touch" of the bell towers. 02:16 are un quart tocat de tres, "a touched quarter of three", and 02:18, un quart ben tocat de tres, "a well-touched quarter of three". These expressions are used with o'clock hours too. 02:02 are las dues tocades, "the two touched".
To add more precision, the system uses the expressions i cinc and i deu, "and five" and "and ten". 02:05 are las dues i cinc, two and five, and 02:25 un quart i deu de tres, a quarter and ten of three.
Around half an hour, we use the expression dos quarts, two quarters, as a basis, and around forty five minutes, tres quarts, three quarters. 02:32 are dos quarts tocats de tres, two touched quarters of three, and 02:43, vora tres quarts de tres, near three quarters of three.
When the end of the hour is near, we go back to vora and gairebé. 02:57 are vora las tres, near three, and 02:59, gairebé las tres, almost three.
The system also specifies the part of the day, always using as a reference the said hour, so, the running hour. La Matinada, early morning, goes from 1 hour to 5 hours; el Matí, the morning from 6 to 11; el migdia, noon, from 12 to 14 hours; la tarda, the afternoon, from 15 to 18; el vespre, the evening, from 19 to 22 hours; and la nit, the night, from 23 to 24 hours. 02:30 are dos quarts de tres de la matinada, two quarters of three of the early morning. 11:15, un quart de dotze del migdia, a quarter of twelve of noon.
Hardware
This is the hardware required for this project:
|
| 1 Arduino Mega 2560. We've made tests with an Arduino UNO and other Arduino models, but they don't work well. Perhaps the intensive use of the String() library in the sketch is too much for the UNO and the more powerful hardware of the Mega is required. |
| A clock chip. The internal clock of Arduino is not enough to work as a real clock, and it resets to zero each time Arduino loses power. We need then a clock chip with a battery that allows keeping the time without power. We've used this excellent circuit based on the DS1307 chip made by Adafruit Industries | |
| A screen. We've used this LCD screen, simple but functional, available in several shops, including Adafruit Industries. We can't use the typical 16X2 LCD, since some strings of the traditional system are longer than 32 characters. | |
| 3 buttons. You can use any tactile button of the kind frequently used in electronics projects. We've used this Sparkfun buttons that have a nice look and can be mounted on a breakout board that makes easier to install them in a box or case. | |
| 1 small breadboard. It will make easier mounting the clock in a case. It would be also convenient to have a big breadboard for testing the LCD before mounting the clock. | |
| Wires. We need a good amount of wires for this project. We need two wires for each button, and a bunch of them for the LCD, since it has a parallel interface. We will anyway explain later how to simplify the LCD cabling to make easier mounting it in a case. | |
| An AC adapter. It's a desktop clock, so the easy solution is an AC adapter. As usual in an Arduino project, we require a 9V, 500 mA adapter. |
Building the clock
Connecting the DS1307 breakout board and configuring time
We will start with the DS1307 breakout board. It's an i2c device, so we have to connect SDA and SCL pins to the SDA and SCL pins of the Arduino Mega, and of course, the GND pin to an Arduino GND pin, and 5V to an Arduino 5V pin. We don't need the SQW pin.
We can make these connections through a breadboard, or to simplify things, we can connect the breakout board straight on the Arduino pins, as you can see in this photograph, leaving SQW pin out. To power the breakout board, we will configure in the sketch digital pin 18 as OUTPUT and LOW and digital pin 19 as OUTPUT and HIGH, giving it GND and 5V.
The DS1307 comes out of the box without no configured time. If we want to make tests before building the whole clock, we can configure the time through a simple sketch that will assign to it the time when we've compiled the sketch. Once we have connected the DS1307 breakout board to the Arduino, and the Arduino to our computer, we can compile and donwload the following sketch.
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib #include#include "RTClib.h" RTC_DS1307 RTC; void setup () { Serial.begin(57600); Wire.begin(); RTC.begin(); pinMode(18, OUTPUT); digitalWrite(18, LOW); pinMode(19, OUTPUT); digitalWrite(19, HIGH); RTC.adjust(DateTime(__DATE__, __TIME__)); if (! RTC.isrunning()) { Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled RTC.adjust(DateTime(__DATE__, __TIME__)); } } void loop () { DateTime now = RTC.now(); Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); Serial.print(" since midnight 1/1/1970 = "); Serial.print(now.unixtime()); Serial.print("s = "); Serial.print(now.unixtime() / 86400L); Serial.println("d"); // calculate a date which is 7 days and 30 seconds into the future DateTime future (now.unixtime() + 7 * 86400L + 30); Serial.print(" now + 7d + 30s: "); Serial.print(future.year(), DEC); Serial.print('/'); Serial.print(future.month(), DEC); Serial.print('/'); Serial.print(future.day(), DEC); Serial.print(' '); Serial.print(future.hour(), DEC); Serial.print(':'); Serial.print(future.minute(), DEC); Serial.print(':'); Serial.print(future.second(), DEC); Serial.println(); Serial.println(); delay(3000); }
Once this is done, and while we keep the battery in the circuit, the DS1307 chip will keep the time. Later on, with the complete circuit, we will be able to adjust the time with the buttons.
Connecting the LCD
Following the instructions on Adafruit, these are the connections needed for the LCD and its potentiometer, that adjust brightness.
| LCD | ARDUINO | FUNCTION |
| 1 | GND | LCD Power |
| 2 | 5V | LCD Power |
| 5 | GND | RW, unused |
| 4 | 7 | Data |
| 6 | 8 | Data |
| 14 | 12 | Data |
| 13 | 11 | Data |
| 12 | 10 | Data |
| 11 | 9 | Data |
Finally, we connect the central pin of the potentiometer to pin 3 of the LCD, and the left and right pins of the potentiometer, one to GND and the other one to 5V.
You can read on Adafruit an excellent tutorial explaining these connections in detail, and it's highly recommended, before building the clock, to make some tests and make sure that the LCD is working.
Buttons
The three buttons are in a pullup configuration. So, we don't need an external resistor, and we will work with the internal resistors of the Arduino pins. One of the pins of each button will be connected to GND and the other one, to a digital pin on Arduino.
One of the buttons activates the time adjustment routine, and the other two adjust hours and minutes.
These Sparkfun buttons have a LED inside. We haven't used this function, leaving the corresponding pins disconnected.
Code
You can download on this link the Arduino sketch for the clock. We will explain now the code step by step.
//Horacatalana.pde #include <Wire.h> #include "RTClib.h" #include <LiquidCrystal.h> #include <Button.h> // pins lcd LiquidCrystal lcd(7, 8, 9, 10, 11, 12); Button botoSet = Button (4, PULLUP); //botons per fixar hora Button botoHores = Button (5, PULLUP); Button botoMinuts = Button (6, PULLUP); const int caracterslcd = 80; RTC_DS1307 RTC;
We start as usual with the Arduino libraries we will use. Wire and LiquidCrystal are part of the Arduino IDE. RTClib can be downloaded here and the Button library here.
Next, we create the lcd object, specifying the Arduino pins where it is connected, and Button class objects that will define our buttons. We specify next the Arduino pins where we have connected them to, and we configure them in a pullup configuration.
We will also define here a constant with the total of characters on the LCD, that will be useful later to clear the screen, and the object defining the clock chip.
void setup () {
Wire.begin();
RTC.begin();
//pins del rtc, Mega 18 --> GND, 19 --> 5V
pinMode(18, OUTPUT);
digitalWrite(18, LOW);
pinMode(19, OUTPUT);
digitalWrite(19, HIGH);
// tamany del lcd
lcd.begin(20, 4);
Serial.begin(57600);
}
The setup() function initializes the clock chip, configures the chips that will supply power to it, and initializes the lcd, specifying its lines and characters per line, as required by the LiquidCrystal library.
void loop () {
String hora, horaseg, horaquart, lahora;
String cadena1,cadena2,cadena3,cadena4; //lahora de 20 en 20
String cadenablancs; //per fer la cadena de 80 caracteres y netejar tot el lcd
lahora= String(); //string del texte de la hora
String lahorafinal; //lahora amb blancs
int horadeldia = 0; //per la part del dia
loop() starts declaring the String objects we will use to build the string with the time and to clear the screen, and other variables whose function will be explained later.
if (botoSet.isPressed()) { //boto pulsat, rutina adjustament hora
DateTime horaSet = RTC.now();
int horaDelSet = horaSet.hour();
int minutsDelSet = horaSet.minute();
lcd.setCursor(0,0);
if (horaDelSet < 10) { //posarem un 0 davant
lcd.print("0");
}
lcd.print(horaDelSet,DEC);
lcd.print(":");
if (minutsDelSet < 10) { //posarem un 0 davant
lcd.print("0");
}
lcd.print(minutsDelSet,DEC);
for (int f=0; f < 75; f++) {
lcd.print(" "); //blancs per "netejar" el lcd, millor que clear() que faria "flickering"
}
There are two main states of the loop() function, controlled by an if...else: if the Set button isn't pressed, the clock will show the time; and if it is pressed, the time adjustment routine is activated. In that case, first of all we create an object that will store the time at that moment in the clock chip. That time is showed on the lcd in digital format while Set is pressed. This will make easier the time adjustment. The for() loop at the end prints blank characters in the part of the lcd where the time isn't printed. It is a bit primitive way to clear the screen, and in fact the LiquidCrystal library includes a clear() function, but our tests showed that it caused a constant flickering of the lcd that made it unreadable.
if (botoHores.isPressed()) {
if (botoHores.stateChanged()) { //adjustem despres de cada pulsacio, no amb la pulsacio
DateTime horacanvi = RTC.now();
DateTime meshoras (horacanvi.unixtime() + 3600);
RTC.adjust(meshoras);
}
}
if (botoMinuts.isPressed()) {
if (botoMinuts.stateChanged()) {
DateTime horacanvi2 = RTC.now();
DateTime mesminuts (horacanvi2.unixtime() + 60);
RTC.adjust(mesminuts);
}
}
}
Next we have two ifs adjusting hours and minutes. We control the state of the button, and after each press, we create a DateTime object with the corresponding increase in seconds. This new object is used to change the time on the clock chip with the function adjust().
else { //mostrem la hora catalana
DateTime now = RTC.now();
int hour = now.hour();
int minute = now.minute();
int hora12 = hour % 12; //no volem hora en format 24 hores
switch(hora12) {
case 0: hora="les dotze "; horaseg="la una "; horaquart="d'una"; break;
case 1: hora="la una "; horaseg="les dues "; horaquart="de dues"; break;
case 2: hora="les dues "; horaseg="les tres "; horaquart="de tres"; break;
case 3: hora="les tres "; horaseg="les quatre "; horaquart="de quatre"; break;
case 4: hora="les quatre "; horaseg="les cinc "; horaquart="de cinc"; break;
case 5: hora="les cinc "; horaseg="les sis "; horaquart="de sis"; break;
case 6: hora="les sis "; horaseg="les set "; horaquart="de set"; break;
case 7: hora="les set "; horaseg="les vuit "; horaquart="de vuit"; break;
case 8: hora="les vuit "; horaseg="les nou "; horaquart="de nou"; break;
case 9: hora="les nou "; horaseg="les deu "; horaquart="de deu"; break;
case 10: hora="les deu "; horaseg="les onze "; horaquart="d'onze"; break;
case 11: hora="les ontze "; horaseg="les dotze "; horaquart="de dotze"; break;
}
Now comes the part that will build a string with the Catalan time. First of all we get the current time and we extract from the DateTime object the hours and the minutes, changing the hour to 12-hours format, since the 24-hours format doesn't make any sense in the Catalan system.
With a switch...case that uses the value of the hour as control, we assign strings to three variables that will be used later or not depending on the minutes of the time. The minutes are the ones who will determine if we have to print the current hour, or the next hour... just as it's been explained above.
switch(minute){
case 0: lahora = hora; break;
case 1:
case 2: if(hora12==1) lahora = hora + "tocada"; else lahora = hora + "tocades"; break;
case 3:
case 4: if(hora12==1) lahora = hora + "ben tocada"; else lahora = hora + "ben tocades"; break;
case 5: lahora= hora + "i cinc"; break;
case 6: lahora = "vora mig quart " + horaquart; break;
case 7:
case 8: lahora = "mig quart " + horaquart; break;
(...)
case 30: lahora = "dos quarts " + horaquart; break;
case 31:
case 32: lahora = "dos quarts tocats " + horaquart; break;
case 33: lahora = "dos quarts ben tocats " + horaquart; break;
case 34: lahora = "gairebe dos quarts i cinc " + horaquart; break;
case 35: lahora = "dos quarts i cinc " + horaquart; break;
case 36: lahora = "vora dos quarts i mig " + horaquart; break;
(...)
case 58: lahora = "vora " + horaseg; break;
case 59: lahora = "a punt de tocar " + horaseg; break;
}
Another case with each minute, and that it isn't showed full here, builds the string with the Catalan time, using the corresponding expressions and the variables that are needed from the former case. The Catalan language uses tildes in words like "gairebé", but we can't print tildes since the lcd doesn't include a character set with tildes.
//part del dia
//la part del dia es determina per la hora esmentada. Segons el minuts, la hora determinant sera la mateixa o la següent
switch (minute) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5: horadeldia = hour; break;
default: horadeldia = hour +1; break;
}
//ara afegim la part del dia
switch (horadeldia) {
case 0: lahora = lahora + " de la nit"; break;
case 1:
case 2:
case 3:
case 4:
case 5: lahora = lahora + " de la matinada"; break;
case 6:
case 7:
case 8:
case 9:
case 10:
case 11: lahora = lahora + " del mati"; break;
case 12:
case 13:
case 14: lahora = lahora + " del migdia"; break;
case 15:
case 16:
case 17:
case 18: lahora = lahora + " de la tarda"; break;
case 19:
case 20:
case 21:
case 22: lahora = lahora + " del vespre"; break;
case 23:
case 24: lahora = lahora + " de la nit"; break;
}
This case finds out the part of the day we're in (tarda, vespre, etc.) and adds it to the string of the Catalan time.
int numblancs = caracterslcd - (lahora.length());
for (int b=0; b< numblancs; b++)
{
cadenablancs = cadenablancs + " ";
}
lahorafinal = lahora + cadenablancs;
After each minute, when the time changes, we need to clear the screen, because if the string is shorter than the former printed time, the lcd will keep the extra characters. But we can't use the clear() function to clear it because of the flickering problem already mentioned. The solution has been to write everytime an 80-characters string, filling it with blanks at the end, and forcing that way a rewriting of each character of the lcd. So, we calculate the characters we need to add to get 80 characters, and we build the 80-characters string.
//dividim la cadena en trocets de 20 caracters
for(int i=0; i<20;i++) {
cadena1 = cadena1 + (lahorafinal.charAt(i));
}
for(int j=20; j<40;j++)
{
cadena2 = cadena2 + (lahorafinal.charAt(j));
}
for (int l=40;l<60;l++)
{
cadena3 = cadena3 + (lahorafinal.charAt(l));
}
for (int m=60;m<80;m++)
{
cadena4 = cadena4 + (lahorafinal.charAt(m));
}
lcd.setCursor(0,0);
lcd.print(cadena1);
lcd.setCursor(0,1);
lcd.print(cadena2);
lcd.setCursor(0,2);
lcd.print(cadena3);
lcd.setCursor(0,3);
lcd.print(cadena4);
}
}
Finally, we print the time on the lcd, but the characteristics of the lcd makes it more complicated than just a print(). It would be usually expected that, if our string is longer than 20 characters, it is printed next at the second line. But due to the design and circuitry of the lcd, it jumps to the third line in that case. So, this part of the code divides the 80-characters string in four 20-characters strings. Next, we use setCursor() and print() to move the cursor and print the four strings.
Mounting the clock in a case
There are many options available to encase the clock. You can build a case with a material of your choice, you can recycle a box... We mounted ours in a cardboard box, opening holes for the lcd, the buttons and power.
To ease the encasing, we can do several things to simplify the LCD wiring. The lcd has two pins connected to 5V and three connected to GND. These pins can be joined soldering small pieces of wire, as you can see here. The potentiometer can be soldered straight on the LCD, soldering the central pin to pin 3 of the LCD, the left pin to pin 2 (5V) and the right pin to pin 5 (GND).
All the power the LCD needs will come now from pins 15 and 16.
The small breadboard will be useful to connect power wires for the lcd and the buttons, connecting to the breadboard a 5V pin and a GND pin of Arduino. This kind of breadboard usually includes an adhesive at the bottom that will be a help to fix it to Arduino.
Take into account that we made all this because it was the easiest way to mount the clock in our box. Depending on the case or box you use, these instructions may or may not be useful for you.
Contact
If you want to make a comment about the project or if you need help building your clock, or if have any idea to improve it, please get in touch with us: support <---at---> kawasemicorp.com

© 2011 Kawasemi Corp.