AdvancedHMI Software

General Category => Support Questions => Topic started by: ENA on November 18, 2013, 04:39:52 AM

Title: Processing signal and data in Advanced HMI
Post by: ENA on November 18, 2013, 04:39:52 AM
Hello.

Is it possible to process signals and data inside HMI?

E.g., if I have several binary signals from PLC, lets call them S1, S2 and S3 (bits or inputs of PLC), can I use BasicIndicator to turn red for a specific combination of symbols?
So, if (S1=1 or S2=1 or S3=0) Basic Indicator should be red (e.g. General Error).

Also, if I have several integer values, is it possible to make calculations inside HMI?

I'm sorry if this is a elementary question or if it was discussed already, I didn't find answers. I was trying to make myself clear, hope I'm not to vague.
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on November 18, 2013, 09:33:32 AM
The BasicInidicator is a 3 color display controlled by 2 bits. You put the 2 bit addresses in PLCAddressSelectColor2 and PLCAddressSelectColor3. You can then set the 3 colors with the color properties. If both bits are false, it will show Color1, if the value in PLCAddressSelectColor2 is true, then it will show Color2, etc.

To do calculations, you will need to write a little bit of code. If you want to add 3 numbers, you can add 3 DataSubscribers to the form and set PLCAddressValue for each of the integers. Add a Label to the form to show the sum. Double click the first DataSubscriber to get back to the code.

Label1.Text=DataSubscriber1.Value+DataSubscriber2.Value+DataSubscriber3.Value

You will need to put this code in the DataChanged event for each of the DataSubscribers.
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on November 19, 2013, 04:26:28 AM
Thank you for your answer Archie.

I tried what you suggested, but it doesn't seem to work hat way. I have data subscribers DS_INT1 and DS_INT2. DS_INT1 reads from N100:0 and DS_INT2 reads from N100:1. Also there is a label called NLabel. Code is as you said (I both tried with NLabel.Text and NLabel.Value):

NLabel.Text = DS_INT1.Value + DS_INT2.Value

Lets assume that N100:0 = 21 and N100:1 = 1.

Label then shows: 211

It doesn't add values, but only appends value from one adress (DataSubscriber) to the value from another.

Would appreciate your further comments on this.
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on November 19, 2013, 05:27:39 AM
I tried what you suggested, but it doesn't seem to work hat way. I have data subscribers DS_INT1 and DS_INT2. DS_INT1 reads from N100:0 and DS_INT2 reads from N100:1. Also there is a label called NLabel. Code is as you said (I both tried with NLabel.Text and NLabel.Value):

NLabel.Text = DS_INT1.Value + DS_INT2.Value

Lets assume that N100:0 = 21 and N100:1 = 1.

Label then shows: 211

It doesn't add values, but only appends value from one adress (DataSubscriber) to the value from another.
NLabel.Text = CInt(DS_INT1.Value) + CInt(DS_INT2.Value)

Ironically I teach this in training classes to be careful about implicit conversion because it will concatenate strings instead of mathematically sum their values. The strings have to be explicitly converted to integers.
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on November 19, 2013, 06:31:01 AM
Thank you Archie, that fixed it. I had a feeling it could be something like that, but I'm a complete newbie with Visual Basic (I'm actually an electromechanical engineer trying to implement SCADA for my PLC systems), and don't have a clue about syntax etc.

Following this example, I tried to experiment with BasicIndicator mentioned in the first post. Idea is to subscribe to bits in PLC and, when they change, change the color of Indicator.

This code is ni DataSubscriber DataChanged sub:

If DS_NZS.Value <> 0 Or DS_NAPON.Value <> 0  'This is where I could put all of my signals and conditions
         Indicator.SelectColor2 = True
Else  Indicator.SelectColor2 = False
End If

Code builds successfully, but it breaks with a message:
"Conversion from string "False" to type "Double" is not valid."

I tried dissecting the code, but can't find where my mistake is. I'm not even sure if this is the correct way to do what I want.
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on November 19, 2013, 07:39:48 AM
The addresses used in DZ_NZS must be pointing to boolean (or bit) values and returning "True" or "False". It is trying to convert this to a value so it can compare it to 0

If DS_NZS.Value<>"False" or DS_NAPON.Value<>"False" then

or

If DS_NZS.Value or DS_NAPON.Value then


Would it be easier to just put the tag names in PLCAddressSelectColor2 and PLCAddressSelectColor3 instead of trying to write your own VB code?
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on November 19, 2013, 08:15:52 AM
Would it be easier to just put the tag names in PLCAddressSelectColor2 and PLCAddressSelectColor3 instead of trying to write your own VB code?

Yes, it would. But, as I understand, then I'm limited to two bits for one indicator. I might need to link e.g. 4 or 5 status bits from PLC to one "General Error" Indicator.

Anyway, this is now working and I must thank you yet again. :)
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on November 25, 2013, 06:51:09 AM
Hello! I have another question.

If I have some instructions that should be executed only once, at startup of my application, how and where should I write them in code?
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on November 25, 2013, 07:18:01 AM
If I have some instructions that should be executed only once, at startup of my application, how and where should I write them in code?
Double click your MainForm to get back to the Form_Load event.
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on November 27, 2013, 04:17:15 AM
Thnx Archie.

For now I managed to initialize Excel file at the startup of application, as globally accessible. I have a hidden form which only purpose is data acquisition using DataSubscribers and periodical export (using timer) of selected data into Excel file, along with ID, date and time.

I have a button for quitting application in my MainForm and when pressed the following code is executed:

DataPolling.Excel_export.Enabled = False
GlobalVariables.oExcel_file1.Quit()
Enviroment.Exit(0)

DataPolling - hidden form with data subscribers
Excel_export - timer for periodical export of data
GlobalVariables - public class where I keep my global variables
oExcel_file1 - public object pointing to excel file

When I quit my application using my quit button, sometimes, Windows give message "AdvancedHMI has stopped working". If I comment the line disabling timer the application quits correctly. Is that line even necessary, am I obligated to stop timer when quitting application?
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on November 27, 2013, 09:52:30 AM
Most of the time you are not obligated to stop the timer. It depends on your code in the tick event. If the form begins to close just as the tick event fires, your code may access a resource that has been disposed and causing an exception or lock up.

I would actually encapsulate the timer disable in the form that contains the timer:

Code: [Select]
    Protected Overrides Sub OnFormClosing(e As System.Windows.Forms.FormClosingEventArgs)
        Excel_export.Enabled = False

        MyBase.OnFormClosing(e)
    End Sub
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on November 29, 2013, 04:04:45 AM
I modified my code as you suggested. For now it hasn't sent any errors.

I'm quite stuck on an another problem. I have an excel file with columns:
A - entry ID
B - date
C - time
D - data1
E - data2

I placed a chart object in my form. I would like to plot my data1 versus date and time. If it would make it easier, I can export date and time in one cell.

I tried several code examples I found on the internet, but had no luck. :(

Ultimately, I would like to have a drop down menu to select which data to plot (data1, data2, ....), two calendars to select start and stop date, and a basic button which would plot the data. But for the beggining, I would just like to be able to plot my excel data to a chart. Please help.

Also in Excel there are many chart styles. Is there a way to apply one of those styles to a chart in a form?
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on November 29, 2013, 09:19:04 AM
I'm a little confused with what is in Excel and what is on a Visual Studio form. Are you just storing the data in Excel and reading back in Visual Basic to show on a chart?
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on December 02, 2013, 02:15:51 AM
Yes, exactly.

Excel file is a storage file where I keep all my data logs. That file opens when my application starts. Applications periodically or on demand writes data to file with a timestamp and saves file after each write. File is open all the time the application is running.
I write my data to excel file from a form that is hidden, user never sees it, but is running in a background.

On a separate form, for when user wants to graphically analyze data, I placed a chart. From that form I will read data from Excel file and plot it in the chart.

I can't figure out that last part of reading and plotting the data.
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on December 02, 2013, 05:13:56 AM
And another question, when my application crashes for whatever reason, my excel files of course stay open, because application didn't exit properly. How can I "clean up" behind application so it closes all open files? I suppose this question could expand on how do I do a general garbage collection?

I'm sorry I'm so tiring and have so many questions, I would like to make this work. Really appreciate all you help.
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on December 02, 2013, 09:46:47 AM
What are you using to write to Excel within VB?
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on December 05, 2013, 04:15:34 AM
My global variables for excel files:

Code: [Select]
Public Class GlobalVariables
    '**************************************************************************************************
    'Excel file1
    'data log
    Public Shared CellIndexRow_file1 As Long = 2 'prvi red je zaglavlje
    Public Shared oExcel_file1 As Object
    Public Shared oBook_file1 As Object
    Public Shared oSheet_file1 As Object
    '**************************************************************************************************

    '**************************************************************************************************
    'Excel file2
    'event list
    Public Shared CellIndexRow_file2 As Long = 2 'prvi red je zaglavlje
    Public Shared oExcel_file2 As Object
    Public Shared oBook_file2 As Object
    Public Shared oSheet_file2 As Object
    '**************************************************************************************************
End Class

In load event function of my main form (actually called "PregledSustava"), this is code to set all the variables:
Code: [Select]
Private Sub MainForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        '**************************************************************************************************
        'Excel file1 initialization, initialization of pointera on first empty row in Excel
        'data log
        GlobalVariables.oExcel_file1 = CreateObject("Excel.Application")
        GlobalVariables.oExcel_file1 = New Excel.Application
        GlobalVariables.oExcel_file1.Workbooks.Open("E:\Documents\Documents\AdvancedHMI\Proba_Excell\AdvancedHMI\bin\Debug\excel_logs\HMItest.xlsx")
        GlobalVariables.oBook_file1 = GlobalVariables.oExcel_file1.Workbooks(1)
        GlobalVariables.oSheet_file1 = GlobalVariables.oBook_file1.Worksheets(1)
        While (GlobalVariables.oSheet_file1.Range("A" + CStr(GlobalVariables.CellIndexRow_file1)).Value <> 0)
            GlobalVariables.CellIndexRow_file1 = GlobalVariables.CellIndexRow_file1 + 1
        End While
        '**************************************************************************************************

        '**************************************************************************************************
        'Excel file2 initialization, initialization of pointera on first empty row in Excel
        'event log
        GlobalVariables.oExcel_file2 = CreateObject("Excel.Application")
        GlobalVariables.oExcel_file2 = New Excel.Application
        GlobalVariables.oExcel_file2.Workbooks.Open("E:\Documents\Documents\AdvancedHMI\Proba_Excell\AdvancedHMI\bin\Debug\excel_logs\event_log.xlsx")
        GlobalVariables.oBook_file2 = GlobalVariables.oExcel_file2.Workbooks(1)
        GlobalVariables.oSheet_file2 = GlobalVariables.oBook_file2.Worksheets(1)
        While (GlobalVariables.oSheet_file2.Range("A" + CStr(GlobalVariables.CellIndexRow_file2)).Value <> 0)
            GlobalVariables.CellIndexRow_file2 = GlobalVariables.CellIndexRow_file2 + 1
        End While
        '**************************************************************************************************

        '**************************************************************************************************
        'start timer for periodical export of data in Excel
        DataPolling.Excel_export.Enabled = True
        'period of data export in seconds or minutes
        DataPolling.Excel_export.Interval = 5 * 1000 '*60
        '**************************************************************************************************

        '**************************************************************************************************
        'DataPolling form must be activated to start polling data, then hide it and show MainForm
        DataPolling.Show()
        DataPolling.Hide()
        Me.Show()
        '**************************************************************************************************
    End Sub

In DataPolling form is a timer to periodically export data, this is function that handles timer tick:
Code: [Select]
Private Sub Excel_export_tick(sender As Object, e As EventArgs) Handles Excel_export.Tick
        '**************************************************************************************************
        'writing data in Excel columns A-E, row determined by CellIndexRow_file1
        GlobalVariables.oSheet_file1.Range("A" + CStr(GlobalVariables.CellIndexRow_file1)).Value = GlobalVariables.CellIndexRow_file1 - 1
        GlobalVariables.oSheet_file1.Range("B" + CStr(GlobalVariables.CellIndexRow_file1)).Value = DateString
        GlobalVariables.oSheet_file1.Range("C" + CStr(GlobalVariables.CellIndexRow_file1)).Value = TimeOfDay()
        GlobalVariables.oSheet_file1.Range("D" + CStr(GlobalVariables.CellIndexRow_file1)).Value = DS_INT1.Value
        GlobalVariables.oSheet_file1.Range("E" + CStr(GlobalVariables.CellIndexRow_file1)).Value = DS_INT2.Value
        'go to next row
        GlobalVariables.CellIndexRow_file1 = GlobalVariables.CellIndexRow_file1 + 1
        'save changes to file
        GlobalVariables.oBook_file1.Save()
        '**************************************************************************************************
    End Sub

Function of data subscriber in DataPolling form for DataChanged, writes event in excel when PLC input changes. This is where I get double entries in file for every event:
Code: [Select]
Private Sub DS_NZS_DataChanged(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles DS_NZS.DataChanged
'function that handles BasicIndicator color change
        Obradi_OpcaGreska()
        If DS_NZS.Value = True Then
            '**************************************************************************************************
            'write event in Excel event log
            GlobalVariables.oSheet_file2.Range("A" + CStr(GlobalVariables.CellIndexRow_file2)).Value = GlobalVariables.CellIndexRow_file2 - 1
            GlobalVariables.oSheet_file2.Range("B" + CStr(GlobalVariables.CellIndexRow_file2)).Value = DateString
            GlobalVariables.oSheet_file2.Range("C" + CStr(GlobalVariables.CellIndexRow_file2)).Value = TimeOfDay()
            GlobalVariables.oSheet_file2.Range("D" + CStr(GlobalVariables.CellIndexRow_file2)).Value = "ALARM Low level"
            GlobalVariables.oSheet_file2.Range("E" + CStr(GlobalVariables.CellIndexRow_file2)).Value = "Pumping station 1"
            GlobalVariables.oSheet_file2.Range("F" + CStr(GlobalVariables.CellIndexRow_file2)).Value = "General"
            'go to next row in file
            GlobalVariables.CellIndexRow_file2 = GlobalVariables.CellIndexRow_file2 + 1
            'save changes to file
            GlobalVariables.oBook_file2.Save()
            '**************************************************************************************************
        End If
    End Sub

When closing my main form:
Code: [Select]
Protected Overrides Sub OnFormClosing(e As System.Windows.Forms.FormClosingEventArgs)
        DataPolling.Excel_export.Enabled = False
        GlobalVariables.oExcel_file1.Quit()
        GlobalVariables.oExcel_file2.Quit()
        Environment.Exit(0)
        MyBase.OnFormClosing(e)
    End Sub
Title: Re: Processing signal and data in Advanced HMI
Post by: Archie on December 05, 2013, 08:06:03 AM
Try putting this in your main form:

Code: [Select]
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf MyApplication_UnhandledException
    End Sub

    Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As System.UnhandledExceptionEventArgs)
        '* Insert code to close open files
        MsgBox("Unhandled Exception occurred")
    End Sub
Title: Re: Processing signal and data in Advanced HMI
Post by: ENA on December 11, 2013, 03:53:38 AM
Works great! I have no open files left after application crash.