IoT - Gadgeteer - Setting the preferred temperature

It’s been a while, but I’ve pulled my project from under the dust and started cleaning up some code by doing a refactor.
I noticed my code got a bit messy so I applied some Design Pattern strategies to it. I’ll save you the details because it’s not really relevant to the Gadgeteer project.

So to continue, in my previous blog I added an observable display and made sure we could see what was going on.
Now it’s time to interact with the device so we can actually set a preferred temperature, which is actually the main purpose of a thermostat.

Adding some buttons

To be able to set a preferred temperature we need some interaction with the system. I’ve chosen two buttons to do the job of increasing and decreasing the preferred temperature.
As with the previous modules we can just select the Button module from the Toolbox and drag in onto the Program.Gadgeteer Designer Board. If you’re not sure how to do this please read carefully the Connecting a Sensor Module blog, which I wrote earlier.

After adding the buttons the Designer Board might look something like below. Notice that I’ve renamed the buttons myself to make a bit more sense than ‘button1’ and ‘button2’.. You can rename the modules by a simple ‘right-click’ on the module, than select the option ‘Properties’ from the context menu and change the value in the ‘Name’ box.

Next to a Power, Temperature and a Display module we now also have two buttons attached (click on the image to enlarge)

Change the preferred temperature

To be able to change the preferred temperature we have to keep track of a value. Therefore I created a double property on the MainData class which I named _preferredTemp. Obviously we could just attach an EventHandler to both buttons which in turn increases or decreases the temperature by a half degree. But that would be way to easy. Next to that it would mean that I have to press the button multiple times to change the temperature a couple degrees. I want to be able to hold a button and change the temperature while holding the button.
Thankfully the Button Module supports both a ‘OnClick’ and a ‘OnReleased’ event.

So this is my approach:
1: Whenever the user presses a button, the preferred temperature should be changed by 0.5 degrees.
2: Whenever the user holds the buttons, the temperature should be changed by 0.5 degrees each half of a second.

This means we have to keep track of a timer which has it’s ‘Tick’ value set to 500 milliseconds.
On each tick, we change the preferred temperature based on the button which is held.

The code snippet of the Program class looks like this.
Side-note: Some ‘irrelevant’ code is replaced by ‘[..]’ for increasing readability on this blog.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public partial class Program
{
[..]
private MainData _mainData;

private readonly Timer _mainTimer = new Timer(2000);
private readonly Timer _buttonHoldTimer = new Timer(500);

private void Initialize()
{

_mainData = new MainData();
[..]
buttonDown.TurnLedOff();
buttonUp.TurnLedOff();

buttonDown.ButtonPressed += ButtonDown_OnButtonPressed;
buttonDown.ButtonReleased += ButtonDown_OnButtonReleased;

buttonUp.ButtonPressed += ButtonUp_OnButtonPressed;
buttonUp.ButtonReleased += ButtonUp_OnButtonReleased;

_buttonHoldTimer.Tick += HoldTimer_OnTick;
[..]
}

[..]
private void HoldTimer_OnTick(Timer timer)
{

if (buttonDown.Pressed)
_mainData.DecreasePreferred(0.5);

if (buttonUp.Pressed)
_mainData.IncreasePreferred(0.5);
}

private void ButtonDown_OnButtonPressed(GhiModules.Button sender, GhiModules.Button.ButtonState state)
{

buttonDown.TurnLedOn();
_mainData.DecreasePreferred(0.5);
_buttonHoldTimer.Restart();
}

private void ButtonDown_OnButtonReleased(GhiModules.Button sender, GhiModules.Button.ButtonState state)
{

_buttonHoldTimer.Stop();
buttonDown.TurnLedOff();
}

private void ButtonUp_OnButtonPressed(GhiModules.Button sender, GhiModules.Button.ButtonState state)
{

buttonUp.TurnLedOn();
_mainData.IncreasePreferred(0.5);
_buttonHoldTimer.Restart();
}

private void ButtonUp_OnButtonReleased(GhiModules.Button sender, GhiModules.Button.ButtonState state)
{

buttonUp.TurnLedOff();
_buttonHoldTimer.Stop();
}
}

The code in the MainData class now looks like this:
Side-note: Some ‘irrelevant’ code is replaced by ‘[..]’ for increasing readability on this blog.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class MainData : ISubject
{
private ArrayList _observers;
private double _temperature;
private double _humidity;
private double _preferredTemp;

public MainData()
{

_observers = new ArrayList();
_preferredTemp = 20.0;
}

[..]
public void NotifyObservers()
{

foreach (IObserver observer in _observers)
{
observer.Update(_temperature, _humidity, _preferredTemp);
}
}

[..]
public void IncreasePreferred(double amount)
{

_preferredTemp = _preferredTemp + amount;
NotifyObservers();
}

public void DecreasePreferred(double amount)
{

_preferredTemp = _preferredTemp - amount;
NotifyObservers();
}
}

So previously we made the display observable, meaning that if some value changes it automatically is updated.
This time actually only had to append the preferred temperature to the display output and call the NotifyObservers() to let the display know that something was changed.

The code in the Display class now looks like this:
Side-note: Some ‘irrelevant’ code is replaced by ‘[..]’ for increasing readability on this blog.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Display : IObserver, IDisplayElement
{
[..]
private double _temperature;
private double _humidity;
private double _preferredTemp;

private readonly GhiModules.CharacterDisplay _charDisplay;

public Display(GhiModules.CharacterDisplay charDisplay)
{

_charDisplay = charDisplay;
}

public void Update(double temperature, double humidity, double preferredTemp)
{

_temperature = temperature;
_humidity = humidity;
_preferredTemp = preferredTemp;
Show();
}

public void Show()
{

_charDisplay.CursorHome();
// Line 1
_charDisplay.Print(_temperature.ToString("F1") + "'C");
_charDisplay.Print(" "); // Four spaces to fill up the displays 16 characters.
_charDisplay.Print(_humidity.ToString("F1") + " %");

// Line 2
_charDisplay.SetCursorPosition(1, 0);
_charDisplay.Print("SET: " + _preferredTemp.ToString("F1") + "'C");
}
}

This makes the display look like this:
On the left we have the 'Down' button and on the right the 'Up' button. The display now also shows the preferred temperature as 'SET: XX.X' (click on the image to enlarge)

Holding the 'Down' button decreases the preferred temperature. And as a bonus also lights up an LED next to the button! (whoohoo) (click on the image to enlarge)

So now we cannot only see the temperature and the humidity in the room, but we can also set a preferred temperature.

NEXT UP: We play around with a programmable LED string to have some nice feedback on our interactions.