domenica 23 ottobre 2016

Standard colors on HMI

The lack of a standard on what colors to use on HMI screens is a serious problem, because the most of HMI graphic pages depended on the personal taste of the engineer that realized it.
It’s not the first time that i see purple buttons, blue leds and green backgrounds.
Even if there isn’t a written standard on what colors you should choose, there are some “best ways” to design graphic page and make HMIs as helpful as possible.

Some colors that you should consider to use

This is the standard that i use as much as i can:
  • Led : green for active, gray for inactive, red for alarm.
  • Reserve leds: gray for inactive, red for alarm/reserve.
  • Motors and valve: green for active, gray for inactive, red for alarm
  • Pipes and tanks: cyan for water, gray empty, other colors if acids or special liquids.
  • Momentary buttons: all grays and possibly with windows style and an image associated. All buttons must have a description (don’t use only images); without a description the operator react with somethink like “i wonder what this button does… better not to touch”.
  • Toggle buttons: i like UP-DOWN lever switch. A button that stays pushed isn’t a good way on how to represent a switch, and it’s difficult to represent it on a flat panel.
  • Alarm banner and log: Red (everything in red should be associated to a wrong condition)
  • Background: gray for numerous reasons, like it doesn’t hurt eyes, no problem if there is low light of too much light, all operators are used to see gray backgrounds, gray means inactive – nothing wrong.
  • Animations: i use them only when i have to attract the attention of the operator, usually for alarms status or to pay attention at some particular operation. An abuse of animation usually distract the operator from it’s job, so it should be for a good reason (not for animating your logo of course). Think twice before representing bottles that get filled and capped with animations, because the operator is not blind and can see what’s happening inside the filling machine. A good use of animations can be a blinking gray-red led when it is in alarm state, a gauge that is changing value, a small alarm popup in the corner and so on. Remember to use them to attract the attention of the operator.
  • Pictures: use ISA symbols or schematic symbols if possible; 3D is your worst friend while representing a plant. It’s important that the operator understand what’s happening, not that he get fashinated.

Exmaple of some bad screens

I took some samples of what i think are bad screens:
Blue background with light green pipes, green and gray tanks and green valves and pumps. Definetly not a good contrast and not good pictures too.
Here pictures are better, but the contrast green on green is still bad. And on top there buttons or tag without a graphic modeling, so i can’t imagine how they can help an operator.

Better screens

This is what i call a useful screen.
with good contrast, not much led and the active ones in green (as you can see you notice them instantly on gray) and alarms in red.
This can be useful too, even if more complex:
Notice the good contrast for liquid levels on tank. I don’t know if components are red because they are not active or in alarms (as i hope), but it’s definetly a good representation.

Interesting article about User Interface

There is a very good article about choosing colors, animations and setting up a Graphical User Interface; you can read it on rollthunder.com – WpfForGoodAndNotEvil.htm
Even if it’s really long, i try to write his points in short:
  • First Principle: That the software that you write has zero value in and of itself. You write software for one reason and one reason only: to create value by making the user of your software happier than he would be without your software.  The only value that your software ever has or ever will have is the degree to which it increases the happiness of its users. It is extremely rare that users are willing to pay for software that decreases their overall happiness.
  • Second Principle: That computer programs increase the happiness of users in one of two ways.  The majority of applications help a user solve a specific  problem – writing an email message or an article, buying groceries or an airplane ticket, viewing a bank statement and paying bills. The user’s only goal in using this type of program is to finish the task and get on with his life, or at least on to the next task. The faster a program converts a task from not-finished to finished, the happier the user will be.
    The second way in which a program increases a user’s happiness, less common than the first, is by putting the user into a pleasurable state that he wants to maintain as long as possible, or at least as long as it remains pleasurable, like Games.
  • Third Principle: That in neither of these cases do users want to think about the programs they are using.  At all. Ever. In the former case, they want to think about the problem they are solving: the wording of the document they are writing, or whether they have enough money to pay their bills, and which unpaid creditor would hurt them the most.  They don’t want the program to distract them from the problem they’re thinking about.  If they want to goof off and waste time, they’ll bring up Solitaire, not admire the flashing video buttons in the word processor.
The point that i liked the most is this one: Motion attracts a user’s attention. Natural selection brutally pounded that design pattern into the human brain and visual system. Our savannah-based ancestors that noticed the twitch of the saber-tooth tiger behind the tall grass avoided being eaten and passed their attentive genes on to their descendants. The ones who didn’t notice the motion got eaten, and didn’t.  Every single user is the inheritor of roughly 13,000 generations of homo sapiens who noticed motion better than the ones who didn’t make it.
[…]
As user interface expert Jared Spool wrote of his test of a Disney web page containing an animated logo, that corporate branding icon so beloved of marketeers everywhere: “Users first tried to scroll the animation off the page, and when they couldn’t, actually covered it up with their hands so they could read the rest of the text.”
I really reccomend to check this article, is well written and with tons of examples

Resources to Learn Visual Studio with C#




https://www.youtube.com/channel/UC5_j0dmvXE0xs6ra-clGz4A

Writing your first HMI project in C# – WPF

Writing an Hmi with C# and WPF is quite easy, once that you know how to structure your project.
In this post i will make an example on how to write a simple Hmi (2 pages) that can access to a variable that get updated from another thread.

Structure of the project

The structure of the Hmi will be the following:
– Graphical User Interface: written in WPF using the PageSwitcher class.
– Plc variables: global static variables that can be read(-only) from all pages.
– Plc driver: multithreaded communication to avoid to block the graphic user interface thread.
Once you created your pages, you need to develop the communication driver for your plc, or to use an existing driver.
The communication driver is usually synchronized with the plc, this means that the driver sends a request to the plc and waits until the plc answers; the waiting time can be short or long, depending on the protocol and cable.
A synchronized communication can be a pain for your graphic user interface, because it will lock the pages for the most of the time; that’s why the communication has to be hosted on a secondary thread and plc-variables needs to be synchronized with the GUI thread.

Plc variables and communication thread

To write an Hmi and access to plc values i often use global static variables, that contains the values that i read from the plc.
Usually i declare a plc variable in this way:
1
public static int Count { get; private set; }
The “private set” means that the variable is read-only outside the class, and this is logic because you can’t write a plc-variable without write it in the plc before.
To contain the variables and the communication thread you should use a static class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static class Plc
{
    static Thread t;
     
    static Plc()
    {
        // this is an example of static constructor, that i don't need in this example and i leave it empty.
    }
    public static void StartCommunication()
    {
        t = new Thread(new ThreadStart(CommunicationThread));
        t.Name = "PlcCommunication";
        t.Start();
    }
}
The communication thread is:
1
2
3
4
5
6
7
8
9
10
11
12
static readonly object _locker = new object();
private static void CommunicationThread()
{
    while (!StopCommunication)
    {
        lock (_locker)
        {
             Count++;
             Thread.Sleep(500); //long elaboration
        }
    }
}

Access to plc-variables inside the pages

To access to plc-variables inside the hmi pages, just declare a timer for each page, with a callback that updates the GUI objects with the plc-variables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DispatcherTimer timer = new DispatcherTimer();
public Page1()
{
    InitializeComponent();
    timer.Interval = TimeSpan.FromMilliseconds(100);
    timer.Tick += new EventHandler(timer_Tick);
    timer.Start();
    timer_Tick(null, null); //this will refresh the textboxes before you show the page
}
void timer_Tick(object sender, EventArgs e)
{
    txtCount.Text = Plc.Count.ToString();
}

Memory issues

There is a known memory leak with DispatcherTimer inside UserControls, because if it’s not stopped it will not release the UserControl and you will keep in RAM all the page that you visit.
The reference is here: http://geekswithblogs.net/dotnetrodent/archive/2009/11/05/136015.aspx
To avoid the memory leak remember to subscribe to the event UserControl_Unloaded:
1
2
3
<UserControl x:Class="HmiExample.Pages.Page1"
             ...
              Unloaded="UserControl_Unloaded">
and to stop the timer in the event handler:
1
2
3
4
private void UserControl_Unloaded(object sender, System.Windows.RoutedEventArgs e)
{
    timer.Stop();
}

Example for VS2010

This is a quick and dirty example, but it will get you started until you will master WPF and Datacontext – Databinding mechanism.
Download the example for Visual Studio 2010.