We have a design language of sorts. We have some simple code. We have an idea of the functions we wish to implement for our Arduino-based thermostat.
Now let’s use that design language and lay out the rest of our screens.
For any complex UI, and let’s be honest: this is a bit of a complex UI (especially for an Arduino Metro with 32K of program space, 2K of RAM and 1K of EEPROM), there will always be a bit of give-and-take. You will run out of memory and need to make some design compromises. You will realize certain designs, once implemented, simply don’t work. You’ll discover better ways to organize your code to make it all fit.
The designs here are not the first pass at a design, but reflect the results. Sometimes (for example, the original screen I designed for setting the time) just seems clunky, sometimes (like the schedule editing screen) required several goes before I came up with something I was happy with. But rather than discuss the different preliminary designs, we’ll discuss the final results, and discuss how they fit in our design language developed in a prior post.
The final implementation of the code is done and checked in to GitHub. And in theory to actually use this with a real hardware thermostat, I’ve included some notes in GitHub on how you may wish to do this.
The main screen.
Our main screen follows the model we used described in our last post. The only difference is that we draw icons where the back button would go, icons which indicate if the heater is running, if the air conditioner is running or if the fan is running. This is done in part for debugging purposes.
Our design language specifies that this area is reserved for the back button–and normally we would leave this area blank if possible. However, the icons we’re displaying are so visually distinct from the back button, and many mobile apps (from which we borrow the back button concept) have also displayed non-back items in this area, it seems in this case okay to violate our guidelines.
Remember: they’re guidelines, in order to aid in discoverability and consistency. And as long as we don’t violate them (by, for example, displaying an arrow and text that a user could reasonably assume means “go back”), it’s okay in this case to vary from our guidelines.
Temperature Settings Page
If the user taps the “Fan” button, or if they tap one of the temperature range buttons, we drop into the temperature/fan control screen.
Our temperature settings page has no ‘nouns’; the thing we’re controlling is pretty direct: the temperature we heat to, the temperature we cool to, and if the fan is on, running automatically, or if we turn our air conditioner system off.
We use our grouping visual language (the rounded rectangle markers) to indicate to the user what can be tapped, and what things are related. This screen should be pretty easy for the user to quickly figure out how to change the temperature settings and how to turn the system on or off.
The two settings we want to control on our system is to set the current time and set the current date. This screen uses the inverted-L because we have two nouns we can pick from: “Time” and “Date.” We also display the current date and time to the user.
We display the current date and time next to the date/time buttons in order to reinforce to the user that the adjacent buttons are setting the date and the time.
Set Time Page
This is the page we use to set the time.
We provide the user a keypad for which to set the time. In order to give a visual indication to the user that the keypad is all part of the same thing, we use rounded rectangles to mark the corners of the keypad.
Set Date Page
The set date page displays a date picker calendar, which was modeled in code rather than using a drawing tool to lay out the buttons. The reason for doing this is because the grid layout of the calendar varies depending on the number of weeks in a month.
The calendar widget is a familiar one to most users, and we use a different background and foreground color in order to indicate the current date.
Notice that like the set time screen, we don’t use an inverted-L because we have no additional nouns to pick from: the user is directly affecting the current date or the current time.
Our original goal for our thermostat was to create a programmable thermostat. By this we mean that we can set a series of times which the thermostat automatically adjusts itself. For example, we can set a time the thermostat turns the heating temperature down and the cooling temperature up, so the HVAC doesn’t work as hard while the owner is away from home.
We model our system by allowing the user to set up to five separate schedules: one for Spring, one for Summer, one for Fall and one for Winter, with an Energy Saver schedule. Each schedule then contains a separate setting depending on the day of the week–and for each day, the user can set up to four times when the thermostat changes the heating and cooling temperature.
The user can pick between the five schedules from the schedule picker screen:
Our main schedule page allows the user to pick the schedule the thermostat is following. We also place a button in the lower left to allow the user to edit the screens.
Note that this violates our notion about using nouns in the left column. The problem we have, however, is that the button can seem redundant: “Schedule” is the object we’re altering, but that is the screen we’re on.
This is another time when we break our design guidelines (and remember: they’re guidelines) in order to provide better clarity to the user. Notice that this brings is up to two times we’ve violated our guidelines–we don’t violate those guidelines lightly, and only do it if it promotes clarity.
Our schedule editor allows the user to actually edit the schedule itself. This is a fairly complex and busy screen.
Sadly, like the old joke goes:
A user interface is like a joke. If you have to explain it, it’s bad.
But we can alleviate some of the complexity of this screen by the use of rounded corners.
In this case we use rounded corners to group the setting rows and the day of the week. We use the left bar to pick the specific schedule we are editing. And we provide some verbs: some operations we can take on the currently selected day: we can clear that day, we can copy that day or we can paste a previously copied day. The later two operations allow you to quickly set a group of days to use the same settings.
Edit Schedule Item
If you select a single date/time row, you are brought to a new screen which allows you to edit the temperature and the time for a given schedule row:
This screen reuses the date selection elements, but adds two additional control groups: one to set the heating temperature, and another to set the cooling temperature.
Like the other screens we use rounded rectangles to group functionally similar items. We also get rid of the inverted L since we have no other nouns: we are directly manipulating three objects and doing so in an obvious manner.
This is a relatively complex UI, and as I noted above, the complete implementation is actually complete and checked into GitHub.
And notice what we’ve done.
In all cases we’ve defined what it is we’re manipulating: the current time, the current temperature–and we’ve carefully defined the nouns and the verbs of our user interface: the noun (such as “the heater temperature setting”), and the verb (“increase the temperature”).
We’ve placed nouns on the left bar when there are multiple nouns to pick from, so the user can select the noun he is interested in manipulating. The content area of the screen then provides the verbs–the controls–by which the user can manipulate those nouns.
We’ve consistently used the inverted-L screen to indicate when there are a group of nouns the user can operate on. We’ve also consistently used a page-navigation scheme to switch between screens as the user switches between items he is interested in manipulating. And our verbs are always placed in rectangular or rounded-rectangle-shapes, where the rounding is used to help define groups of verbs. (For example, the “+”/”-” button in the Edit Schedule Item screen.)
And in the process we’ve designed the UI for a programmable thermostat that should be relatively easy for a user to use. Yes, the schedule programming screen is cluttered–but the use of grouping should make explaining how to use the screen in a user’s manual relatively trivial.
This process: defining our nouns, defining our verbs, defining the user interface elements and their appearance, and consistently applying these rules as we design our screens, results in a user interface that almost seems inevitable.
It wasn’t; there were a thousand other ways we could have gone. But this use of a design language with well defined nouns, verbs and actions results in an interface that seems simple–almost troublingly simple.
But that is what we want: a user interface that is so discoverable, so consistent, that it seems… invisible.
The next few posts will cover the implementation–the steps used in putting together the code.