A clock comprised of 60 NeoPixel LEDs. Shows the time, but can also show programmable patterns (as alerts) and temporal information (such as expected rainfall for the coming hour). Schematics and building instructions included.
Home page is https://github.com/cwi-dis/iotsaNeoClock. This software is licensed under the MIT license by the CWI DIS group, http://www.dis.cwi.nl.
- Arduino IDE, v1.6 or later.
- The iotsa framework, download from https://github.com/cwi-dis/iotsa.
- The new LiquidCrystal library, download from https://bitbucket.org/fmalpartida/new-liquidcrystal.
- The Adafruit NeoPixel library.
- a iotsa board (or another esp8266-based board).
- A strip of 60 NeoPixels.
- Optionally an LDR to auto-adjust the clock brightness.
Construction of the iotsa board is very simple: the NeoPixel strip data in should be connected to GPIO 14 and power and ground should be connected to 5V and GND, respectively.
If you want light adaptation you also connect an LDR (light dependent resistor) between AIN and 3V3 and a resistor of around 10Kohm between AIN and GND.
At this point you can test that things work (but you have to mentally group your 60 NeoPixels into 12 groups of 5, with the very first LED being at the top of the clock, and the last LED being the innermost at the 11 o'clock position).
Now you need to cut your NeoPixels into 12 groups of 5, and somehow affix them to a frame. There is a template in extras/pixel-layout.pdf to help you get things spaced correctly. The data in of the 12 o'clock 5-pixel strip goes to the iotsa board. The data out of the 12 o'clock 5 pixel strip goes to the data in of the 1 o'clock 5 pixel strip. And so forth. The data out of the 11 o'clock strip is not connected. All the power are connected together (and to 5V) and all the ground are connected together (and to GND), how you do this does not matter. You probably want to tape or glue your wires to the template.
I bought a 5 euro clock with a glass front, ripped all the internals out and glued the NeoPixels to the template, then glued the template to what was left of the clock. Finally I put semi-opaque paper on the inside of the glass and put the clock together again.
If you have the LDR you want to somehow position it so that it catches the incident light on the clock (but not the light from the clock), and that it is not too ugly.
You need to define (or #undef) WITH_BRIGHTNESS depending on whether you want to be able to change the clock brightness over the net (and definitely if you have the LDR for auto-brightness).
If you want different colors for the hands your can adapt the COLOR_SEC, COLOR_MIN and COLOR_HOUR defines (in iotsaNeoClockMod.h). If you want different patterns to show the time you need to modify IotsaNeoClockMod::updateClockFace() in iotsaNeoClockMod.cpp.
The first time the board boots it creates a Wifi network with a name similar to config-iotsa1234. Connect a device to that network and visit http://192.168.4.1. Configure your device name (using the name neoclock is suggested), WiFi name and password, and after reboot the iotsa board should connect to your network and be visible as http://neoclock.local.
Visit http://neoclock.local/ntpconfig to configure the NTP (Network Time Protocol) server to use (but the default pool.ntp.org will usually work) and your timezone. After about half a minute the clock should have a fix and start displaying the right time. The time is also shown on the ntpconfig page and on the clock homepage.
You can change the brightness of the clock at http://neoclock.local/brightness (or, as JSON, at http://neoclock.local/api/brightness). You can either set a single brightness value (0.0 to 1.0), or set Adapt to ambient light and set a minimum and maximum brightness.
You can set the LED rotation offset (the clock position where LED 0 actually sits -- needed on the first two clocks built, which have LED 0 at the 1 o'clock position) at http://neoclock.local/neoclock (or, as JSON, at http://neoclock.local/api/neoclock).
The clock can display alerts, which are sequences of patterns, there are sample patterns in data/data. Each line consists of 181 numbers: a duration (in milliseconds) and 60 R, G and B values for each of the pixels. Triggering an alert will simply show the lines in order.
Alerts share the device's generic /upload file store with arbitrary other files, so alert pattern files must be named alert-<name>, e.g. alert-Red. Upload via http://neoclock.local/upload, see what's available at http://neoclock.local/neoclock, which has a button per alert (or, as JSON, at http://neoclock.local/api/neoclock, which also reports the currently-playing alert, if any), then trigger with the name without the alert- prefix, e.g. http://neoclock.local/alert?alert=Red. Stop a running alert early with http://neoclock.local/alert?stop=1. The same trigger/stop can be done as JSON: PUT /api/neoclock {"alert": "Red"} / {"alert": ""}.
Alerts are intended to be shown programmatically when something interesting has happened, such as a doorbell being pushed, or a facebook mention, or whatever you can think of. Igor is a good way of connecting triggers to alerts.
The clock can also display status information, which is intended to be longer-lived. Think of things like "the garden door is open" or "the temperature in the freezer is above -20 C". There are two types of status indicators, each with its own URL:
- http://neoclock.local/status -- the inner ring, used for main status information. All 12 LEDs show the same color and intensity.
- http://neoclock.local/temporal -- the outer ring, used for temporal status information, information for the coming hour. The LEDs all have the same color, but the intensity can vary. This can be used to get a quick visual indication of things like the expected rainfall in the coming hour.
Some example URLs to trigger status indicators:
http://neoclock.local/status?color=0x00ff00
Sets the inner ring to bright green.
http://neoclock.local/status?color=0x006600&timeout=60
Sets the inner ring to medium green for 60 seconds, then revert to normal.
http://neoclock.local/status?color=0&nextColor=0xff0000&timeout=300
Sets the inner ring to normal (unlit) for 5 minutes, then go to a very bright red. This can be used as a watchdog: by re-issuing this command within those 5 minutes the red will never show up. Unless the agent that is responsible for contacting the URL is too late.
http://neoclock.local/temporal?color=0xccffff&factors=1.0,0.0,0.0,0.5&timeout=300
Sets the outer ring with timed information. Where the minute hand is pointing is set to 100% lightish blue, 15 minutes into the future to that color with 50% intensity. After 5 minutes the outer ring will revert to normal.
The factors are perceived intensities: the LEDs get factor^gamma, because LEDs are linear and eyes aren't. The gamma (Temporal gamma on http://neoclock.local/neoclock, default 2.2) can be tuned there; 1.0 shows the factors as they are.
The same as JSON, with the colors as numbers (JSON has no hexadecimal: 0x00ff00 is 65280): PUT /api/neoclock {"status": {"color": 65280, "nextColor": 0, "timeout": 60}} and PUT /api/neoclock {"temporal": {"color": 13434879, "factors": [1.0, 0.0, 0.0, 0.5], "timeout": 300}}.
Until you add a user (at http://neoclock.local/users, in configuration mode), everyone on the network can do everything. With users, alerts, the status rings and the brightness stay open to everyone; the LED rotation offset and the rain forecast settings need the right config (and reading the forecast's latitude and longitude too, since they give away where the clock hangs); adapting to ambient light needs lighttuning.
Some NeoClocks have a built-in rain forecast feature: they periodically fetch the precipitation forecast for a configured location from buienradar.nl (Netherlands only) and use it to drive the outer ring automatically -- no external process needed to push /temporal updates.
If your clock has this feature, configure it at http://neoclock.local/buienradar (or, as JSON, at http://neoclock.local/api/buienradar): fill in your latitude and longitude -- the easiest way to find them is to right-click your location on Google Maps and copy the two numbers shown from the top of the menu that pops up (not "Copy link", which gives you something else entirely) -- and the outer ring will start showing the forecast for the coming hour automatically. There's also an Enabled switch on that page, in case you ever want to turn the feature off. The same page shows the last poll: per 5 minutes of the coming hour the time, buienradar's rain level and the factor the ring shows it with. Off at (default 40) and Full at (default 144, about 12 mm/h) set which levels show nothing and which show at full brightness; a change shows on the ring right away, without a new poll.
If your clock doesn't have this feature, you can still get the same effect yourself: have some external process fetch a forecast periodically and push it to /temporal, as shown above.