Quinn-Curtis Forums
Quinn-Curtis Forums
Home | Profile | Register | Active Topics | Members | Search | FAQ
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 Tools for Microsoft .Net
 SPC Control Chart Tools for .Net
 AutoLogAlarmsAsNotes selectively?
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

jkiecker

13 Posts

Posted - 12 Jun 2009 :  07:46:26  Show Profile  Reply with Quote
Working with a batch individual range chart:
I have AutoLogAlarmsAsNotes = True
I am populating the chart from a sql table.
I am also writing the note back to that table for history purposes.

What I would like to do is not log the notes for a particular record when certain conditions exist for that record.
Can I selectively remove the alarm info from the note?

Or is there a way to check the alarm for each record and selectively populate the note myself?

thanks

quinncurtis

1586 Posts

Posted - 12 Jun 2009 :  09:19:22  Show Profile  Reply with Quote
You can install an alarm event handler that will trap any alarm event. See the manual and the example TImeVariableControlCharts.DynamicXBarRChart. In the event handler you can write out your own notes record using

this.ChartData.SetNotesString(notesstring);
Go to Top of Page

jkiecker

13 Posts

Posted - 12 Jun 2009 :  11:24:24  Show Profile  Reply with Quote
I added this:
AddHandler Me.ChartData.AlarmStateEventHandler, AddressOf Me.SPCControlLimitAlarm
and I added a sub routine called SPCControlLimitAlarm
The sub routine never fires even though there are alarms on the chart... Do I need to do something else yet to enable it?

One other question:
I can use Me.ChartData().GetNotesString(i).ToString to get the note for a particular record by using its index. Is there also a way to set the value of the notestring using the index(i) after the chart has been displayed?
Go to Top of Page

quinncurtis

1586 Posts

Posted - 12 Jun 2009 :  16:50:11  Show Profile  Reply with Quote
From the TImeVariableControlCharts.DynamicXBarRChart example

AddHandler Me.ChartData.AlarmStateEventHandler, AddressOf Me.SPCControlLimitAlarm
' don't generate alarms in initial data simulation
Me.ChartData.AlarmStateEventEnable = False
.
.
.
'  generate alarms starting now
Me.ChartData.AlarmStateEventEnable = True



You can append to am exiting note using ChartData.AppendNotesString
Go to Top of Page

jkiecker

13 Posts

Posted - 16 Jun 2009 :  11:53:50  Show Profile  Reply with Quote
I still cant seem to get the event to fire. In the example you mentioned I cant get it to fire either if the timer is disabled. It only seems to fire when the timer adds a record with an alarm, not on the initial data load. That would lead me to believe that ChartData.AlarmStateEventEnable has to be set to true before rebuilding the chart, but I cant get it to work that way either?
Go to Top of Page

quinncurtis

1586 Posts

Posted - 16 Jun 2009 :  13:19:49  Show Profile  Reply with Quote
There have to be alarm limits to test against. Exactly how are you specifying the alarm limits before you start updating the chart using AddNewSampleRecord?
Go to Top of Page

jkiecker

13 Posts

Posted - 17 Jun 2009 :  07:15:57  Show Profile  Reply with Quote
I am specifying the alarm limits the same as in the example: It is in the sub that is called by the AddHandler statement. But the event never fires. In the example, it wont fire during the initial data load either, it only fires when the timer adds a record that has an alarm.

Private Sub SPCControlLimitAlarm(ByVal sender As Object, ByVal e As SPCControlLimitAlarmArgs)
Dim alarm As SPCControlLimitRecord = e.EventAlarm
Dim alarmlimitvalue As Double = alarm.ControlLimitValue
Dim alarmlimitvaluestring As [String] = alarmlimitvalue.ToString()

Dim spcData As SPCControlChartData = alarm.SPCProcessVar
Dim spcSource As SPCCalculatedValueRecord = e.SPCSource
Dim calculatedvaluestring As [String] = spcSource.CalculatedValue.ToString()

Dim message As [String] = alarm.AlarmMessage

If alarm.AlarmState Then
me.ChartData.AppendNotesString(message)
End If
Go to Top of Page

quinncurtis

1586 Posts

Posted - 17 Jun 2009 :  09:28:24  Show Profile  Reply with Quote
The code you reference in your last post has nothing to do with setting an alarm limit; it shows how to explicitly post existing alarm data in a note.

You're missing something in your logic. The alarm event is called when an alarm limit is exceeded. You MUST set the alarms BEFORE any alarm can be triggered. Most of our examples establish the alarms based on collected data, using the AutoCalculateControlLimits method.

No alarm events are triggered prior to, or during, the call of that method, because no alarms exist. So, if you are not calling AutoCalculateControlLimits you need to explicitly set the alarm limits BEFORE you start calling the AddNewSampleRecord method. This is discussed in the manual, page 182, section SPC Control Limits. Simple code would look something like this.

Dim controllimitvalues() As Double = {30, 28, 32, 10, 0, 22}
Me.ChartData.SetControlLimitValues(controllimitvalues)

Go to Top of Page

jkiecker

13 Posts

Posted - 17 Jun 2009 :  09:48:18  Show Profile  Reply with Quote
Yes my fault - sorry about the confusion,
I am using AutoCalculateControlLimits. Here is my code (excluding some of the sql statements to get external data):

Public Sub DrawChart()
Try
'get parameters:
...
'Open connections
...
'get part and operation description:
...
'get size, frequency, control limits, etc...
...
' Initialize the SPCBatchVariableControlChart
Me.InitSPCBatchVariableControlChart(charttype, numsamplespersubgroup, numdatapointsinview)
Me.GraphStartPosX = 0.175
Me.ChartData.TitleHeader = "" 'dont show the word "title:"
Me.ChartData.Title = strChar
Me.ChartData.PartNumber = strStockCode
Me.ChartData.ChartNumberHeader = strPartDescr
Me.ChartData.PartNameHeader = "Last " & strNumOfSamples & " samples"
Me.ChartData.Operation = strMachineCode & " - " & strOperDescr
Me.ChartData.MachineHeader = ""
Me.ChartData.OperatorHeader = "Size: " & strSize & " Frequency: " & strFrequency & " Lower Limit: " & strLowerLimit & " Upper Limit: " & strUpperLimit

Me.EnableNotes = True
Me.EnableInputStringsDisplay = True
Me.EnableCalculatedValues = True
Me.EnableTimeValues = False
Me.EnableScrollBar = True
Me.EnableDataToolTip = True
Me.EnableCategoryValues = False Me.TableAlarmEmphasisMode = SPCChartBase.ALARM_HIGHLIGHT_OUTLINE
Me.ChartAlarmEmphasisMode = SPCChartBase.ALARM_HIGHLIGHT_SYMBOL
Me.AutoLogAlarmsAsNotes = False'this would put the out of spec data in the note

'Add CPK, etc....
Me.ChartData.ProcessCapabilityLSLValue = strLowerLimit
Me.ChartData.ProcessCapabilityUSLValue = strUpperLimit
Me.ChartData.AddProcessCapabilityValue(SPCProcessCapabilityRecord.SPC_CPK_CALC)
Me.ChartData.AddProcessCapabilityValue(SPCProcessCapabilityRecord.SPC_CP_CALC)
Me.ChartData.ProcessCapabilityDecimalPrecision = 1
Me.ChartData.CalculatedValueDecimalPrecision = 4

'Display histograms:
Me.PrimaryChart.DisplayFrequencyHistogram = True
Me.SecondaryChart.DisplayFrequencyHistogram = True

'add event handler for alarms:
AddHandler Me.ChartData.AlarmStateEventHandler, AddressOf Me.SPCControlLimitAlarm
' don't generate alarms in initial data simulation
Me.ChartData.AlarmStateEventEnable = False

GetData() 'load chart data

'No lower control limit on secondary chart:
Dim secondarylowercontrollimit As SPCControlLimitRecord = ChartData.GetControlLimitRecord(SPCControlChartData.SPC_SECONDARY_LOWER_CONTROL_LIMIT)
secondarylowercontrollimit.ControlLimitType = SPCControlLimitRecord.SPC_NOTA_LIMIT

' Calculate control limits
Me.AutoCalculateControlLimits()
Me.AutoScalePrimaryChartYRange()
Me.AutoScaleSecondaryChartYRange()
Me.RebuildChartUsingCurrentData()

' generate alarms starting now
Me.ChartData.AlarmStateEventEnable = True

'get the upper and lower control limits that were calculated:
primaryUpperControlLimit = ChartData.GetControlLimitRecord(SPCControlChartData.SPC_PRIMARY_UPPER_CONTROL_LIMIT)
primaryLowerControlLimit = ChartData.GetControlLimitRecord(SPCControlChartData.SPC_PRIMARY_LOWER_CONTROL_LIMIT)

'move the scroll position to the last records.
If numOfSamplesLoaded > numdatapointsinview Then
Me.HScrollBar1.Value = Me.HScrollBar1.Maximum - numdatapointsinview + 3
End If

Catch ex As Exception
MsgBox(ex.ToString)
Finally
cnE.Close()
cnW.Close()
End Try

End Sub 'DrawChart
Go to Top of Page

quinncurtis

1586 Posts

Posted - 17 Jun 2009 :  10:10:23  Show Profile  Reply with Quote
Where do the the AddNewSampleRecord updates you want to trigger on occur in the code you show?

Do they occur before or after the call to AutoCalculateControlLimits?
Go to Top of Page

jkiecker

13 Posts

Posted - 17 Jun 2009 :  10:21:21  Show Profile  Reply with Quote
Yes, it is in the GetData() subroutine which is before the AutoCalculateControlLimits... here is the code. I also tried this using your SimulateData() sub in place of GetData() and still couldn't get it to fire?

Sub GetData()
'get chart data
strSQL = "SELECT Top " & strNumOfSamples & " APQP_SpcData.DrDate, APQP_SpcData.Note, APQP_SpcData.Measurement, APQP_ControlPlan.Size, APQP_ControlPlan.Frequency, " _
& "APQP_SpcData.Job, APQP_SpcData.Machine, APQP_SpcData.Count, APQP_SpcData.Characteristic, APQP_SpcData.Timestamp, " _
& "APQP_ControlPlan.UpperLimit, APQP_ControlPlan.LowerLimit, APQP_SpcData.EmpNo FROM APQP_SpcData " _
& "INNER JOIN APQP_ControlPlan ON APQP_ControlPlan.StockCode = APQP_SpcData.StockCode " _
& "AND RTRIM(LTRIM(APQP_ControlPlan.ProcessNum)) = RTRIM(LTRIM(APQP_SpcData.Machine)) AND APQP_ControlPlan.CharProduct = APQP_SpcData.Characteristic " _
& "WHERE APQP_SpcData.StockCode = '" & strStockCode & "' AND RTRIM(LTRIM(APQP_SpcData.Machine)) = '" & Trim(strMachineCode) & "' AND APQP_SpcData.Characteristic = '" & strChar & "' " _
& "AND NOT APQP_SpcData.Measurement IS NULL ORDER BY Timestamp DESC"

cmdW.CommandText = strSQL
rdrW = cmdW.ExecuteReader

'Loop trough records and create chart data:
While rdrW.Read
'get empName
strSQL = "SELECT Name FROM BomEmployee WHERE Employee = " & rdrW("EmpNo")
cmdE.CommandText = strSQL
rdrE = cmdE.ExecuteReader
rdrE.Read()
arrayEmp(i) = rdrE("Name")
rdrE.Close()

'load values in an array :
arrayJob(i) = rdrW("Job")
arrayCount(i) = rdrW("Count")
arrayMachine(i) = rdrW("Machine")
arrayMeasurement(i) = rdrW("Measurement")
If IsDBNull(rdrW("Note")) Then 'only populate the note with info if it is blank
arrayNote(i) = "Emp:" & arrayEmp(i) & vbNewLine & "Date: " & arrayTimestamp(i) & vbNewLine & rdrW("Note")
Else
arrayNote(i) = rdrW("Note")
End If
i += 1
numOfSamplesLoaded = i
End While

'read through the array backwards to load data in chart:
'this will put most current records to the right
For i = strNumOfSamples - 1 To 0 Step -1

samples = New com.quinncurtis.chart2dnet.DoubleArray
samples.Add(arrayMeasurement(i))
Me.ChartData.AddNewSampleRecord(samples, arrayNote(i))

Next
rdrW.Close()
End Sub
Go to Top of Page

quinncurtis

1586 Posts

Posted - 17 Jun 2009 :  10:46:15  Show Profile  Reply with Quote
Your GetData call occurs before the AutoCalculateControlLimits call. So when you call GetData, you have no alarm limits, therefore alarm events will not be triggered. You have alarm limits after the AutoCalculateControlLimits call, therefore alarm events will be triggered from that time forward. That is what your program is doing, and that's the way it supposed to work. If you are looking to customize the notes generated during the AutoCalculateControlLimits method, there is no way to do that using an alarm event.

Go to Top of Page

jkiecker

13 Posts

Posted - 17 Jun 2009 :  11:23:38  Show Profile  Reply with Quote
OK -- I see. Can I do one of the following instead?

1. Load the data to establish the limits then reload the data? This code seems to work and the event fires, but then my records are doubled. Is there a way to clear it before the second load?

GetData() 'load chart data

' generate alarms starting now
Me.ChartData.AlarmStateEventEnable = True

' Calculate control limits and ranges
Me.AutoCalculateControlLimits()

GetData() 're-load chart data

Me.AutoScalePrimaryChartYRange()
Me.AutoScaleSecondaryChartYRange()
Me.RebuildChartUsingCurrentData()

or

2. Loop through the records after they are loaded and check for the alarm myself? This code would work but I cant seem to find a way to set the note based on its index? is it possible?


'get the upper and lower control limits that were calculated:
primaryUpperControlLimit = ChartData.GetControlLimitRecord(SPCControlChartData.SPC_PRIMARY_UPPER_CONTROL_LIMIT)
primaryLowerControlLimit = ChartData.GetControlLimitRecord(SPCControlChartData.SPC_PRIMARY_LOWER_CONTROL_LIMIT)

For i = 0 To Me.ChartData.CurrentNumberRecords
'If no note has been logged yet:
If InStr(Me.ChartData().GetNotesString(i).ToString, "Alarm") = 0 Then
'if outiside the limit :
If CDbl(arrayMeasurement(i)) > CDbl(primaryUpperControlLimit.ControlLimitValue) Or CDbl(arrayMeasurement(i)) < CDbl(primaryLowerControlLimit.ControlLimitValue) Then
'using the index of the note, somehow manipulate the note here?
End If
End If
Next

Go to Top of Page

quinncurtis

1586 Posts

Posted - 17 Jun 2009 :  11:42:45  Show Profile  Reply with Quote
You can reset the chart data using the

ChartData.ResetSPCChartData()

method.
Go to Top of Page

jkiecker

13 Posts

Posted - 18 Jun 2009 :  09:38:17  Show Profile  Reply with Quote
Works great. Thanks.
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
Quinn-Curtis Forums © 2000-2018 Quinn-Curtis, Inc. Go To Top Of Page
Powered By: Snitz Forums 2000 Version 3.4.07