Outsourcing >

SSI Quality Process Overview Customer Satisfaction Our Engineers Questions to Ask Technical Lab Testimonials Whitepapers
SSI Embedded Systems Trust Facts

Fact: Over 50% of SSI Staff has 8 or More Years Experience

"You can count on the work being done right and on time." ~ SSI Client

Fact: 30% of SSI staff has twelve or more years experience

"The people blended in and became part of the design team."

Fact: Experienced Team Lead manages all projects

"I was impressed with the quality of SSI's work throughout this contract. I appreciated their ability to work with minimal guidance, and minimal design details. And I greatly appreciated their suggestions and alternate design proposals. Their willingness to work overtime when necessary to meet deadlines was greatly appreciated." ~ SSI Client

Fact: All SSI staff is trained on the Quality Development Process

"Work is spectacular. More exceptional than I thought it would be. Sensors work great. They can detect the slightest pressure accurately. It is WAY beyond my expectations." ~ SSI Client

Fact: Long term staff retention rate at SSI is > 95%

Fact: SSI's Internal Software process operates as CMM Level 3

"The experience was a good one" ~ SSI Client

Fact: SSI has been in business 16+ years

"The best thing about working with SSI is that the people genuinely care about the success of the overall project. Typical contractors stop when they have merely met the letter of the contract that they are bound to; where as, SSI is willing to go above and beyond to drive a project to completion and ultimately success." ~ SSI Client

Fact: Over half of SSI Business is from returning clients

"I would use SSI again" ~ SSI Client

Fact: SSI client relationships last several years

"The best thing about working with SSI is that the people genuinely care about the success of the overall project. Typical contractors stop when they have merely met the letter of the contract that they are bound to; where as, SSI is willing to go above and beyond to drive a project to completion and ultimately success." ~ SSI Client

Fact: SSI's Customers report a consistent 4.5 out of 5 rating for satisfaction

"Keep finding people who can get to the root of the issue and resolve it as specified. [Your Engineer] is golden!." ~ SSI Client

Fact: 100% of clients surveyed said they would recommend SSI to others

"SSI will deliver what is promised on a timely basis." ~ SSI Client

Fact: SSI Supports Continual Employee Training

"Consistent high quality engineers who perform very well. SSI is the only company -- contracting or consulting -- who consistently provides the best talent who are not only technically accomplished but have excellent verbal and personal skills. I have not seen anything like it before." ~ SSI Client

SSI Embedded Trust Facts

Embedded Systems Whitepapers

Developing a Controller Using Design Patterns
By John Kramer

This whitepaper details a practical example of how to use software design patterns in modeling real-world embedded systems applications.  By illustrating how to apply design patterns during development of a garage door controller, we demonstrate the important benefits of state design patterns:

  • Software Modularity
  • Code Re-usability
  • Improved Maintainability
  • Lower Costs
  • Faster Time-to-Market
View the source code for this controller.

A Garage Door Controller - Introduction
In the following example, we illustrate design patterns as they are used to develop a simplified garage door controller:  from design to software.  All sample code is in Java, although other object-oriented languages such as C++ can be used. 

The main focus of this document is on the design of an embedded systems application using object-oriented design patterns.  Topics such as the choice of wireless protocol to use for communications between the remote device and the controller, garage door motor size, and sensor interfaces, are another topic altogether.  While we use a garage door controller as an example, this example is not intended for use in designing specific garage door controllers.

A familiarity with general software design principles and guidelines for embedded systems applications is assumed.  A basic knowledge of the Unified Modeling Language (UML), specifically the constructs used on class diagrams is also helpful.

Why Use Design Patterns for Your Embedded Application/Controller?
Although the use of design patterns is an established methodology in software design, its benefits are often poorly understood when compared to conventional programming styles. This confusion begins with the formal definition for a software design pattern: a general reusable solution to a commonly recurring problem. This definition is too generic and abstract to reveal anything useful about design patterns.

In an effort to better understand why design patterns are used, it is perhaps better to examine their various features. A software design pattern consists of several software classes and their relationships. Classes consist of a name, attributes (variables), and methods (functions); relationships include inheritance, composition, aggregation, and/or references. A software design pattern is a combination of one or more classes and their relationships, and it is this combination that facilitates the grouping of software code in such a way that significant benefits can be achieved.

The greatest benefits to using software design patterns are modularity and better code re-usability. These, of course, all lead to code that is easier to maintain, lower costs and faster time to market.

Controller Specifications
Most modern garage doors have a button to toggle the door up and down.  If the door is down and the button is pushed, the door will start to open.  If the door is open and the button is pushed, the door will start to close.  It should also be possible for the user to reverse the direction of the door by pressing the button while the door is moving (four-year-olds love to perform this operation repeatedly to the annoyance of their parents!).

Furthermore, if the door reaches its final position (either at the top or bottom), the controller should signal the motor to stop driving the door. 

Most garage doors also have a sensor beam located at the bottom of the door.  In the event that someone or something stands directly underneath the door while it is closing, the door should open back up to prevent a collision and possible bodily injury. 

Controller Design
There are, of course, ultimately many ways one could choose to design the garage door controller.  For most engineers, an intuitive solution involves using a state machine to govern the behavior of the garage door under the various situations described.  Two obvious states are “OPEN” and “CLOSED,” and these indicate the status of the garage door under the stationary conditions implied by their names. 

A third state is needed to describe the motion of the garage door.  It would be tempting to call this state “MOVING”, but such a state cannot capture which direction the door is moving.  Among other reasons, it would be important to know this information to determine whether tripping the sensor would require any action as described above.  Thus, it is necessary to utilize two states to describe the garage door motion.  These will be called “OPENING” and “CLOSING.”  The final state machine is shown below:

state
Figure 1:  Garage Door State Machine

The transition labeled ‘tripSensor’ is included as a safety feature to prevent objects or people from being crushed by a closing garage door.  The transition ‘motorStopped’ indicates the door cannot travel any further in the direction it is moving, and has signaled the motor to stop driving it.  The transition ‘pushButton’ is analogous to a human user pushing their garage door opener button to either open or close their garage door.

This is an overly simplistic view of a garage door controller.  The safety feature for tripping the sensor is attractive to those with children or people who have a tendency to leave things directly underneath the door (especially their cars)! 

But what happens when power is lost and the door is ajar?  There is no state here to model error conditions such as lost power, nor is there any recovery mechanism.  Since there are alternative design methods for handling the loss of power that do not involve the use of a state machine (i.e. flagging diagnostics), a solution for handling the loss of power in this design is intentionally omitted.

Transitioning the Controller from Design to Software
At this point, many embedded software engineers would code up a standard state machine solution.  Enumerated constants would be used to designate the states.  Additionally, a new thread would be spawned off that executed in a forever repeating loop.  This loop would wait for events, and then take action on the event based on which state is current.  The code for this state machine would like this:

#define STATE_OPEN                1
#define STATE_CLOSED            2
#define STATE_OPENING          3
#define STATE_CLOSING           4

#define EVENT_MOTORSTOPPED         1
#define EVENT_PUSHBUTTON               2
#define EVENT_TRIPSENSOR                3

int state = STATE_CLOSED;

// This code runs forever looking for events!
StateMachine::void run() {
    GarageDoorControllerEvent newEvent;
    while( 1 == 1 ) {
        dequeueEvent( &newEvent );
        switch( newEvent->getType() ) {
            case EVENT_MOTORSTOPPED:
                if( state == OPENING ) { state = OPEN; }
                else if( state == CLOSING ) { state = CLOSED; }              
                break;

            case EVENT_PUSHBUTTON:
                if( state == CLOSED ) { state = OPENING; }
                else if( state == OPEN ) { state = CLOSING; }
                else if( state == CLOSING ) { state = OPENING; }
                else if( state == OPENING ) { state = CLOSING; }
                break;

            case EVENT_TRIPSENSOR:
                if( state == CLOSING ) { state = OPENING; }
                break;                  
       
            default:
                // Not a valid event, either discard or flag an error?!
                break;
        }

        // Don’t be a CPU hog, share with others and let them have a chance!
        sleep( 50 );
    }
}

NOTE:  The above code omits details regarding threading, mutual exclusion for access of the state variable, and queuing mechanism for the stored events.

This method of straightforward coding, however, has some significant drawbacks.  The change or addition of any events and/or transitions is cumbersome and rather error prone.  Re-testing is required for this since the code has to change.

Using the Design Pattern Called 'State'
A wonderful software design pattern exists for the modeling of state machines.  The pattern is called State.  It can be used to model any state machine one can conceive.  A diagram of the State pattern is shown below:

 

sate
Figure 2:  State Design Pattern UML Class Diagram

 

The State pattern can easily be mapped into the problem domain of a state machine.  Simply, each state in the state machine design becomes a ConcreteState subclass of an abstract State class (it can also be implemented as an interface for the Java inclined).  Each transition in the state machine design becomes a method in the abstract State class, and the implementation of each transition is placed inside the overridden concrete subclass methods.

Applying the above description to our garage door opener state machine design yields an abstract class GarageDoorControllerState with the three abstract methods pushButton, tripSensor, and motorStopped.  It also yields four subclasses of the GarageDoorControllerState called Closed, Closing, Open, and Opening.  The context object is largely template-driven and simply created for simplicity of usage.  The final class diagram is shown below:

 

astset
Figure 3:  State Pattern Applied to Garage Door Design

The Benefits of the State Design Pattern
This design definitely has advantages over the previous implementation.  For one, each state is encapsulated inside its own class.  This means that, if there are changes, there is a minimum amount of recompilation and testing to perform. 

This design also isolates the state transitions from any code that needs to be done in conjunction with the transition.  The StateContext object handles things such as engaging motor control or reading the sensors to determine if an object is present underneath the door.  Another huge advantage to this approach involves the use of auto-generated tools.  Many tools, such as UML Studio, Rhapsody, Together, Poseidon and others, allow for the creation of UML design patterns and have a feature that automatically generates the code.  This allows the engineer to focus on the actual design and less on the implementation details.  All in all, this approach allows for greater accuracy and understanding of the actual design and results in faster time to market. 

One potential disadvantage exists with this approach, particularly in C++ where memory allocation becomes an issue.  The constant use of the new and delete operators used while changing states could become a problem, depending upon the operating system’s memory allocation policies.  Constantly allocating and de-allocating memory could result in memory fragmentation.  The extent of this depends upon the underlying memory allocation scheme in the operating system.

View the source code for this controller.

FEATURED ARTICLES
The Real Time Review brings you the latest embedded software news and technical articles - published approx. six times throughout the year.
> VIEW ALL NEWS

RSS Feed
A Certified Women's Business Enterprise and Member of the Illinois Technology Association