[VB.NET 2.0 & Ser. Com.] Waarde word niet altijd opgeslagen

Pagina: 1
Acties:
  • 178 views sinds 30-01-2008
  • Reageer

  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
Situatie
Ik werk binnen Visual Studio.NET met visual basic als taal aan een project waarbij via seriele communicatie een zogenaamde weger word aangesproken. De applicatie is een system tray applicatie welke een menu toont waarbij een aantal formulieren getoond kunnen worden. Het enige wat deze applicatie doet is ophalen van bepaalde strings uit het apparaat en weergeven in de applicatie. Dit werkt niet geheel honderd procent.

Om te communiceren met het apparaat maak ik gebruik van system.io.ports in combinatie met een module die gebruikt word in dit artikel: http://www.codeworks.it/net/VBNetRs232.htm.
Vervolgens maak ik gebruik van een seriele pc card met 2 poorten van sweex waarbij ik de beide volgens de handleiding van de weger geconfigureerd heb. Dit heb ik ook in de applicatie gedaan. Hieronder volgt een stukje code waarbij ik de poorten open:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
        'Port 5 properties
        With mRS232Port5
            .Port = 5
            .BaudRate = 9600
            .DataBit = 7
            .StopBit = Rs232.DataStopBit.StopBit_2
            .Parity = Rs232.DataParity.Parity_Even
            .Timeout = 1500
            .Open()
        End With

        'Port 6 properties
        With mRS232Port6
            .Port = 6
            .BaudRate = 9600
            .DataBit = 7
            .StopBit = Rs232.DataStopBit.StopBit_2
            .Parity = Rs232.DataParity.Parity_Even
            .Timeout = 1500
            .Open()
        End With

        'Check if ports are realy open
        If mRS232Port5.IsOpen And mRS232Port6.IsOpen Then
            sysTray.ShowBalloonTip(250, gFunction.ApplicationTitle(""), "Port " & mRS232Port5.Port & " and " & mRS232Port6.Port & " are opened and initialized." + _
                    CType(ChrW(13), [Char]) + "Calculations are started.", ToolTipIcon.Info)

            mRS232Port5.Dtr = True
            mRS232Port6.Dtr = True

            mRS232Port5.Rts = True
            mRS232Port6.Rts = True

            mRS232Port5.EnableEvents()
            mRS232Port6.EnableEvents()

Dit is alleen de relevante code.

Vervolgens word in een ander deel van de code de waarde opgehaald:

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    Sub Calculate(ByVal mRS232Port As Rs232, ByVal Weighingid As Int32, ByVal intWeigherid As Int16)
        'Create variables for storing TOTALS
        Dim strTotal2 As String
        Dim dblTotal2 As Double
       
 'Retrieve Total2 from the weigher
        Dim strRequestTotal2 As String
        strRequestTotal2 = "@01199999999949*" + ControlChars.Cr
        mRS232Port.Write(strRequestTotal2)
        mRS232Port.Read(17)
        strTotal2 = mRS232Port.InputStreamString
        strTotal2 = Mid(strTotal2, 6, 8)
        If IsNumeric(strTotal2) Then
            dblTotal2 = CType(strTotal2, Double)
        Else
            dblTotal2 = 0
        End If
    mRS232Port.PurgeBuffer(Rs232.PurgeBuffers.TxClear Or Rs232.PurgeBuffers.RXClear)

Dit is alleen de relevante code.

Deze code is werkt voor elke string hetzelfde. De applicatie voert deze string in: "@01199999999949” waarbij wij vervolgens een string terugkrijgen. Deze string bevat de waarde uit de weger en deze word dan in de database opgeslagen.

Probleem
Nu is het zo dat deze code hierboven niet altijd juist uitgevoerd word. De ene keer tijdens het debuggen word de waarde wel opgehaald en een andere keer niet. De variabele dblTotal2 word Ik kan tijdens het debuggen niet echt achterhalen wat er mis gaat. Zo gauw je een breakpoint zet en er doorheen stept word 8 van de tien keer de waarde gevuld. Zo gauw je zonder draait niet of 2 van de tien keer. Erg vaag en vrij allemaal. Het lijkt alsof het programma in runtime te snel draait wat de code niet de tijd geeft om alles op te halen. Threads gebruikt helpt ook niet een thread.sleep(5000) of thread.sleep(10000) tussen diverse regels van bovenstaande code plaatsten haalt niets uit.

Wat ik geprobeerd heb
- Debuggen en watches gedraaid en gezet. Zoals ik zei wordt de waarde soms gevuld. De weger zelf functioneerd prima. De applicatie van de fabrikant waarmee zij de weger testen werkt prima en leest altijd waarden uit.
- Veel gegoogled maar niets gevonden wat mij kan vertellen waarom de communicatie of het ophalen van de data zo sporadisch verloopt. Dit natuurlijk vanwege het feit dat ik een erg specifieke apparaat gebruik.
- Gezocht op GOT natuurlijk, ook niets nuttigs gevonden met betrekking tot sporadisch werkende communicatie.

Nu ligt mijn hoop hier. Ik ben bereid veel meer informatie te verstrekken en wilde in mijn TS vrij kort en bondig mijn probleem tonen en zo een niet al te lange mogelijk verwarrende post maken.

Hopelijk zijn jullie in staat mij te helpen.

[ Voor 2% gewijzigd door RobIII op 06-12-2006 15:26 ]

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
Zonder er echt ervaring mee te hebben, maar ben je zeker dat je wel altijd je buffers flushed als je een waarde wegschrijft ?

https://fgheysels.github.io/


  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
whoami schreef op woensdag 06 december 2006 @ 12:11:
Zonder er echt ervaring mee te hebben, maar ben je zeker dat je wel altijd je buffers flushed als je een waarde wegschrijft ?
Daar heb je een goed punt. Ik gebruik deze regel zoals ook gebruikt word in de applicatie op de site die ik in mijn TS noem:
Visual Basic:
1
    mRS232Port.PurgeBuffer(Rs232.PurgeBuffers.TxClear Or Rs232.PurgeBuffers.RXClear) 
Dit moet genoeg zijn al kan ik nog zoeken naar een mogelheid om de buffers op een "hardere manier" leeg te gooien en te controleren of ze leeg zijn. Wil het echt zo zijn dat het buffer gedeelte van een port niet altijd juist geleegd word?

[ Voor 0% gewijzigd door RobIII op 06-12-2006 15:26 ]

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 31-03 07:26

PhysicsRules

Dux: Linux voor Eenden

kan er een vertragingsprobleem optreden. Debuggen gaat langzamer. Wat gebeurt er als je tussen de write en read stap extra lang wacht?

  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
PhysicsRules schreef op woensdag 06 december 2006 @ 12:29:
kan er een vertragingsprobleem optreden. Debuggen gaat langzamer. Wat gebeurt er als je tussen de write en read stap extra lang wacht?
Het lijkt inderdaad een vertragingsprobleem. Zo gauw ik een breakpoint zet op declaratie van de string en ik loop met een tussenpauze van ongeveer 1 seconde door het blok dan word de waarde dblTotal2 gevuld. Het gekke is dat ik een blok als dit 4 keer gebruik (zie code). Steeds met een andere variable vb dblTotal1 die een andere waarde voorsteld. Deze regel word altijd uitgevoerd en altijd getoond8)7. Die laatste waarde dblTotal2 dus niet. Thread.Sleep(5000) na mRS232Port.InputStreamString in het laatste blok haalt niets uit. De waarde word niet gevuld.

Wat kan ik hieraan doen? Een andere vorm actie of propertie van thread gebruiken? Of een geheel andere methode zoeken?

Hier de code voor alle blokken:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
        'Create variables for storing TOTALS
        Dim strTotalToday, strTotalPrecDay, strTotal1, strTotal2 As String
        Dim dblTotalToday, dblTotalPrecDay, dblTotal1, dblTotal2 As Double

        'Retrieve previous day's total from the weigher
        Dim strRequestTotalPrecedentDay As String
        strRequestTotalPrecedentDay = "@01139999999943*" + ControlChars.Cr
        mRS232Port.Write(strRequestTotalPrecedentDay)
        mRS232Port.Read(17)
        strTotalPrecDay = mRS232Port.InputStreamString
        strTotalPrecDay = Mid(strTotalPrecDay, 6, 8)
        If IsNumeric(strTotalPrecDay) Then
            dblTotalPrecDay = CType(strTotalPrecDay, Double)
        Else
            dblTotalPrecDay = 0
        End If
        mRS232Port.PurgeBuffer(Rs232.PurgeBuffers.TxClear Or Rs232.PurgeBuffers.RXClear)

        'Retrieve(Daily) 's total from the weigher
        Dim strRequestTotalDaily As String
        strRequestTotalDaily = "@01149999999944*" + ControlChars.Cr
        mRS232Port.Write(strRequestTotalDaily)
        mRS232Port.Read(17)
        strTotalToday = mRS232Port.InputStreamString
        strTotalToday = Mid(strTotalToday, 6, 8)
        If IsNumeric(strTotalToday) Then
            dblTotalToday = CType(strTotalToday, Double)
        Else
            dblTotalToday = 0
        End If
        mRS232Port.PurgeBuffer(Rs232.PurgeBuffers.TxClear Or Rs232.PurgeBuffers.RXClear)

        'Retrieve Total1 from the weigher
        Dim strRequestTotal1 As String
        strRequestTotal1 = "@01159999999945*" + ControlChars.Cr
        mRS232Port.Write(strRequestTotal1)
        mRS232Port.Read(17)
        strTotal1 = mRS232Port.InputStreamString
        strTotal1 = Mid(strTotal1, 6, 8)
        If IsNumeric(strTotal1) Then
            dblTotal1 = CType(strTotal1, Double)
        Else
            dblTotal1 = 0
        End If
        mRS232Port.PurgeBuffer(Rs232.PurgeBuffers.TxClear Or Rs232.PurgeBuffers.RXClear)

        'Retrieve Total2 from the weigher
        Dim strRequestTotal2 As String
        strRequestTotal2 = "@01199999999949*" + ControlChars.Cr
        mRS232Port.Write(strRequestTotal2)
        mRS232Port.Read(17)
        strTotal2 = mRS232Port.InputStreamString
        strTotal2 = Mid(strTotal2, 6, 8)
        If IsNumeric(strTotal2) Then
            dblTotal2 = CType(strTotal2, Double)
        Else
            dblTotal2 = 0
        End If
        mRS232Port.PurgeBuffer(Rs232.PurgeBuffers.TxClear Or Rs232.PurgeBuffers.RXClear)

[ Voor 0% gewijzigd door RobIII op 06-12-2006 15:26 ]

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 31-03 07:26

PhysicsRules

Dux: Linux voor Eenden

Ik zou sowieso deze vier blokken code vervangen door één method die je vier keer aanroept. Dan kun je ook makkelijker bepalen of de fout misschien in een verkeerde input iod zit.

  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
PhysicsRules schreef op woensdag 06 december 2006 @ 13:34:
Ik zou sowieso deze vier blokken code vervangen door één method die je vier keer aanroept. Dan kun je ook makkelijker bepalen of de fout misschien in een verkeerde input iod zit.
Dat zou inderdaad een betere oplossing zijn. Maar ik kan me zo nog niet bedenken hoe ik dat het beste aanpakken en op welke manier ik te werk ga. Waarschijnlijk zoals nu een aantal strings defineren met de string voor het ophalen van de wegerinformatie (die code). Die string als parameter meegeven aan een methode of procedure en de waarde daarvan koppelen aan een variabele die in de database gaat. Iets in die geest.

Overigens vallende 4 blokken in een sub gedeelte die informatie binnenkrijgen als portnummer, weger id (de app. moet 2 wegers ondersteunen)
Visual Basic:
1
    Sub Calculate(ByVal mRS232Port As Rs232, ByVal Weighingid As Int32, ByVal intWeigherid As Int16)


Het opslaan gebeurt binnen sub calucale als volgt:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
            Dim AvroraConStr As New SqlConnection("Data Source=******;Initial Catalog=******;uid=******;pwd=******;")
            Dim insWeigherDataCommand As SqlCommand = New SqlCommand
            Dim dsWeigherData As DataSet = New DataSet
            insWeigherDataCommand = New SqlCommand("csp_InsertAmount", New SqlConnection(AvroraConStr.ConnectionString))
            insWeigherDataCommand.CommandType = CommandType.StoredProcedure
            dsWeigherData.Tables.Add("WEIGHERDATA")
            With insWeigherDataCommand.Parameters
                .Add(New SqlParameter("@am_weighing_id", SqlDbType.Int))
                .Add(New SqlParameter("@am_weigher_id", SqlDbType.SmallInt))
                .Add(New SqlParameter("@am_tot_daily", SqlDbType.Float))
                .Add(New SqlParameter("@am_tot_prec_day", SqlDbType.Float))
                .Add(New SqlParameter("@am_tot_1", SqlDbType.Float))
                .Add(New SqlParameter("@am_tot_2", SqlDbType.Float))
                .Add(New SqlParameter("@am_modifytype", SqlDbType.Char))
                .Add(New SqlParameter("@am_createuser", SqlDbType.SmallInt))

                .Item("@am_weighing_id").Value = Weighingid
                .Item("@am_weigher_id").Value = intWeigherid
                .Item("@am_tot_daily").Value = dblTotalToday
                .Item("@am_tot_prec_day").Value = dblTotalPrecDay
                .Item("@am_tot_1").Value = dblTotal1
                .Item("@am_tot_2").Value = dblTotal2
                .Item("@am_modifytype").Value = "I"
                .Item("@am_createuser").Value = 32001
            End With

            Try
                insWeigherDataCommand.Connection.Open()
                insWeigherDataCommand.ExecuteNonQuery()
            Catch ex As Exception
                MessageBox.Show(ex.Message, gFunction.ApplicationTitle(""), _
                    MessageBoxButtons.OK, MessageBoxIcon.Error)
            Finally
                insWeigherDataCommand.Connection.Close()
            End Try
        Catch exc As Exception
            MessageBox.Show(exc.Message, gFunction.ApplicationTitle(""), _
                                MessageBoxButtons.OK, MessageBoxIcon.Error)

[ Voor 0% gewijzigd door RobIII op 06-12-2006 15:26 ]

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • CodeIT
  • Registratie: Juni 2002
  • Laatst online: 01-12 21:22

CodeIT

Code IT

Staat er iets vermeld in de datasheet van de weger over de tijd die het nodig heeft om een waarde te retourneren. Misschien poll je te snel of te vaak. In het eerste geval kun je de readtimeout misschien verhogen.
Verder heb ik nog een vraag/opmerking. Als je .NET 2.0 gebruikt zit er een standaard SerialPort klasse in (System.IO.Ports.SerialPort). Kan je het niet alleen met die klasse oplossen?

[ Voor 7% gewijzigd door CodeIT op 06-12-2006 14:19 ]


  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
CodeIT schreef op woensdag 06 december 2006 @ 14:17:
Staat er iets vermeld in de datasheet van de weger over de tijd die het nodig heeft om een waarde te retourneren. Misschien poll je te snel of te vaak. In het eerste geval kun je de readtimeout misschien verhogen.
Ik heb niets kunnen vinden over een eventuele responstijd in de documentatie van de weger. De leverancier van de weger heeft een applicatie geleverd die altijd en vrijwel gelijk na het verzenden van een string een waarde retourneert. De applicatie, afkomstig van een Italiaans bedrijf, is een delphi applicatie en daar heb ik geen broncode van.
Verder heb ik nog een vraag/opmerking. Als je .NET 2.0 gebruikt zit er een standaard SerialPort klasse in (System.IO.Ports.SerialPort). Kan je het niet alleen met die klasse oplossen?
In het begin heb ik hier gebruik van gemaakt. Echter leek deze mij niet geschikt genoeg om in dit specifieke geval te gebruiken, feitelijk weet ik de echte precieze reden niet meer (ben er al een tijd mee bezig) 8)7.

Ik denk dat ik het toch moet zoeken in een timer of thread. Debuggen van het blok leert me dat ik op de een of andere manier een vertraging moet inbouwen in het aanroepen van de data. Hoe is me nu nog een raadsel.

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
[offtopic]
Als je nou [norml][code=vb] gebruikt i.p.v.
code:
1
[/norml] dan krijg je extragratis syntax-highlighting ;) Dat leest wel zo prettig :Y)
Arethusa schreef op woensdag 06 december 2006 @ 15:01:
Ik denk dat ik het toch moet zoeken in een timer of thread. Debuggen van het blok leert me dat ik op de een of andere manier een vertraging moet inbouwen in het aanroepen van de data. Hoe is me nu nog een raadsel.
Met de juiste keywords kom je een heel eind ;)

[ Voor 67% gewijzigd door RobIII op 06-12-2006 15:32 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
RobIII schreef op woensdag 06 december 2006 @ 15:28:
[offtopic]
Als je nou [norml][code=vb] gebruikt i.p.v.
code:
1
[/norml] dan krijg je extragratis syntax-highlighting ;) Dat leest wel zo prettig :Y)


[...]

Met de juiste keywords kom je een heel eind ;)
Bedankt voor die suggestie. Ik had al gezocht naar timers en threads maar wie weet levert het nu wel wat bruikbaars op.
offtopic:
Je hebt inderdaad gelijk wat betrefd die tags. Dat had ik moeten weten natuurlijk :X

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 17-10 16:43
als je er nu is een loopje van maakt? iets als

Visual Basic:
1
2
3
4
5
'Beginnen met pakken bestandje

While sString = ""
     'wacht
Wend


Ik denk dat als je thread.sleep gebruikt dat alles stil wordt gelegt ook dat gedeelte dat die string zou moeten pakken en dat je dus nog steeds het zelfde probleem houd, namelijk dat je alleen een waarde krijgt als je gelukt hebt (de "wager?" snel genoeg was)

Weet je trouwens wel zeker of de waardes altijd wel in een string passen? Als je weet hoelang de waarde precies zal zijn elke keer gebruik dan dim sString * 50

Suc6!

~ Mijn prog blog!


  • empheron
  • Registratie: Mei 2004
  • Laatst online: 10-03 14:26
edit : Ik realiseer me nu pas wat een lap code dit is... excuses...

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
Imports System.Threading
Imports System.IO.Ports

Public Class Weegschaal
    Private mut1 As New Mutex
    Private miComPort As Integer
    Private WithEvents WeegschaalPoort As SerialPort
    Public WeegschaalValue As String
    Public WeegschaalStacktrace As String
    Private BrutoGr As Integer = 0
    Private TaraGr As Integer = 0
    Public metingen As Int32 = 0
    Private Gelijkemetingen As Int32 = 3
    Private TellerNulstellen As Integer
    Private EventsEnabled As Boolean = False

#Region "PublicSubs"
    Public Sub New(ByRef ComPort As Integer)
        Try
            mut1.WaitOne()
            WeegschaalPoort = New SerialPort("COM" + ComPort.ToString(), 9600, Parity.None, 8, StopBits.One)
            WeegschaalPoort.DtrEnable = True
            WeegschaalPoort.RtsEnable = True
            WeegschaalPoort.ReceivedBytesThreshold = 100
            WeegschaalPoort.ReadTimeout = 1500
            WeegschaalPoort.Open()
            EventsEnabled = False
        Finally
            mut1.ReleaseMutex()
        End Try
    End Sub

    Public Sub Nulstellen()
        Try
            mut1.WaitOne()
            TaraGr = 0
            WeegschaalPoort.DiscardOutBuffer()
            WeegschaalPoort.Write("<" + "Y2" + ">")
        Finally
            mut1.ReleaseMutex()
        End Try
    End Sub

    Public Sub EnableEvents()
        Try
            mut1.WaitOne()
            If Not EventsEnabled Then
                AddHandler WeegschaalPoort.DataReceived, AddressOf WeegschaalHandler
                EventsEnabled = True
            End If
        Finally
            mut1.ReleaseMutex()
        End Try
    End Sub

    Public Sub DisableEvents()
        Try
            mut1.WaitOne()
            If EventsEnabled Then
                RemoveHandler WeegschaalPoort.DataReceived, AddressOf WeegschaalHandler
                EventsEnabled = False
            End If
        Finally
            mut1.ReleaseMutex()
        End Try
    End Sub

    Public Function GetBrutoGr() As Integer
        Dim tmpint As Integer
        tmpint = BrutoGr
        Return tmpint
    End Function
#End Region

#Region "privatesubs"

    Public Sub WeegschaalHandler(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
        Dim sBuf As String
        Dim positie As Integer
        Try
            mut1.WaitOne()
            sBuf = WeegschaalPoort.ReadExisting()
            WeegschaalPoort.DiscardInBuffer()
            Try
                WeegschaalValue = sBuf
                positie = InStr(sBuf, " G", CompareMethod.Text)
                WeegschaalValue = Trim(WeegschaalValue.Substring(positie, 12))
                Try
                    BrutoGr = Convert.ToInt32(DumpAZ(WeegschaalValue))
                Catch ex As Exception
                    BrutoGr = 0
                End Try
                metingen = metingen + 1
            Catch ex As Exception
'blabla code om entry in event log te knallen
            End Try
        Finally
            mut1.ReleaseMutex()
        End Try
    End Sub
#End Region
End Class


In bovenstaande code is het volgende erg belangrijk geweest om mijn weegschalen goed aan te sturen:
Visual Basic:
1
            WeegschaalPoort.ReceivedBytesThreshold = 100


Anders word soms het event afschoten voordat de complete string binnen is. Zelfde control gebruik ik ook voor barcode scanners, hierbij staat deze waarde op 15.

Over het algemeen denk ik dat je beter met de ingebouwde serialport klasse kunt werken. Het probleem dat jij omschrijft had ik ook (met dezelfde code) tot ik overstapte op .net 2.0 en de ingebouwde io-klasses. Hopelijk kun je mijn code hergebruiken om de overstap rond te krijgen :*)

[ Voor 17% gewijzigd door empheron op 06-12-2006 15:56 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
therat10430 schreef op woensdag 06 december 2006 @ 15:46:
Weet je trouwens wel zeker of de waardes altijd wel in een string passen? Als je weet hoelang de waarde precies zal zijn elke keer gebruik dan dim sString * 50
Dat kan niet meer in Vb.Net ;)
Het kan wel, maar met wat work-arounds en spullen die je helemaal niet wil gebruiken ;) Maar de manier die jij aangeeft werkt dus zowieso niet (meer)

[ Voor 26% gewijzigd door RobIII op 06-12-2006 16:04 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
empheron schreef op woensdag 06 december 2006 @ 15:52:
edit : Ik realiseer me nu pas wat een lap code dit is... excuses...

*grote knip*

In bovenstaande code is het volgende erg belangrijk geweest om mijn weegschalen goed aan te sturen:
Visual Basic:
1
            WeegschaalPoort.ReceivedBytesThreshold = 100


Anders word soms het event afschoten voordat de complete string binnen is. Zelfde control gebruik ik ook voor barcode scanners, hierbij staat deze waarde op 15.

Over het algemeen denk ik dat je beter met de ingebouwde serialport klasse kunt werken. Het probleem dat jij omschrijft had ik ook (met dezelfde code) tot ik overstapte op .net 2.0 en de ingebouwde io-klasses. Hopelijk kun je mijn code hergebruiken om de overstap rond te krijgen :*)
Bedankt voor je code en je tip. Ik denk dat ik daar wel wat aan heb. Ik zal alsnog proberen mijn code om te bouwen met behulp van de serial port klasse. Het is wel interessant om te weten dat jij ook gebruik hebt gemaakt van de code van de website die ik in mijn TS noemde. Het lijkt erop dat dat echt specifiek voor modem gebruik gemaakt is.

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Volgens mij zijn je problemen dezelfde als de mensheid altijd heeft met dit soort dingen : timing

Mijn ervaringen:
- altijd een timeout constructie maken.
- gebruik geen busyloops
- gebruik niet (alleen) events maar ook een pollmechanisme voor het geval een event niet aankomt ( Ja dat gebeurt echt een keer )

Samen maken deze punten dat je eigenlijk altijd een timer nodig hebt die je compoort polled en de timeout controleert ( of als je app dat niet toestaat een poll actie in je main loop die hetzelfde doet ).

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • CodeIT
  • Registratie: Juni 2002
  • Laatst online: 01-12 21:22

CodeIT

Code IT

Arethusa schreef op woensdag 06 december 2006 @ 15:01:
[...]

Ik heb niets kunnen vinden over een eventuele responstijd in de documentatie van de weger. De leverancier van de weger heeft een applicatie geleverd die altijd en vrijwel gelijk na het verzenden van een string een waarde retourneert. De applicatie, afkomstig van een Italiaans bedrijf, is een delphi applicatie en daar heb ik geen broncode van.
Ik gebruik zelf de ReadTimeOut property als timeout. Als ik een write heb gedaan ga ik wachten tot ik een x aantal bytes binnen heb. Als er geen data is retourneert de methode Read geen bytes.
Ik heb de code om de bytes te lezen wel in een thread gebouwd (heb een UI die ook moet worden geupdate) die op zijn beurt een delegate invoked als er data is binnengekomen of als er een timeout is opgetreden.

Verwijderd

Ik heb goede resultaten gehaald met een barcode scanner met de volgende techniek:

De serieele poort uit System.IO.Ports
Een zelf gebakken buffer( niet meer dan een List(Of byte) met een paar tweaks)
Het DataReceived event van de SerialPort

De scanner stuurt bij elke gescande barcode <STX>barcode<ETX>
(<STX> en <ETX> zijn de ASCII codes voor 0x02 en 0x03)
Dat maakt het makkelijk doordat je dan weet wanneer je data pakketje ophoudt en je de read timeout niet hoeft te gebruiken om te wachten tot je alles binnen hebt.

Ik vul mijn buffer bij elk DataReceived event en als ik na een paar events <ETX> tegenkom dan vuurt een tweede event met het hele bericht waar mijn app dan weer naar luistert.
met een timertje die je in elke DataReceived event reset kan je dan eventueel detecteren of je apparaat uit staat en echt niet meer gaat antwoorden.

Voor het programmeren van de scanner doe ik het zonder events
dan schrijf ik eerst een commando naar de scanner en doe dan in een while loop Read()'s van 8 bytes waarmee ik m'n buffer vul totdat ik het antwoord helemaal binnen heb.
Een voordeel van deze manier is dat je zelf je Read grootte kan bepalen en niet afhankelijk bent van de lengte van het bericht
Die afhankelijkheid geeft namelijk vervelende interactie met je read timeout als timeout < (lengte bericht / baudrate ) soms waar is en soms niet.
nog een voordeel is dat je makkelijk progress eventjes kan afvuren als je veel moet lezen.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Verwijderd schreef op woensdag 06 december 2006 @ 23:49:
Ik heb goede resultaten gehaald met een barcode scanner met de volgende techniek
Een timeout timer resetten in je received event is idd ook een methode om iets dergelijks te bouwen. Een read timeout heb je altijd nodig btw, ook als je start/stop karakters in je protocol hebt zitten.

De rest van wat je beschrijft heeft een aantal beperkingen:

- Een While ByteReceived Loop contructie komt neer op blocking communicatie. Soms (vaak?) is dat niet gewenst tenzij je multithreaded gaat werken. Dat heeft weer een heleboel andere consequenties.
- Een readtimeout op een seriele poort is vaak een timeout op het complete bericht*, al dan niet vanaf het moment dat het eerste karakter wordt ontvangen. Wat gebeurd er als er helemaal niets wordt ontvangen? ( *Eea werkt samen met een receive count )
- Niet ASCII protocollen hebben vaak geen start en stop karakter. Dat maakt het allemaal wat complexer.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

farlane schreef op donderdag 07 december 2006 @ 09:20:
[...]
- Een While ByteReceived Loop contructie komt neer op blocking communicatie. Soms (vaak?) is dat niet gewenst tenzij je multithreaded gaat werken. Dat heeft weer een heleboel andere consequenties.
blocken is mijn programmeer situatie juist fijn, want je wil geen onverwachte data naar je apparaat sturen als je aan het flashen bent. :9 en 't is idd een multithreaded server app omdat ie meerdere scanners tegelijk moet aansturen, en meerdere clients moet kunnen servicen om de scanners te kunnen monitoren/programmeren/testen. tis maar net wat je use case is natuurlijk

ook heb ik gemerkt dat ook al is de receive buffer van de System.IO.Port.SerialPort groot genoeg voor het hele bericht, en is de timeout meer dan genoeg, dat je toch soms meerdere reads moet doen /meerdere events gevuurd worden om 't hele bericht binnen te krijgen,
maar dat zou zommar ook kunnen liggen aan het feit dat de scanners altijd aan serial2ethernet converters zijn aangesloten die op de server dan weer net doen alsof ze een echte serieele port zijn m.b.v. een drivertje. funky, maar werkt voor de rest als een speer.

  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
Het programma werkt inmiddels en draait naar behoren. Ter aanvulling op dit topic een stukje code waarmee data uit de weger gehaald word. Dit is de belangrijkste code:

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        'Retrieve Previous day's total from the weigher
        Dim strRequestTotalPrecDay As String
        Dim chrRequestTotalPrecDay(2500) As Char
        strRequestTotalPrecDay = "@01139999999943*" + ControlChars.Cr
        If Not mRS232Port.IsOpen Then
            mRS232Port.Open()
        End If
        If mRS232Port.IsOpen Then
            mRS232Port.Write(strRequestTotalPrecDay)
            Thread.Sleep(500)
            strTotalPrecDay = mRS232Port.ReadExisting
            strTotalPrecDay = Mid(strTotalPrecDay, 6, 8)
            If IsNumeric(strTotalPrecDay) Then
                dblTotalPrecDay = CType(strTotalPrecDay, Double)
            Else
                dblTotalPrecDay = 0
            End If
        End If
        Thread.Sleep(500)


Gebruik van threading, en uiteraard het juist werken van hardware en com-poorten, bracht uiteindelijke een werkende versie op. Overige code wil ik op verzoek ook wel openbaar maken. Wellicht dat iemand anders er baat bij kan hebben. Iedereen: bedankt voor het meedenken en het geven van aanvullende informatie en tips _/-\o_

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Ik met zeggen dat ik je foutcontrole behoorlijk karig vind. Het enige dat je controleert is of een aantal opeenvolgende karakters in het bericht numeriek zijn.

- Zit er geen start/stop karakter in? ( Aangezien je ASCII karakters binnenkrijgt )
- Zit er geen source/destination adres in?
- Zit er geen reply type indicatie in ( dus wat voor een soort antwoord het is ) ?
- etc

Onthoud dat omdat het 4 dagen bij jouw op je bureau goed heeft gedraaid je niet kunt zeggen dat daarom dus betrouwbaar/stabiel is.

[ Voor 15% gewijzigd door farlane op 18-12-2006 08:54 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Arethusa
  • Registratie: December 2003
  • Laatst online: 07:54

Arethusa

Niet die server

Topicstarter
farlane schreef op maandag 18 december 2006 @ 08:53:
Ik met zeggen dat ik je foutcontrole behoorlijk karig vind. Het enige dat je controleert is of een aantal opeenvolgende karakters in het bericht numeriek zijn.

- Zit er geen start/stop karakter in? ( Aangezien je ASCII karakters binnenkrijgt )
- Zit er geen source/destination adres in?
- Zit er geen reply type indicatie in ( dus wat voor een soort antwoord het is ) ?
- etc

Onthoud dat omdat het 4 dagen bij jouw op je bureau goed heeft gedraaid je niet kunt zeggen dat daarom dus betrouwbaar/stabiel is.
Mijn foutcontrole is inderdaad karig. Dit heeft een reden en de reden is helaas tijdgebrek. Ik ben me ervan bewust dat een goede foutcontrole een must is. Het programma draait op een plek waar ik ten alle ten alle tijde op afstand bij kan. Mogelijke problemen kunnen snel opgelost worden. De verwachting is ook dat er een uitbreiding van het programma komt waarin we dan eventueel alle overige tekortkomingen zoals een uitgebreide foutcontrole kunnen opnemen.
Wat betrefd je vragen:
- Zit er geen start/stop karakter in? ( Aangezien je ASCII karakters binnenkrijgt )
- Zit er geen source/destination adres in?
- Zit er geen reply type indicatie in ( dus wat voor een soort antwoord het is ) ?
- etc
- De handleiding geeft het volgende als host computer call string:
@XXYYDDDDDDDDFF*CR
De @ is de startsting en cr is de stop string
- De handleiding meld niets over een source/destination adres
- Het antwoord wat ik van de weger krijg, ik neem aan dat je dat bedoeld met reply type indicatie, is een string.

De handleiding meld alleen wat over de portinstellingen, de verklaring van commandos en requests en hoe die de string vormen, dit geld voor zowel het signaal naar de weger, als van de weger terug.

Heb je misschien tips om het in de toekomst beter op te lossen qua foutoplossing? Ik weet dat je niet de beschikking hebt over alle code maar misschien kun je wat tips van de hand doen.

[ Voor 5% gewijzigd door Arethusa op 18-12-2006 09:18 ]

I've been mad for fucking years, absolutely years, been over the edge for yonks.
Vinyl: Discogs


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
Arethusa schreef op maandag 18 december 2006 @ 09:15:
Heb je misschien tips om het in de toekomst beter op te lossen qua foutoplossing? Ik weet dat je niet de beschikking hebt over alle code maar misschien kun je wat tips van de hand doen.
Ik weet natuurlijk niet tot in detail hoe je protocol eruit ziet, maar dit soort protocollen kennende ( dwz vrotprotocollen, vaak Duitse herkomst :) ) is er niet heel veel mogelijkheid tot controle. De basisdingen waar je rekening mee zou kunnen houden:

- Indien mogelijk, houd rekening met start en stop karakters. De velden in het frame zou je moeten bepalen vanaf het startkarakter.
- Controleer de lengte van het bericht dat je binnenkrijgt. ( Dus ga niet door met een oneindige lange buffer maken als er op een op ander manier geen stop karakter binnenkomt maar wel een hele stroom andere karakters )
- Indien mogelijk, controleer of het antwoord dat je krijgt bij de vraag hoort die je gesteld hebt. ( dat bedoelde ik met een reply type indicatie. ( Dus een vraag 'stuur weging' die wordt beantwoord met 'tarra uitgevoerd' moet worden afgekeurd bijvoorbeeld ).
- Indien mogelijk controleer de checksum (if any) van het bericht.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1