Logo Banner

Velleman K8000 - [K8000 Standalone Usage] - [K8000 Home Automation] - [Software Architecture]

K8000 Standalone Home Automation

Software Architecture

The code you need to write is minimal, but the complete program contains hundreds of lines to make things work. You don't need to understand all this, all you need to do is to modify the Program.cs file (the main file of the project). However, some understanding is required in order to modify/expand the program with your own functions. The image below shows a part of the internal structure of the program.

I created a separate class for any of the available commands. Their names always start with Cmd... for an easier identification. All of these classes are inherited from the SwitchButton class: the SwitchButton class is the master class, other Cmd classes are derived from it. This abstract SwitchButton class contains some functions that can be called from any of the Cmd classes, like k8000() to get the Velleman_K8000 object. This object is used for the communications to/with the Velleman K8000. It is shared across all Cmd objects.

Once you create an instance of a Cmd class, it will add itself to a static array in the SwitchButton class automatically. This way the SwitchButton class can keep a list of all created Cmd objects. This might sound odd, it is done to minimize the complexity for the end user (novice programmer). An object is usually created in this way:

    CmdToggle myButton = new CmdToggle(1, 10);
    

In the sample above a new CmdToggle object is created, and it is assigned to the myButton variable. Thanks to my mechanism this assigning is not required. You can just write: new CmdToggle(1, 10);. Frankly I'm not sure if this is a recommended coding practice, but it certainly works and it is easy for the end user.

Each of the Cmd classes has a constructor. They contain the initialization code for the object. Any required information for the function is passed through this constructor, and is put into member variables. The constructor of each Cmd class should always include this line: createPermanentInstance(this, inputChannel);. It will add the newly created object to an array in the SwitchButton class.

The Home Automation program will be executed by calling the SwitchBox.executeAll() static method. The FEZ will then start cycling very rapidly through each of the objects you created. For each of them the function doAction(); is called, a function in the SwitchButton class. It will verify the state of the corresponding I/O channel. The doAction() can trigger 5 possible events:

Each of the Cmd classes can use any of these events. Event functions that aren't necessary don't have to be included in a Cmd class. You can put any code you like inside the event functions, but you need to consider one thing: you MUST avoid large loops or delay functions: You should be aware a home automation system contains a lot of input switches: two people could push a different button at the same time. So this Home Automation application acts as some kind of multitasking system: each process (switch/Cmd class) gets a little time to do its own job. For the end user it will look like everything is running simultaneous. So, a certain programming method is required inside the event handling functions.

Let's assume a small program with only one button. The program runs for a few seconds and then the button is briefly pushed. These are the events that will occur inside the corresponding Cmd class:

    buttonUnpressed()
    buttonCycle()
    {... repeated ??? times...}
    
    buttonDown() {}
    buttonCycle() {}
		
    buttonPressed(int time_ms) {}
		buttonCycle() {}
    {... repeated ??? times... time_ms increases after each cycle}
    
    buttonUp() {}
    buttonCycle() {}
    
    buttonUnpressed()
    buttonCycle()
    {... repeated ??? times...}		
    

You might wonder: why didn't you just build a system that uses multiple threads? The FEZ Panda hardware supports it. On such system the FEZ would run each Cmd class in a separate thread. I did consider this option, but sharing the I2C bus between multiple threads would definately cause problems.

Program startup

When the FEZ is just powered, the program will start in the Program.cs file. First the K8000 is initialized by setting the SwitchBox.numberOfK8000Cards static property, to specify the number of connected K8000 cards. Setting this property will internally create a K8000 object, that is used for all communications with the K8000 card. This object will be shared across all Cmd classes through the k8000() method.

Then the FEZ will create all objects you created in the Program.cs file. During the creation they will be put into an array in the SwitchButton class. Eventually your program is started by the SwitchButton.executeAll(); command. This static method will create an infinite loop: during each cycle the doAction(); method for any of the existing objects is called. It will evaluate the push button and will call the appropriate events.


Add your own functions

You can add your own custom functions by adding a new Cmd class to the project. This class should inherit from the SwitchButton class. You do this by calling your class class Cmd*YOURNAME* : SwitchButton. The constructor of the class has to accept some parameters, like the I/O channel for the pushbutton. You should put these parameters into member variables, to make them accessible from any function in the class.

The constructor should also always contain the createPermanentInstance(this, inputChannel); statement, to add the instance of the class to the SwitchButton class. The keyword this refers to the class. The inputChannel is the channel your pushbutton is connected to.

Your custom classes should always contain at least one of these functions:

In these functions you can add the code must be executed when the corresponding event occurs. As mentioned before, it shouldn't contain any loops or delay functions. You can find a sample class below. It is the class for the CmdStartAll() function, which will start all I/O output channels when the input button is pressed.

    class CmdStartAll : SwitchButton 
    {
      public CmdStartAll(int inputChannel) 
      {
      	createPermanentInstance(this, inputChannel);
      }
    
      public override void buttonDown() 
      {
      	k8000().setAllIO();
      }
    }
    

[Return to the Home Automation main page]

Copyright ©1998-2017 Vanderhaegen Bart - last modified: August 24, 2013