Author |
Topic |
|
jkiecker
13 Posts |
Posted - 12 Jun 2009 : 07:46:26
|
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
|
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); |
|
|
jkiecker
13 Posts |
Posted - 12 Jun 2009 : 11:24:24
|
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? |
|
|
quinncurtis
1586 Posts |
Posted - 12 Jun 2009 : 16:50:11
|
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 |
|
|
jkiecker
13 Posts |
Posted - 16 Jun 2009 : 11:53:50
|
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? |
|
|
quinncurtis
1586 Posts |
Posted - 16 Jun 2009 : 13:19:49
|
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? |
|
|
jkiecker
13 Posts |
Posted - 17 Jun 2009 : 07:15:57
|
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
|
|
|
quinncurtis
1586 Posts |
Posted - 17 Jun 2009 : 09:28:24
|
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)
|
|
|
jkiecker
13 Posts |
Posted - 17 Jun 2009 : 09:48:18
|
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 |
|
|
quinncurtis
1586 Posts |
Posted - 17 Jun 2009 : 10:10:23
|
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? |
|
|
jkiecker
13 Posts |
Posted - 17 Jun 2009 : 10:21:21
|
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 |
|
|
quinncurtis
1586 Posts |
Posted - 17 Jun 2009 : 10:46:15
|
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.
|
|
|
jkiecker
13 Posts |
Posted - 17 Jun 2009 : 11:23:38
|
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
|
|
|
quinncurtis
1586 Posts |
Posted - 17 Jun 2009 : 11:42:45
|
You can reset the chart data using the
ChartData.ResetSPCChartData()
method. |
|
|
jkiecker
13 Posts |
Posted - 18 Jun 2009 : 09:38:17
|
Works great. Thanks. |
|
|
|
Topic |
|