Things used in this project

Hardware components:
Img 9622 copy 300x420
O Watch Base Kit
×1

Code

simple_word_watch.inoArduino
Code to display a mini Word Clock using an 8 x 8 letter grid on the O-Watch
/*
 * Simple Word Watch
 *
 * Demonstrates the use of the Arduino Zero Real-Time-Clock (RTC) library to make a simple 8 x 8 'Word Clock'
 * display of the current hours and minutes.
 * 
 * This type of display only shows the current minutes (to within 5 minutes) and current hour, using a grid of 8 x 8 letters. The letters
 * needed to display the current time (for example, 'HALF PAST TEN') are 'lit up' (drawn with a bright color like yellow), and the
 * unnneeded letters are 'turned off' (drawn with a dull color like gray).
 * 
 * Since the TinyScreen is 64 pixels high, the 8 x 8 grid of letters will take up most of the display, since the
 * smallest font provided on the O-Watch is 7 pixels tall (plus 1 pixel gap between rows): (7 + 1) * 8 = 64 pixels needed 
 * to display 8 rows. That doesn't leave any room for the date, day of the week, or seconds. It's also a bit hard to read
 * since the letters are pretty, well, tiny.
 *
 * Uses Arduino Zero RTC library https://www.arduino.cc/en/Reference/RTC
 * Maintained by Arturo Guadalupi https://github.com/arduino-libraries/RTCZero
 *
 * This code is for the TinyScreen+ board by TinyCircuits used by O Watch http://tiny-circuits.com 
 *
 * This example is based on the Simple Watch code created by O Watch on 6 March 2016 http://theowatch.com
 * Modified to use RTC, to set the display brightness based on time of day, and to use __DATE__ and __TIME__
 * to preset the watch's date and time by J Koger 13 March 2016
 * 
 * Modified to display time as an 8 x 8 character 'Micro Word Clock' by J Koger 16 March 2016, using a tweaked
 * version of the code from Daniel Rojas' https://github.com/formatc1702/Micro-Word-Clock
 * 
*/

#include <TinyScreen.h> //include TinyScreen library
#include <RTCZero.h> //include the Arduino Zero's Real Time Clock library
#include <stdio.h>  // include the C++ standard IO library

/* Create an rtc object */
RTCZero rtc;

// We'll dynamically change these values to set the current initial time
// No need to change them here.
byte seconds = 0;
byte minutes = 45;
byte hours = 9;

// We'll dynamically change these values to set the current initial date
// The preset values are only examples.
byte days = 13;
byte months = 3;
byte years = 16;

int brightness = 15; // We'll set it, 3 - 15 based on time of day

TinyScreen display = TinyScreen(TinyScreenPlus); //Create the TinyScreen object

// Our colors for letters that are off and
// for letters that are lit.
#define LETTER_OFF  TS_8b_Gray
#define LETTER_LIT  TS_8b_Yellow

// This is the 8 x 8 grid of letters used to display the current time.
// We'll only 'light up' the letters needed to show the current
// time, and draw all the other ones in a 'dark' color.

char wordClock[8][9] = { 
 "HATWENTY",
 "FIFVTEEN",
 "LF*PASTO",
 "NINEIGHT",
 "ONETHREE",
 "TWELEVEN",
 "FOURFIVE",
 "SIXSEVEN"
};

// This is an array used to determine which letters should be 'lit'
// to display the current minutes (or, really, the current 5-minute
// segment. There is one grid for each segment, and since there are 12
// 5-minute segments in an hour, there are 12 grids in the array.
//
// For example, if the current time is 10:06, then it is roughly
// 5 minutes past 10. So, we'll want the letters F I V E and P A S T
// to be lit. Look in the second grid for 'five past'; it has 1's for
// each of the wanted letters and 0's for all of the unused letters.
//
// The lit/unlit letter indicators are stored as bits within bytes
// (a byte holds 8 bits). We could use a byte for each letter, but
// bits only need 1/8 the space. And it'll give us an excuse to have
// some fun with bit comparisons later on!

unsigned char letterMinutes[12][8] ={
  { // o'clock
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  , { // five past
    0B00000000,
    0B11010100,
    0B00011110,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  , { // ten past
    0B00000000,
    0B00001101,
    0B00011110,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // fifteen past
    0B00000000,
    0B11101111,
    0B00011110,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // twenty past
    0B00111111,
    0B00000000,
    0B00011110,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // twentyfive past
    0B00111111,
    0B11010100,
    0B00011110,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // half past
    0B11000000,
    0B00000000,
    0B11011110,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // twentyfive to
    0B00111111,
    0B11010100,
    0B00000011,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // twenty to
    0B00111111,
    0B00000000,
    0B00000011,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // fifteen to
    0B00000000,
    0B11101111,
    0B00000011,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // ten to
    0B00000000,
    0B00001101,
    0B00000011,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // five to
    0B00000000,
    0B11010100,
    0B00000011,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
};

// These are the corresponding
// grids to determine which letters
// should be 'lit' to show the
// current hour, 1 grid for each of
// the 12 hours.

unsigned char letterHours[12][8] ={
  { // twelve
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B11110110,
    0B00000000,
    0B00000000
  }
  ,{ // one
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B11100000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // two
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B11000000,
    0B01000000,
    0B00000000
  }
  ,{ // three
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00011111,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // four
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B11110000,
    0B00000000
  }
  ,{ // five
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00001111,
    0B00000000
  }
  ,{ // six
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B11100000
  }
  ,{ // seven
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00011111
  }
  ,{ // eight
    0B00000000,
    0B00000000,
    0B00000000,
    0B00011111,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // nine
    0B00000000,
    0B00000000,
    0B00000000,
    0B11110000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000
  }
  ,{ // ten
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000001,
    0B00000001,
    0B00000001,
    0B00000000,
    0B00000000
  }
  ,{ // eleven
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00000000,
    0B00111111,
    0B00000000,
    0B00000000
  }
};



void setup()
{
  char s_month[5];
  int tmonth, tday, tyear, thour, tminute, tsecond;
  static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

  display.begin();                            //Initializes TinyScreen board
  display.setFlip(1);                         //Flips the TinyScreen rightside up for O Watch
  display.on();                               //Turns TinyScreen display on
  display.fontColor(LETTER_OFF, TS_8b_Black); //Set the font color, font background
  display.setFont(thinPixel7_10ptFontInfo);   //Set the font type


  rtc.begin(); // initialize RTC
  
  // Set the time and date. Change this to your current date and time.
  // setTime(16,19,00,12,3,2016);    //values in the order hr,min,sec,day,month,year

  // Let's be lazy and let the compiler set the current date and time for us.
  // This will be a few seconds off due to the time it takes to compile the
  // .ino file and upload the app. But pretty close.

  // __DATE__ is a C++ preprocessor string with the current date in it.
  // It will look something like 'Mar  13  2016'.
  // So we need to pull those values out and convert the month string to a number.
  sscanf(__DATE__, "%s %d %d", s_month, &tday, &tyear);

  // Similarly, __TIME__ will look something like '09:34:17' so get those numbers.
  sscanf(__TIME__, "%d:%d:%d", &thour, &tminute, &tsecond);

  // Find the position of this month's string inside month_names, do a little
  // pointer subtraction arithmetic to get the offset, and divide the
  // result by 3 since the month names are 3 chars long.
  tmonth = (strstr(month_names, s_month) - month_names) / 3;

  months = tmonth + 1;  // The RTC library expects months to be 1 - 12.
  days = tday;
  years = tyear - 2000; // The RTC library expects years to be from 2000.
  hours = thour;
  minutes = tminute;
  seconds = tsecond;

  rtc.setTime(hours, minutes, seconds);
  rtc.setDate(days, months, years);
}

void displayTime()
{

  display.on();                               //Turns TinyScreen display on
  
  for (int i = 1; i < 10; i++) // Display for 10*1000 milliseconds (5 seconds), update display each second
  {
    // To correctly handle switching date at midnight while the time display is on,
    // update -everything-, not just the seconds.

    // Get the time now since it's used for the brightness calculations.
    // We only need the hours and minutes, since they're all we have
    // room to display.
    hours = rtc.getHours();
    minutes = rtc.getMinutes();

    if (hours <= 12)
      brightness = hours + 3; // 0 hours = 3 brightness, noon = 15
    else if (hours >= 18)
      brightness = (24 - hours) * 2 + 2;  // 23 hours = 4 brightness, 18 hours = 14
    else
      brightness = 15; // full brightness all afternoon
    if (brightness < 3)
      brightness = 3;
    if (brightness > 15)
      brightness = 15;
    display.setBrightness(brightness);                  //Set display brightness 0 - 15

    // Convert 24-hour time into the 12-hour format for
    // the word clock.
    int wordHours, wordMinutes;
    wordHours = hours;
    if (minutes >= 35)   // After half-past the hour, the minute words start referencing the next hour.
      wordHours++;
    wordHours %= 12;    // Now 0 - 11, which is what we need for lookups in the grid.

    // Convert minutes to 5-minute segments
    wordMinutes = minutes / 5;

    // Get the letter-selection grids for the current hour and 5-minute segment.
    unsigned char *thisLetterMinute = letterMinutes[wordMinutes];
    unsigned char *thisLetterHour = letterHours[wordHours];
     
    for (int row = 0; row < 8; row++)   // Walk from the top to the bottom of the 8 x 8 word grid
    {
      // Look out, we're about to do some binary comparisons. As we walk from the left to the right
      // in the word grid, we'll compare the corresponding bit in each byte to determine if the
      // letter in that position should be lit or not. We'll start with the leftmost bit,
      // and shift it right once for each column.
      unsigned char letterColumn = B10000000;
      for (int column = 0; column < 8; column++, letterColumn = letterColumn >> 1)
      {
        // Set the drawing cursor to the position of the current letter.
        display.setCursor((column * 10) + 10, (row * 8));

        // Check to see if the current letter should be off or lit.
        if (((thisLetterMinute[row] & letterColumn) == 0) &&
            ((thisLetterHour[row] & letterColumn) == 0))
          display.fontColor(LETTER_OFF, TS_8b_Black);
        else
          display.fontColor(LETTER_LIT, TS_8b_Black);
          display.print(wordClock[row][column]);
      }
    }

    delay(1000); //display for 1 seconds
  }

  display.off();                               //Turns TinyScreen display off
}

void loop()
{
   if (display.getButtons())
   {
      displayTime();
   }
}

Credits

Thanks to Daniel Rojas.

Replications

Did you replicate this project? Share it!

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Animated Word Clock on the O-Watch
Easy
  • 451
  • 6

A modified version of J Koger's Mini Word Clock for O-Watch, now with an animated digital rain effect.

Getting Started with O Watch
Easy
  • 528
  • 8

Full instructions

Assemble the O Watch, configure the Arduino IDE and load your first program.

2048 Sliding Tile Game for the O Watch
Easy
  • 289
  • 5

Full instructions

This is a sliding tile game for the O Watch based on the simple and addicting game 2048 by Gabriele Cirulli.

Googly Eye O-Watch
Easy
  • 130
  • 3

Protip

Inspired by Mike Mak's Eye Clock, now the O-Watch can show the time with two googly eyes: hours (left eye) and minutes (right eye).

Simple Watch Using RTC
Easy
  • 1,207
  • 4

Full instructions

The O-Watch Simple Watch code tweaked to use the Arduino Zero's built-in RTC, plus a couple other tweaks.

Windows 7/8 Driver Installation for O Watch
Easy
  • 31
  • 1

Full instructions

This is the Windows Device Driver installation applicable only for Windows 7/8. Windows 10 and Mac OSX automatically installs drivers.

Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaFree StoreBlog