What is this code good for?

This code provides the functionality of a timer switch (Zeitschaltuhr) remotely managed via WiFi that can be set to switch devices on and off at

  • daily intervals,
  • hourly intervals, or
  • intervals repeating every minute.

It provides action feedback via MQTT and thus lends itself for the integration with the IoT.

Here is the code.

What hardware is required?

ZsuTT is known to work with the

What can we do with it?

ZsuTT provides functionality similar to a mechanical timer switch, but may be managed and monitored remotely over WiFi. To enter commands we may use the Arduino Wifi console or any other utility providing simple TCP access on port 23. A good utility to use for this purpose is netcat, but there are others. Execution feedback is given via MQTT topics whose names are parametrized and thus can be changed to suit.

In order to use MQTT it is necessary to have an MQTT broker running where the Arduino can reach it. On the Arduino MQTT must be activated via the Connectivity Panel (same connection as the console). The Arduino also needs to be told where to find the broker and on which port to reach it. A broker that works well with ZsuTT is mosquitto, but there may be others.

If no MQTT broker is available, the program can be used without. However in that case the verbose option should be activated, thus ensuring that action feedback is provided to the Console instead.

Special challenges addressed

The Arduino UNO Wifi does not have a Real Time Clock (RTC). Yet the millisecond count is reasonably accurate. While there are deviations, they appear to be consistent within each specific hardware used. The command adjust may be used to indicate by how many seconds the millisecond count needs to be adjusted for each 24 hour period so as to keep the internal pseudo clock reasonably aligned with actual time.

Since the Arduino UNO Wifi does not have any awareness of time, actual time needs to be set after each restart. The command settime HH:MM:SS allows us to do so. This command may either be used manually via the console by any utility accessing port 23 of the Arduino device, or it may be used to reset the time programmatically at regular intervals, e. g. using the crontab facility of any *nix device.

Aren't there timers that are commercially available?

Most timers that I could find are designed to handle household power. There are a few timers on the market that can handle 12V DC. However these are hard to find and quite expensive. None that I could find were able to handle a mix of AC, DC and different voltages. And they also could not be controlled remotely.

The Hardware and Software proposed here can do both.

Isn't there already code that can do this?

Probably yes, but, alas, I don't think it was published ☹. At least, if it was, I didn't find it. There is a most useful library TimeAlarms.h by Paul Stoffregen. In fact, for starters, that is what I used. But then I realized, that, being interrupt driven (i.e. by alarm) it would not set a correct state (i.e. on or off) if engaged past the time the alarm had been set to, or when the settings were changed. Hence I decided to write my own code implementing true state sensitivity: if the time is reset to a time when the timer is supposed to be on, then the timer will in fact be on.

How is this code currently being used?

The code is used to control my hydroponics. Since my plants are alive and well, the code is probably not too buggy.

In an excess of zeal I am resetting the time of my Arduino four times a day. Once a week would probably be sufficient, but crontab commands are cheap and easy to implement, so I couldn't resist. This is what these commands look like.

I am also using crontab to provide a once a day initial load of all parameters. Under normal circumstances this is really quite unnecessary. However in case of a power failure or a forced system restart I can be assured that the parameters are reset to the correct values at least once a day. Alternatively I could use the initialization option built in to the code (see: initialLoad() in the code). However I found this not to be flexible enough for my purposes, as I would need to recompile the program after each change. This is what my initial load script looks like .

My Arduino controls one set of 220V AC lights, one set of 12 V DC light and a 12V nutrient pump (currently still driven through a 220V AC converter but soon to be changed to low DC voltage).

What are the commands that can be used to control this program?

Valid commands are listed in the comments and they are also displayed on the console in response to an arbitrary data entry. Here is an summary:

  • showtime No parameters: returns actual system time of device. By default system time is set to midnight at startup and increased from there

  • settime HH:MM:SS Parameters must have indicated format. Sets system time to desired value. Returns ack or ERR. Lends itself to automated time sync via netcat or similar

  • adjust ±n Positive number accelerates, negative number slows down SW clock by n seconds within 24 hours. This command calibrates hardware to clock speed, as the Arduino UNO does not have a reliable time provider built in

  • #on&off HH:MM HH:MM where # is the number of the relay addressed (1...4). Normally open contact (NOC) is closed during the times indicated (from... to). Multiple entries for the same relay and overlapping times are permissible. NOC closed (=relay on) settings prevail

  • #everyh MM:SS MM:SS where # is the number of the relay addressed (1...4). This command repeats EVERY HOUR. NOC is closed during the indicated period every hour. Multiple entries and overlapping times are possible. NOC closed (=relay on) settings prevail

  • #everym SS SS where # is the number of the relay addressed (1...4). This command repeats EVERY MINUTE. NOC is closed (=relay ON) during the indicated period every minute. Multiple entries and overlapping times are possible. NOC closed (=relay on) settings prevail

  • #manon where # is the number of the relay addressed (1...4). Manually overrides NOC settings to closed (=relay ON), just like the physical "on" button on a mechanical timer

  • #manoff where # is the number of the relay addressed (1...4). Counters #manon setting and reverts to timer setting (not necessarily to "off")

  • #name assigns meaningful name to relay number #; max 8 chars; this name used as MQ topic; if no name is given, relay number is used

  • clearall removes all entries from the timer setting teable. All timer settings then need to be reentered

  • showall Shows all timer settings, including manual overrides and time adjustments (calibrations)

  • remove n Removes entry <n> from the timer settings table as visible via showall command

  • verbose [on|off] allows to choose the amount of feedback provided by the application. If set to off, messages regarding relay change and time adjustment events will be suppressed. Default is off.

Known bugs and issues

There have been times when a command was issued to port 23, but the Arduino appeared to receive only random characters (i.e. white noise). I found that in those cases it is sufficient to perform a Wifi reboot (not a full µC reset) via the Debug Log Window of the Console connection.

Comments and Observations

Send to mýið or post right here.