PLC Training: Exercise #2 Input Mapping

You can find the other parts of the exercise here: http://mestaa.blogspot.com/2011/05/plc-training-exercise-2-solution-with.html
 
1) Sequence analisys and algorithym

Step #1: Waiting for Box in position
Step #2: Box is full
Step #3: Box is moved outside the level sensor
To change steps follow the arrow and the signal that has to be received.
From all steps you must be able to stop the machine if Stop push button is pressed
If the machine is stopped, pressing Start push button will restart the cycle from Step #1

2) Writing the program:
Defining tasks:

those 3 tasks should be in every program
-Simulation
-Map Inputs
-Map Outputs
- There should be an Alarm task also, but in this exercise alarms are not requested.
I gave the name MainProgram to the task that runs the cycle because this is a really simple program, with one short cycle and a start/stop without particular requests.

3)Input Mapping:

I usually map inputs in DINT variables, so i can force them without problems while debugging on the real plant.
Also it makes it easy to change a broken Input without having to change all the program.
Other programmers uses to map Input in UDT data types, with all the problems connected on the  debugging phase the real system when it is ready.

As for the output i usually write an alias tag, because i always use outputs once in all program and with a coil segment.

Next part is here: Cycles and Outputs

PLC Training: Some interesting exercises

I found some interesting exercises about plc programming that cover almost all the topics that a programmer should know.
The document is mainly thought for Allen Bradley plcs users, but it can be useful also for others.
The exercises are:
1) Using simple relays logic to control a motor
2) Using relays logic to control simple sequences
3) Using Timers, Retentive Timers and Counters
4) Using relays logic + everything saw before to control a batch mixing system
5) Using shift registers to determine the position of a bottle in a filling plant
6) Using various modules to control an elevator system.

The pdf  was found on http://thelearningpit.com/lp/logixpro.html, they also sells some kind of graphical simulation to run the plants if you're interested.
 I reccomend to try logixpro simulator (15 days trial) because it can really improve your ladder code with just your time.
You can download the exercise file directly from learning pit website or from here:
http://www.megaupload.com/?d=PIWQA7AS

HMI Controls for WPF: Led (and a tutorial on WPF User Control)

You can downlaod the source code with sample here: http://www.mesta-automation.com/Downloads/Led%20Wpf.rar

Every Scada system has his own framework that contains a lot of graphic objects, from gauges to charts, that can be controlled directly by some Tags or variables.
Unfortunately .Net doesn't come with this objects, so we have to create them.
In this sample i show how to create a simple graphical Led.

Create a new Control Library (File -> New -> Project -> WPF User Control Library),
then create a new project to test the control( to test and show how to use the control).
After the creation of this 2 projects, set the test project as startup project and add as reference the  control library.
Now we are ready to start creating the graphic part.

Basically a led can be drawn as a Border object that inside it contains a color, and his background is of another color.
This is the code for the graphic part
<Grid x:Name="gridBigLed" >
        <Border x:Name="border1" BorderThickness="6" Width="{Binding ActualHeight, ElementName=gridBigLed, Mode=OneWay}" CornerRadius="{Binding ActualWidth, ElementName=gridBigLed, Mode=OneWay}">
            <Border.Background>
                <RadialGradientBrush >
                    <GradientStop Color="White"/>
                    <GradientStop x:Name="backgroundColor" Color="Red" Offset="0.835"/>
                </RadialGradientBrush>
            </Border.Background>
            <Border.BorderBrush>
                <RadialGradientBrush>
                    <GradientStop Color="#FF020202" Offset="0.383"/>
                    <GradientStop Color="#FFE4E4E4" Offset="1"/>
                </RadialGradientBrush>
            </Border.BorderBrush>
        </Border>
    </Grid>


We bind the height of the border to the height of the grid, so we can resize the control when developing our application.
Corner radius is in binding with width too, to be sure that the border will be always circular.
For the background color you can use wathever you like. I used a radial gradient with Red(Off state) and White , and i will change it with green and  white (On state) depending on the state of a property. That's why I gave the name "backgroundColor" on the red GradientStop.

To give properties to a UserControl we must use Dependency Properties.
We will give 3 properties to the user control:
- bool IsActive
- Color ColorOn (color when IsActive is true)
- Color ColorOff (color when IsActive is false)

The declaration is the following:

/// <summary>Dependency property to Get/Set the current IsActive (True/False)</summary>
        public static readonly DependencyProperty IsActiveProperty =
            DependencyProperty.Register("IsActive", typeof(bool), typeof(Led),// null);
                new PropertyMetadata(new PropertyChangedCallback(Led.IsActivePropertyChanced)));

        /// <summary>Dependency property to Get/Set Color when IsActive is true</summary>
        public static readonly DependencyProperty ColorOnProperty =
            DependencyProperty.Register("ColorOn", typeof(Color), typeof(Led), //null);
                new PropertyMetadata(Colors.Green,new PropertyChangedCallback(Led.OnColorOnPropertyChanged)));

        /// <summary>Dependency property to Get/Set Color when IsActive is false</summary>
        public static readonly DependencyProperty ColorOffProperty =
            DependencyProperty.Register("ColorOff", typeof(Color), typeof(Led),// null);
                new PropertyMetadata(Colors.Red,new PropertyChangedCallback(Led.OnColorOffPropertyChanged)));

        /// <summary>Gets/Sets Value</summary>
        public bool IsActive
        {
            get { return (bool)GetValue(IsActiveProperty); }
            set 
            {
                SetValue(IsActiveProperty, value);
            }
        }

        /// <summary>Gets/Sets Color when led is True</summary>
        public Color ColorOn
        {
            get
            {
                return (Color)GetValue(ColorOnProperty);
            }
            set
            {
                SetValue(ColorOnProperty, value);
            }
        }

        /// <summary>Gets/Sets Color when led is False</summary>
        public Color ColorOff
        {
            get
            {
                return (Color)GetValue(ColorOffProperty);
            }
            set
            {
                SetValue(ColorOffProperty, value);
            }
        }

Now there is a lot to talk about dependency properties, but basically:
you can set the starting value when you create the objects (ColorOn starts with Color.Green and ColorOff start with Color.Red)
and you should note that every property has is name written as string in the 1st field of DependencyProperty.Register method.
the properties also access to values contained in dependency properties  by getValue() and SetValue().

Every Dependency Property should have is own method when it changes. Those methods describe the behaviour of our object, basically a change of IsActive should modify the color of the border and if i change a color at runtime, depending on the state, it should refresh the color instantly.
In this case i wrote the following methods:

private static void IsActivePropertyChanced(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Led led = (Led)d;
            if ((bool)e.NewValue)
                led.backgroundColor.Color = led.ColorOn;
            else
                led.backgroundColor.Color = led.ColorOff;
        }

        private static void OnColorOnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Led led = (Led)d;
            led.ColorOn = (Color)e.NewValue;
            if (led.IsActive)
                led.backgroundColor.Color = led.ColorOn;
            else
                led.backgroundColor.Color = led.ColorOff;
        }

        private static void OnColorOffPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Led led = (Led)d;
            led.ColorOff = (Color)e.NewValue;
            if (led.IsActive)
                led.backgroundColor.Color = led.ColorOn;
            else
                led.backgroundColor.Color = led.ColorOff;
        }

Note that every method is static and it access to the user control property by casting the dependencyobject d.

As for the constructor, i wrote a refresh depending on what color it's set.

public Led()
{
   InitializeComponent();
   if (this.IsActive)
       this.backgroundColor.Color = ColorOn;
   else
       this.backgroundColor.Color = ColorOff;       
}


In this way our control should work.

Now to test we should try it with and without databinding.
This is the test that i wrote:

<Window x:Class="LedTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:uc="clr-namespace:LedControl;assembly=LedControl"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="10"/>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <uc:Led Name="led1" Height="60" Width="60" IsActive="False" Flashing="False" FlashingPeriod="500"  />
        <TextBlock Grid.Column="1">Led without binding</TextBlock>
        <Button Name="btnChange"  Grid.Column="2"  Content="Change" Click="btnChange_Click" />
        <uc:Led Name="led2" Grid.Row="2" Height="60" Width="60" IsActive="{Binding LedStatus}"  />
        <TextBlock  Grid.Row="2" Grid.Column="1">Led with binding</TextBlock>
        <Button Name="btnChange2"  Grid.Row="2" Grid.Column="2"  Content="Change" Click="btnChange2_Click" />
    </Grid>
</Window>
         


public partial class MainWindow : Window,INotifyPropertyChanged
    {
        bool ledStatus;
        public bool LedStatus
        { get { return ledStatus; } set { ledStatus = value; this.OnPropertyChanged("LedStatus"); } }

        public MainWindow()
        {
            InitializeComponent();
            led2.DataContext = this;
            led1.ColorOn = Colors.Blue;
            led1.ColorOff = Colors.Gray;
        }

        private void btnChange_Click(object sender, RoutedEventArgs e)
        {
            led1.IsActive = !led1.IsActive;
        }

        private void btnChange2_Click(object sender, RoutedEventArgs e)
        {
            LedStatus = !LedStatus;
        }


        #region INotifyPropertyChanged members

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }

        #endregion  

The 1st button test the led by changing the color from codebehind, the second test it in binding with a property contained (in this case) in the mainwindow directly.

Playing with Blend and adding more Dependency Properties will give even a better result.

Sample App is here: http://www.mesta-automation.com/Downloads/Led%20Wpf.rar