Tuesday, April 26, 2016

From the mailbox

AlexP managed to port the Wise Clock 4 code to Arduino Mega2560 (shared here, thanks Alex!). He made this video demonstrating it in action:

Today I had a great day! I did it! I soldered a development board for my Mega2560. A little corrected code and ... voila!  Wiring diagram:
  • rtc sqw (1hz) - pin 2
  • menu key - pin 3
  • set key - pin 4
  • plus key - pin 5
  • speaker - pin 6
  • speaker - pin 7
  • HT1632_WRCLK - pin 10
  • HT1632_CS - pin 11
  • HT1632_DATA - pin 12
  • HT1632_CLK - pin 13
  • rtc sda - pin 20
  • rtc scl - pin 21
(SD while not tested, but I think it works)
  • sd miso - pin 50
  • sd mosi - pin 51
  • sd sck - pin 52
  • sd cs - pin 53

NelsonC built his own hand-wired version of WiFiChron and it looks awesome:

MikeM sent in (thanks Mike!) his latest WiFiChron code (available here).
The enclosed zip file compiles under Arduino 1.6.8, though it generates a warning I haven't figured out how to eliminate.
Ray ran into a problem with data overruns. When data in an RSS feed was split between multiple packets, sometimes the last few bytes of a packet were dropped from the RSS buffer. I didn't see that problem with my clock when I was developing the code, nor did I see it on the WiseClock4. I've re-built the RSS state machine to be more CPU efficient, and now the packets are processed without drops. We probably don't need to change the RSS code on the WiseClock4 as it runs at 16 MHz and not 8 MHz like the WiFiChron.
I also changed the PROGMEM statements to fit the 1.6.8 standard.

And finally, I got the PCBs for the 1284-equipped versions of WiFiChron and bGeigie nano.
For both I relied on internal (software-driven) pull-ups (basically I eliminated the pull-up resistors), without checking first if that would work. Unfortunately, the current sanguino library does not implement correctly the function pinMode(x,INPUT_PULLUP). So I had to resort to resistors soldered on the back of the board. That, plus missing a necessary decoupling capacitor, plus also missing some connections on the bGeigie board, made for a "fun-filled", but in the end successful, testing. More on these in a future post.

Sunday, April 3, 2016

Wise Clock 4 software for Arduino 1.6.8

Scott H. put the time and the effort to port the Wise Clock 4 code (also the HDSP-Proverb and WiFiChron code) to Arduino 1.6.8 (the latest, but maybe not the greatest). This is a big endeavor, which I did not plan to pursue any time soon. Now, thanks to Scott, here we have it. I compiled it and uploaded it myself, on Windows (he did it on Mac).

The Wise Clock 4 files are all in the same "TheClock" folder, directly under "libraries", as shown in the following screenshot.

But before uploading to ATmega1284, this section needs to be inserted in boards.txt (*):

atmega1284.name=Sanguino W/ ATmega1284p 16mhz

The two highlighted lines are new for 1.6.8: "upload.tool" and "build.board" (which has a default value though).

Next, as specified in the line "atmega1284.build.core=sanguino", we need to create the folder "sanguino", containing the core files. Folder structure should look like this:

Note that a few sanguino core files that worked in Arduino 1.0.6 need to be modified to compile on 1.6.8. Like the Wise Clock 4 code itself, most of these changes are related to the PROGMEM definition, which now requires every progmem variable to be constant. The modified files are WString.* and Print.*, copies of the arduino core files.

Talking about sanguino core files, which served pretty well so far, it is worth mentioning that the current implementation for pinMode(pin, INPUT_PULLUP) (in file wiring_digital.c) is not working. Until I find a software solution, I will still need to use pull up resistors.

(*) There is a more "user friendly" way to add a new board, that involves downloading packages from a specified URL, but I found the learning curve for this method too steep (or, to say it differently, I was too lazy).

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.