J Koger
Created March 17, 2016 © GPL3+

Binary O-Watch

A binary clock on the O-Watch. Displays seconds, minutes, hours, weekday, day, month as a stack of horizontal binary on/off counters.

BeginnerProtip1 hour113
Binary O-Watch

Things used in this project

Hardware components

O Watch Base Kit
O Watch Base Kit
×1

Story

Read more

Code

simple_binary_watch.ino

Arduino
This sketch helps the O-Watch show the time in its own native language of binary.
/*
 * Simple Binary Watch
 *
 * Displays the time and date as a stack of horizontal binary digits, with the 'on' bits represented by a 'lit' box and the 'off' bits
 * represented by an unlit box.
 * 
 * Each row has an identifier to the left (S for seconds, M for minutes, H for hours, W for weekday, D for day, M for month, Y for year) and
 * the decimal numbers for the row's value (or 2-character weekday representation).
 * 
 * Each row has it's own color (red for seconds, pink for minutes, orange for hours, yellow for weekdays, green for days, sky blue for
 * months, and blue for years).
 * 
 * The values are shown as true binary numbers (not one binary value per decimal digit). 6 boxes for year, 4 for month, 5 for day,
 * 4 for hour, 6 for minutes, 6 for seconds. But if we draw each row at the minimum number of boxes, then they look raggedy
 * and the binary digits don't line up. So we'll draw 6 boxes for each of them.
 * 
 * Because year is limited to 6 binary boxes, (years since 2000), this watch will no longer work in 2032.
 * 
 * To keep things simple, the boxes will be drawn as characters (spaces with the background color set to the row's color). Thus everything
 * can be drawn as characters.
 *
 * 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
 * 
 * Modified into a binary watch by J Koger 17 March 2016.
 * 
*/

#include <TinyScreen.h> //include TinyScreen library
#include <TimeLib.h> //include the Arduino Time 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 boxes that are off (binary digit 0) and
// for boxes that are lit (binary digit 1) and characters, by row.
#define BOX_OFF         0B01001001    // Dark gray
#define SECONDS_COLOR   TS_8b_Red
#define MINUTES_COLOR   0B10010011    // pink
#define HOURS_COLOR     0B00010111    // orange
#define WEEKDAY_COLOR   TS_8b_Yellow
#define DAYS_COLOR      TS_8b_Green
#define MONTHS_COLOR    0B11001110    // sky blue
#define YEARS_COLOR     TS_8b_Blue

// Comment out this #define to remove the horizontal divider lines.
#define DIVIDER_COLOR   TS_8b_Gray

// Number of boxes (binary digits) needed to display this value
#define SECONDS_BOXES   6
#define MINUTES_BOXES   6
#define HOURS_BOXES     5
#define WEEKDAY_BOXES   3
#define DAYS_BOXES      5
#define MONTHS_BOXES    4
#define YEARS_BOXES     6
// To make everything look less raggedy, and have the binary digits of
// the rows line up with each other, just draw the same number of boxes
// for each.
#define MAX_BOXES       6

// Vertical offset of each row
#define SECONDS_Y      0
#define MINUTES_Y      9
#define HOURS_Y        18
#define WEEKDAY_Y      27
#define DAYS_Y         36
#define MONTHS_Y       45
#define YEARS_Y        54

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(BOX_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     drawBinaryBoxes(int xStart, int yStart, int value, int numBoxes, uint8_t color)
{
  int   xPos = xStart, thisBit;

  numBoxes = MAX_BOXES;     // This makes all of the rows display the same number of boxes
                            // (binary digits). It's perhaps more confusing but looks less raggedy.

  thisBit = 1 << (numBoxes - 1);
  
  for (int i = numBoxes; i > 0; i--)
  {
    display.setCursor(xPos, yStart);
    if (thisBit & value)
      display.fontColor(color, color);
    else
            display.fontColor(BOX_OFF, BOX_OFF);
    display.print(" ");
    xPos += 8;
    thisBit >>= 1;
  }
  
}


void displayTime()
{

  display.on();                               //Turns TinyScreen display on
  
  for (int i = 1; i < 30; i++) // Display for 30*1000 milliseconds (30 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.
    months = rtc.getMonth();
    days = rtc.getDay();
    years = rtc.getYear();
    hours = rtc.getHours();
    minutes = rtc.getMinutes();
    seconds = rtc.getSeconds();
    
    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

    // Seconds row
    display.setCursor(0, SECONDS_Y);
    display.fontColor(SECONDS_COLOR, TS_8b_Black);
    display.print("S");
    display.setCursor(16, SECONDS_Y);
    display.print(seconds / 10);
    display.setCursor(24, SECONDS_Y);
    display.print(seconds % 10);
    drawBinaryBoxes(40, SECONDS_Y, seconds, SECONDS_BOXES, SECONDS_COLOR);

    // Minutes row
    display.setCursor(0, MINUTES_Y);
    display.fontColor(MINUTES_COLOR, TS_8b_Black);
    display.print("M");
    display.setCursor(16, MINUTES_Y);
    display.print(minutes / 10);
    display.setCursor(24, MINUTES_Y);
    display.print(minutes % 10);
    drawBinaryBoxes(40, MINUTES_Y, minutes, MINUTES_BOXES, MINUTES_COLOR);

    // Hours row
    display.setCursor(0, HOURS_Y);
    display.fontColor(HOURS_COLOR, TS_8b_Black);
    display.print("H");
    display.setCursor(16, HOURS_Y);
    display.print(hours / 10);
    display.setCursor(24, HOURS_Y);
    display.print(hours % 10);
    drawBinaryBoxes(40, HOURS_Y, hours, HOURS_BOXES, HOURS_COLOR);

    // Weekday row
    setTime(hours,minutes,seconds,days,months,2000 +  years);    //values in the order hr,min,sec,day,month,year
    char  tmp[2], wkday[16];
    int   wkdayNum = 0;
    strcpy(wkday, dayStr(weekday()));
    if (wkday[0] == 'S')
    {
      if (wkday[1] == 'u')
        wkdayNum = 1;     // Sunday
      else
        wkdayNum = 7;     // Saturday
    }
    else if (wkday[0] == 'M')
    {
      wkdayNum = 2;       // Monday
    }
    else if (wkday[0] == 'T')
    {
      if (wkday[1] == 'u')
          wkdayNum = 3;   // Tuesday
      else
          wkdayNum = 5;   // Thursday
    }
    else if (wkday[0] == 'W')
      wkdayNum = 4;       // Wednesday
    else
      wkdayNum = 6;       // Friday
    display.setCursor(0, WEEKDAY_Y);
    display.fontColor(WEEKDAY_COLOR, TS_8b_Black);
    display.print("W");
    display.setCursor(16, WEEKDAY_Y);
    tmp[0] = wkday[0];
    tmp[1] = '\0';
    display.print(tmp);
    display.setCursor(24, WEEKDAY_Y);
    tmp[0] = wkday[1];
    if (tmp[0] >= 'a')
      tmp[0] = tmp[0] - 'a' + 'A';
    display.print(tmp);
    drawBinaryBoxes(40, WEEKDAY_Y, wkdayNum, WEEKDAY_BOXES, WEEKDAY_COLOR);

    // Days row
    display.setCursor(0, DAYS_Y);
    display.fontColor(DAYS_COLOR, TS_8b_Black);
    display.print("D");
    display.setCursor(16, DAYS_Y);
    display.print(days / 10);
    display.setCursor(24, DAYS_Y);
    display.print(days % 10);
    drawBinaryBoxes(40, DAYS_Y, days, DAYS_BOXES, DAYS_COLOR);

    // Months row
    display.setCursor(0, MONTHS_Y);
    display.fontColor(MONTHS_COLOR, TS_8b_Black);
    display.print("M");
    display.setCursor(16, MONTHS_Y);
    display.print(months / 10);
    display.setCursor(24, MONTHS_Y);
    display.print(months % 10);
    drawBinaryBoxes(40, MONTHS_Y, months, MONTHS_BOXES, MONTHS_COLOR);

    // Years row
    display.setCursor(0, YEARS_Y);
    display.fontColor(YEARS_COLOR, TS_8b_Black);
    display.print("Y");
    display.setCursor(16, YEARS_Y);
    display.print(years / 10);
    display.setCursor(24, YEARS_Y);
    display.print(years % 10);
    drawBinaryBoxes(40, YEARS_Y, years, YEARS_BOXES, YEARS_COLOR);
    
#ifdef DIVIDER_COLOR
    display.drawLine(0, MINUTES_Y - 1, 95, MINUTES_Y - 1, DIVIDER_COLOR);
    display.drawLine(0, HOURS_Y - 1, 95, HOURS_Y - 1, DIVIDER_COLOR); 
    display.drawLine(0, WEEKDAY_Y - 1, 95, WEEKDAY_Y - 1, DIVIDER_COLOR); 
    display.drawLine(0, DAYS_Y - 1, 95, DAYS_Y - 1, DIVIDER_COLOR); 
    display.drawLine(0, MONTHS_Y - 1, 95, MONTHS_Y - 1, DIVIDER_COLOR);
    display.drawLine(0, YEARS_Y - 1, 95, YEARS_Y - 1, DIVIDER_COLOR);
#endif

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

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


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

Credits

J Koger

J Koger

10 projects • 4 followers

Comments