Imports System.IO.Ports Imports System.Windows.Forms Public Class weightForm Private weightSum As Integer Private switchMotion As Boolean = False Private weightErrorPlus As Integer Private weightErrorMinus As Integer Private weightMode As Boolean Private weightStart As Boolean Private Delegate Sub serialDelegate() Private updateDelegate As serialDelegate Private weightResult As Integer Private weightResult2 As Double = 0 Private zeroSet As Boolean = True Private weightBuffer As New List(Of Double) ' 무게 버퍼 Private Const BUFFER_SIZE As Integer = 3 ' 버퍼 크기 (3개로 축소) Private Const STABILITY_THRESHOLD As Double = 5.0 ' 안정성 임계값 (5g로 완화) Private weight(2) Private weight2(1) As String Private Sub weightForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load ZeroTimer.Enabled = True lbNowWeight.Text = Nothing lbWeightEX.Text = Nothing weightSum = mainForm.weightSum lbNowWeight.Refresh() lbWeightEX.Refresh() weightErrorPlus = Val(mainForm.txbWeightPlus.Text) weightErrorMinus = Val(mainForm.txbWeightMinus.Text) lbError.Text = "(오차: +" & weightErrorPlus & ", -" & weightErrorMinus & ")" weightResult = 0 zeroSet = True weightMode = mainForm.rdbWeightAuto.Checked weightStart = mainForm.weightStart End Sub Private Sub playTimer_Tick(sender As Object, e As EventArgs) Handles playTimer.Tick Dim scaleData As String If mainForm.rdbWeightAuto.Checked = True Then If weightResult > 0 Then statusTimer.Enabled = False playTimer.Enabled = False lbNowWeight.Text = weightResult If weight_compare() Then lbWeight.BackColor = Color.Green lbWeight.Text = "무게 일치" delay(2000) mainForm.weightResult = lbNowWeight.Text mainForm.weightOkNg = True Me.DialogResult = DialogResult.OK Else lbWeight.BackColor = Color.Red lbWeight.Text = "무게 불일치" delay(2000) mainForm.weightOkNg = False Me.DialogResult = DialogResult.No End If End If ElseIf mainForm.rdbWeightQW.Checked = True Then If weightResult2 > 5 Then ' 5g 이상이면 측정 시작 ' 실시간 무게 표시 lbNowWeight.Text = Math.Round(weightResult2, 0).ToString() lbWeight.BackColor = Color.Yellow lbWeight.Text = "측정중 (" & Math.Round(weightResult2, 0).ToString() & "g)" ' 무게 버퍼에 추가 (안정성 확인용) AddToWeightBuffer(weightResult2) ' 버퍼가 충분히 쌓이면 안정성 검사 If weightBuffer.Count >= 3 AndAlso IsWeightStable() Then statusTimer.Enabled = False playTimer.Enabled = False Dim stableWeight As Double = GetStableWeight() lbNowWeight.Text = Math.Round(stableWeight, 0).ToString() If weight_compare_improved(stableWeight) Then lbWeight.BackColor = Color.Green lbWeight.Text = "무게 일치" delay(2000) mainForm.weightResult = lbNowWeight.Text mainForm.txbCheckWeight.Text = lbNowWeight.Text mainForm.weightOkNg = True Me.DialogResult = DialogResult.OK Else zeroSet = False lbWeight.BackColor = Color.Red lbWeight.Text = "무게 불일치" ZeroTimer.Enabled = True End If End If End If Else scaleData = Mid(MeasureScale(200), 2, weight.Length) If scaleData > 5 Then statusTimer.Enabled = False lbWeight.BackColor = Color.Yellow lbWeight.Text = "측정중" playTimer.Enabled = False If AutoMeasureScale() Then lbNowWeight.Text = Val(weight(1)) If weight_compare() Then lbWeight.BackColor = Color.Green lbWeight.Text = "무게 일치" delay(2000) mainForm.weightResult = lbNowWeight.Text mainForm.txbCheckWeight.Text = lbNowWeight.Text mainForm.weightOkNg = True Me.DialogResult = DialogResult.OK Else zeroSet = False lbWeight.BackColor = Color.Red lbWeight.Text = "무게 불일치" ZeroTimer.Enabled = True End If Else lbWeight.Text = "무게 측정 불안정" lbWeight.BackColor = Color.Red End If End If End If End Sub ' 무게 버퍼에 추가하는 함수 Private Sub AddToWeightBuffer(weight As Double) weightBuffer.Add(weight) ' 버퍼 크기 초과 시 가장 오래된 값 제거 If weightBuffer.Count > BUFFER_SIZE Then weightBuffer.RemoveAt(0) End If End Sub ' 무게가 안정한지 확인하는 함수 Private Function IsWeightStable() As Boolean If weightBuffer.Count < BUFFER_SIZE Then Return False End If Dim maxWeight As Double = weightBuffer.Max() Dim minWeight As Double = weightBuffer.Min() ' 최대값과 최소값의 차이가 임계값보다 작으면 안정 Return (maxWeight - minWeight) <= STABILITY_THRESHOLD End Function ' 안정된 무게값을 얻는 함수 (평균값 사용) Private Function GetStableWeight() As Double If weightBuffer.Count = 0 Then Return 0 End If Return weightBuffer.Average() End Function ' 개선된 무게 비교 함수 Private Function weight_compare_improved(currentWeight As Double) As Boolean Dim targetWeight As Double = weightSum Dim upperLimit As Double = targetWeight + weightErrorPlus Dim lowerLimit As Double = targetWeight - weightErrorMinus Return currentWeight >= lowerLimit And currentWeight <= upperLimit End Function Private Sub Status_timer_Tick(sender As Object, e As EventArgs) Handles statusTimer.Tick If switchMotion = True Then lbWeight.BackColor = Color.MediumSlateBlue switchMotion = False Else lbWeight.BackColor = Color.Gold switchMotion = True End If End Sub Private Sub Zero_Timer_Tick(sender As Object, e As EventArgs) Handles ZeroTimer.Tick Dim scaledata As String Try If mainForm.rdbWeightAuto.Checked = True Then If zeroSet = True Then statusTimer.Enabled = True playTimer.Enabled = True ZeroTimer.Enabled = False lbWeightEX.Text = weightSum lbWeight.Text = "저울에 올려주세요" End If ElseIf mainForm.rdbWeightQW.Checked = True Then lbNowWeight.Text = Math.Round(weightResult2, 0).ToString() ' 무게 불일치 후 재측정 모드를 먼저 체크 If zeroSet = False Then ' 무게가 변경되었는지 확인 (이전 측정값과 5g 이상 차이나면 재측정 시작) Static previousWeight As Double = 0 If Math.Abs(weightResult2 - previousWeight) >= 5 Then ' 무게 변화 감지 - 재측정 시작 statusTimer.Enabled = True playTimer.Enabled = True ZeroTimer.Enabled = False lbWeightEX.Text = weightSum lbWeight.Text = "재측정 중..." lbWeight.BackColor = Color.Yellow ' 버퍼 초기화 weightBuffer.Clear() previousWeight = weightResult2 Else ' 무게 변화 없음 - 계속 대기 lbWeight.Text = "무게를 조정해주세요" lbWeight.BackColor = Color.Orange ZeroTimer.Enabled = True previousWeight = weightResult2 End If ElseIf weightResult2 <= 0 Then statusTimer.Enabled = True playTimer.Enabled = True ZeroTimer.Enabled = False lbWeightEX.Text = weightSum lbWeight.Text = "저울에 올려주세요" lbWeight.BackColor = Color.White Else ZeroTimer.Enabled = False lbWeight.Text = "저울을 비워주세요." lbWeight.BackColor = Color.Red ZeroTimer.Enabled = True End If Else scaledata = Mid(MeasureScale(200), 2, weight.Length) If scaledata = 0 Then statusTimer.Enabled = True playTimer.Enabled = True ZeroTimer.Enabled = False lbWeightEX.Text = weightSum lbWeight.Text = "저울에 올려주세요" Else ZeroTimer.Enabled = False lbWeight.Text = " 저울을 비워주세요" lbWeight.BackColor = Color.Red ZeroTimer.Enabled = True End If End If Catch ex As Exception ZeroTimer.Enabled = False mainForm.errorGen(Err.Description & "Zero_Timer_Tick_Scale_Error") End Try End Sub Private Function weight_compare() As Boolean If lbNowWeight.Text >= weightSum - weightErrorMinus And lbNowWeight.Text <= weightSum + weightErrorPlus Then Return True Else Return False End If End Function Public Sub delay(ByVal milliSecond As Double) Dim delayTime As Date = Now.AddSeconds(milliSecond / 1000) Do Until Now > delayTime Application.DoEvents() Loop End Sub Private Function MeasureScale2(timeout As Integer) As String 'Return "US,GS, " & weightResult2.ToString("F3") & " kg" Return "US,GS, " & (weightResult2 * 1000).ToString("F0") & " g" End Function Private Function AutoMeasureScale() As Boolean Try If mainForm.rdbWeightQW.Checked = True Then ' 2번 측정해서 무게가 거의 같으면 OK For i = 0 To 1 weight2(i) = MeasureScale2(200) ' 예: "US,GS, 0.901 kg" Next Dim w0 As Double = ParseWeightData(weight2(0)) Dim w1 As Double = ParseWeightData(weight2(1)) If Math.Abs(w0 - w1) < 10 Then ' 10g 이내 차이 (kg 단위면 0.01) Return True Else Return False End If End If Do For i = 0 To 1 weight(i) = MeasureScale(200) If Mid(weight(i), 1, 1) = "U" Then Exit For ElseIf Mid(weight(i), 1, 1) = "S" Then weight(i) = Mid(weight(i), InStr(1, weight(i), "S") + 1, weight(i).Length) If weight(i) = weight(1) Then Exit Do End If End If Next Loop If weight(0) - weight(1) < 10 And weight(0) - weight(1) > -10 Then Return True Else Return False End If Catch ex As Exception MsgBox("자동 무게 측정 에러 : " & Err.Description) Return False End Try End Function Private Sub Weight_Count_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed ZeroTimer.Enabled = False statusTimer.Enabled = False playTimer.Enabled = False End Sub Private Function ParseWeightData(data As String) As Double Try Dim m = System.Text.RegularExpressions.Regex.Match(data, "([-+]?\d+\.\d+|\d+)\s*(kg|g)") If m.Success Then Dim value As Double = Convert.ToDouble(m.Groups(1).Value) Dim unit As String = m.Groups(2).Value.ToLower() If unit = "kg" Then value = value * 1000 ' kg → g 변환 End If Return value ' g 단위로 반환 End If Catch ex As Exception Debug.Print("파싱 오류: " & ex.Message) End Try Return 0 End Function Private Sub QWSerialPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles QWSerialPort.DataReceived Try System.Threading.Thread.Sleep(300) '딜레이 Dim incoming As String = QWSerialPort.ReadExisting() 'Debug.Print("수신 데이터: " & incoming) ' 여러 줄이 들어올 수 있으니, 줄 단위로 분리 Dim lines() As String = incoming.Split({vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries) Dim maxWeight As Double = 0 For Each line As String In lines Dim w As Double = ParseWeightData(line) If w > maxWeight Then maxWeight = w Next weightResult2 = maxWeight 'Debug.Print(maxWeight) 'Debug.Print(weightResult2) If weightResult2 = 0 Then zeroSet = True Else zeroSet = False End If Catch ex As Exception Debug.Print("수신 오류: " & ex.Message) End Try End Sub Private Sub cmdSerialPort_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles cmdSerialPort.DataReceived Try If weightMode = True Then If weightStart = True Then Dim RecBuffer() As Byte Dim weightUse As Single = 0 Dim dataSet As String = "" Dim n As Integer = cmdSerialPort.BytesToRead RecBuffer = New Byte(n - 1) {} cmdSerialPort.Read(RecBuffer, 0, n) For cnt = 0 To RecBuffer.Length - 1 dataSet = dataSet & Chr(RecBuffer(cnt)) Next Dim dataCount As Int32 = UBound(Split(dataSet, vbCr)) - 1 For i = 0 To dataCount Dim weightData As Single = Mid(dataSet, 1, InStr(dataSet, vbCr) - 1) If weightData > weightUse Then weightUse = weightData End If If i <> dataCount Then dataSet = Mid(dataSet, InStr(dataSet, vbCr) + 1, dataSet.Length) End If Next weightResult = weightUse * 1000 If weightResult = 0 Then zeroSet = True Else zeroSet = False End If cmdSerialPort.DiscardInBuffer() cmdSerialPort.DiscardOutBuffer() Else cmdSerialPort.DiscardInBuffer() cmdSerialPort.DiscardOutBuffer() End If End If Catch ex As Exception MsgBox("데이터를 읽어올 수 없습니다. 통신을 확인하여 주십시오.", vbExclamation) End Try End Sub End Class