Saturday, March 26, 2016

GPS-synchronized Mondrian clock

The challenge was to add GPS to this "basic LED matrix clock".

Since I don't see the point of a GPS clock that does not show seconds, I had to figure out how to fit 6 digits on the 8x16 LED matrix. One way to do it is this:

as used by the "Matrix Clock V1.0". Kind of hard to distinguish between 0 and 8 though.

Another way is based on MixiClock, where 4 digits are crammed in a 8x8 (tri-color) matrix. (This was more than 4 years ago. Incredible how little progress I made since.)

As for the name, I settled for "Mondrian" because Kandinsky was already taken :)

The hours are shown in red, the minutes in green and the seconds in orange. After power up, the seconds blink until the GPS time is received (less than 5 minutes in my house, more than 3 meters away from the nearest window). Only the minutes and the seconds are synchronized (but not the hours).

The Mondrian clock is made of 2 boards: the wsduino with the GPS Bee plugged in (and the antenna affixed on the back with double sided tape, as shown in the next photo), and the LED-mini-display shield.

The GPS Bee module is connected on the hardware serial port (there are only a couple of pins left available, D2 and D17).
The clock has two buttons (on the LED matrix shield) used for incrementing the hours and the minutes respectively. The GPS synchronization occurs every 10 hours. That should be more than enough, considering that the highly accurate DS3231 on the wsduino board is responsible for timekeeping.
The clock, powered by 5V, consumes less than 200mA.
The sketch can be found here (compiles on Arduino IDE 1.0.6 and has dependencies on TinyGPS and DS1307 libraries).

Saturday, March 19, 2016

A recap of Wise Clock 4 features

The list of code changes and new features at the top of the source files (see WiseClock.cpp, for example) grows longer and longer. I thought of getting this list out in the open, for the people who are not particularly interested in the C++ code or just don't want to look at the source code (or release notes file for that matter, not updated in a long while though) to find out what Wise Clock 4 can do.

1. First and foremost, Wise Clock 4 displays quotes retrieved from text file(s) stored on SD card, with both  FAT16 or FAT32 file systems being supported. This piece of functionality is still the core of the software.

2. Secondly, Wise Clock 4 displays the time retrieved from DS3231 extremely accurate real time clock chip. (These first two features inspired its name: "wise" and "clock" :)

3. The display is tri-color (red, green, orange) LED matrix with a minimum resolution of 16x32 and a maximum of 16x128. Currently, the resolution is hard-coded, meaning that the software is compiled and built for a specific display and it cannot be changed dynamically (by the user, from buttons or configuration settings, although this may be a future enhancement);

4. Time can be shown in:
  • various display modes:
    • Pacman;
    • Pong;
    • Words;
    • TIX;
    • Unix;
    • binary;
    • BIG;
    • Quotes (time displayed along with scrolling text);
    • "close enough" (approximate), showing passed minutes pie-chart;
    • dual time-zone analog display, with hour and minute hands "rotating" inside round face;
  • most formats:
    • just hours and minutes or
    • hours, minutes and seconds, or
    • even tenths of a second for chronometer;
    • 12 or 24 (military) hour format;
  • different sizes:
    • medium, on the bottom half of the screen;
    • big, scrolling across or rolling digits or
    • tiny, when more digits need to fit on the screen.
5. Beside clock, Wise Clock 4's other time-related functions:
  • alarm;
  • stop watch (chronometer);
  • count down timer;
  • project time clock;
  • GPS-based time synchronization (requires GPSBee module to be installed);
  • NTP-based time synchronization (requires Esp8266 Wee/WiFly module to be installed);
  • scoreboard (as a separate, independent, standalone, software);
  • time lived since birth;
  • chime every half hour;
  • show night and day on a global map (requires map overlay, see this post);
  • show the current time at up to ten different cities, cycling through each city;
  • show messages predefined for specific days (e.g. birthday/holiday wishes, event reminders etc.) recorded in message.txt file on SD card;
  • automatic, configurable (in SD file) "night" mode for display (saves power and LEDs, produces less light at night);
  • automatic and configurable (SD file) Daylight Savings Time;
6. Wise Clock 4 functions not related to time:
7. Other Wise Clock 4 features:
  • manual (press "Plus" button) or auto dimming (with LDR) of the display brightness;
  • manual (press "Set" button) adjustment of the speed for text-scrolling;
  • remote control using 4-button keyfob;
  • uses different colors to indicate how close the alarm is to go off (red two hours before, orange before that);
  • define and display quotes, partially or entirely, in different colors;
  • select a mode ("app") to start at power on;
  • select one of the many different fonts;
  • post sensor data to monitoring web site;
  • display info retrieved from the web (through WiFi), e.g. stock quotes, weather data etc.
  • can be used as electronic commercial signage for advertisement, news, announcements etc. due to its high visibility/readability and ease to set up and configure;
  • can be used in competitions or sporting events, to display timing and/or info, visible from both sides of the finish line (see Kandisky clock).
8. A vast tree of menu items, allowing the user to access its many functions easily, to choose the time-display mode, to set values (e.g. time) and/or parameters (e.g. amount of time for a countdown) and to save settings (e.g. the app running at power on).

The menu is split into two loops: one for settings, the other one for apps.
  • Settings menu items are: APPS, ALARM, AL+/AL-, DATE+/DATE-, REMI+/REMI-, TEMP+/TEMP-, MESG+/MESG-, CHME+/CHME-, FONT+/FONT-, CELS/FAHR, 24H+/24H-, DST+/DST-, TIME, Y M D, DAY, NGHT+/-, LOG+/-, ANIM+/-, PWRON.
Selecting the "SETUP" menu entry will take you to the Settings menu loop, selecting the "APPS" menu entry will take you to the Apps menu loop.

Each app can use the buttons "Plus" and "Set", with button "Menu" always being used to trigger the display of the menu.
The buttons "Set" and "Plus" have different functions for different apps. For example, in SCORE, one of the simplest apps, each button increments the score for one side/player; in CHRON, "Set" moves from one function to the other, with "Plus" triggering that function (e.g. increment the number of hours).
Menu navigation is intuitive and easy to understand after playing with the buttons a little bit.

9. From the source code perspective, the Wise Clock 4 software is modular, flexible and extensible (see this mod, for example), based on a framework (implemented in WiseClock.cpp) and multiple "applications" (files named App*.cpp) that can be enabled/disabled (included in/excluded from the software) at build-time by macro definitions (e.g. #define) and activated/executed at run time.

Add light sensor to Wise Clock 4

This is long overdue.
As we know, the display brightness on Wise Clock 4 can be changed between 5 levels, by pressing the "Plus" button. To adjust the brightness automatically, based on the light conditions, we need to add a light-sensitive sensor of some sort, and the most common is the LDR (light-dependent resistor).
Any of the countless articles and tutorials on Arduino + LDR will teach how to connect the LDR to an analog pin, using a voltage divider. For Wise Clock 4, the LDR is connected between A0 (pin 40 of the processor) and ground, with a 10k resistor between A0 and Vcc, as shown below:

  GND|----[ LDR ]---A0---[10k resistor]----+Vcc

The automatic brightness adjustment is enabled in software with this macro (in file UserConf.h):

// use an LDR (connected to A0) to automatically adjust
// (every 5 seconds) screen brightness to ambient light;

and implemented in this new function:

void WiseClock::checkBrightness()
  // adjust brightness every 5 seconds;
  if (millis() - lastCheck > 5000)
    int ldrValue = analogRead(0); // A0
    byte brightLevel = map(ldrValue, 0, 1023, MAX_BRIGHTNESS, 0);
    if (nBrightness != brightLevel)
      nBrightness = brightLevel;
    lastCheck = millis();

called from the main loop (TheClock.ino):

void loop()
unsigned long ms = millis();


if ((long)(ms - wiseClock.nextRun) >= 0)


It really doesn't get much simpler than this.

I also considered other hardware solutions (and actually bought the parts):
- I2C light sensor TSL2561
but I did not follow through after I saw how effective (and so much cheaper) the LDR is.