PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197
Receiving data from serial port - Page 2-VBForums
Page 2 of 3 FirstFirst 123 LastLast
Results 41 to 80 of 103

Thread: Receiving data from serial port

  1. #41
    Hyperactive Member
    Join Date
    Sep 2009
    Location
    Lost in thought
    Posts
    349

    Re: Receiving data from serial port

    My motto for Life,
    If all else fails THEN read the instructions

    Here is Wat I think now I've looked at the instructions,
    In a module make a user-defined Type.

    'Pseudo code
    Code:
    Option Explicit
    Public Enum DataPacketsType
          icWindData = &H0
          icRainData = &H1
     '.....so on
    End Enum
    
    Public Enum DataByteCount
          bcWindData = 11
          bcRainData = 16
     '.....so on
    End Enum
    
    Public Type aCommDataPackets
     WindData(1 To 8) As Byte
     RainData(1 To 13) As Byte
     '.....so on
    End Type
    
    Public PacketArr(60) As aCommDataPackets
    Public thisDataPacketsType As DataPacketsType
    Public bcCount As DataByteCount
    Public secCount&, ByteCount&
    Public MoorGoodDataForMe As Boolean
    #1 In the Timer1,
    Timer1 is set to 1sec, and have a Count, i.e Dim secCount&
    Set MoorGoodDataForMe To True
    Set DTREnable To True. ......... Now the WMR-968 will send info to you.

    #2 Count Bytes, in the MSComm1_OnComm, ie Dim ByteCount&

    #3 Read 3rd Byte, in the MSComm1_OnComm, WindData = 0 and RainData = 1 '.....so on

    Code:
    Private Sub MSComm1_OnComm()
      Dim thisByte As Variant
          thisByte = MSComm1.Input
          ByteCount = ByteCount + 1
        Select Case ByteCount
           Case 3  'the 3rd Byte
                  thisDataPacketsType = thisByte
                Select Case thisDataPacketsType
                      Case 0: bcCount = bcWindData
                      Case 1: bcCount = bcRainData: MoorGoodDataForMe = False
                        MSComm1.PortOpen = False
    
                       '.....so on
                End Select
           Case Is > 3
                If ByteCount < bcCount Then addToPacketArr thisByte
                If ByteCount = bcCount Then
                 ByteCount = 0
                addToPacketArr MSComm1.Input
                End If
        End Select
      If ByteCount = 0 And Not MoorGoodDataForMe Then MSComm1.DTREnable = False: ProcessWMR968Data
    End Sub
    
    Private Sub addToPacketArr(MSCInput As Variant)
                 Select Case thisDataPacketsType
                      Case bcWindData: PacketArr(secCount).WindData(ByteCount) = MSCInput
                      Case bcRainData: PacketArr(secCount).RainData(ByteCount) = MSCInput
                       '.....so on
                End Select
    End Sub
    
    Public Sub ProcessWMR968Data()
    
    End Sub
    Now you'll get the Data from WMR-968 the each second
    #4 Process the Data from WMR-968

    That should give you time



    ......
    .

    The answer to your question is Here
    And here
    C:\Program Files\Microsoft Visual Studio\MSDN98\98VSa\1033\SAMPLES\VB98

    Please go to the "Thread Tools" menu at the top of this Thread, and click "Mark Thread Resolved" when you have your answer.
    So I can fine the answer when I need it.

    how to stop the playsound when it is in loop..Play more than 1 sound at a time..
    ini file Check if IP changed Strings 'Split', 'Left' and 'Right'
    Save And Load an Array of list-boxes, to and from a file......list-box and CommonDialog
    Quote Originally Posted by RobDog888

    So please install VB6 service pack 6 as its the latest and last supported service pack MS will ever make.
    http://support.microsoft.com/kb/q198880/ I'm sure this will fix your issue
    The only reason some people get lost in thought is because it’s unfamiliar territory. —Paul Fix

  2. #42
    Hyperactive Member
    Join Date
    Sep 2009
    Location
    Lost in thought
    Posts
    349

    Re: Receiving data from serial port

    How to Read bit Data in vb, I do not know, but I would like to.
    In the protocol shown as Bytes of 7bits

    MSComm1.InputMode = comInputModeBinary

    Byte1 =FF, is ok, it's a Header
    Byte2 =FF, is ok, it's a Header
    Byte3 =Device type, is ok to

    But
    4th Byte
    Bit1 of Byte4 = -
    Bit2 of Byte4 = -
    Bit3 of Byte4 = -
    Bit4 of Byte4 = some Data, 1
    Bit5 of Byte4 = some Data, 2
    Bit6 of Byte4 = some Data, Low batt.
    Bit7 of Byte4 = -

    How do I Read the 4th Byte.

    I posted this in a new thread
    .
    Last edited by 5ms?; Oct 23rd, 2009 at 04:11 PM.
    .

    The answer to your question is Here
    And here
    C:\Program Files\Microsoft Visual Studio\MSDN98\98VSa\1033\SAMPLES\VB98

    Please go to the "Thread Tools" menu at the top of this Thread, and click "Mark Thread Resolved" when you have your answer.
    So I can fine the answer when I need it.

    how to stop the playsound when it is in loop..Play more than 1 sound at a time..
    ini file Check if IP changed Strings 'Split', 'Left' and 'Right'
    Save And Load an Array of list-boxes, to and from a file......list-box and CommonDialog
    Quote Originally Posted by RobDog888

    So please install VB6 service pack 6 as its the latest and last supported service pack MS will ever make.
    http://support.microsoft.com/kb/q198880/ I'm sure this will fix your issue
    The only reason some people get lost in thought is because it’s unfamiliar territory. —Paul Fix

  3. #43
    Hyperactive Member
    Join Date
    Sep 2009
    Location
    Lost in thought
    Posts
    349

    Re: Receiving data from serial port

    FF FF 00 00 39 00 01 00 20 00 58 (Anemometer and Wind Data)
    I read this as,
    Byte1: FF=Header 1, 11111111
    ----------------------------------------
    Byte2: FF=Header 2, 11111111
    ----------------------------------------
    Byte3: 00=wind, 00000000
    ----------------------------------------
    Byte4: 00=, 00000000
    Bit0 Byte4:=0
    Bit1 Byte4:=0
    Bit3 Byte4:=0
    Bit4 Byte4:=0,=Gust over
    Bit5 Byte4:=0,=Avgerage over
    Bit6 Byte4:=0,=Low batt.
    Bit7 Byte4:=0
    ----------------------------------------
    Byte5: 39=, 00111001
    Bit0,1,2,3: 0011= Winddirection1&#176; digit
    Bit4,5,6,7: 1001= Winddirection10&#176; digit
    ----------------------------------------
    Byte6: 00=, 0000000
    Bit0,1,2,3: 0000= Winddirection100&#176; digit
    Bit4,5,6,7: 0000= GustWindSpeed0.1m/sec
    ----------------------------------------
    Byte7: 01=, 00000001
    Bit0,1,2,3: 0000= GustWindSpeed1 m/sec
    Bit4,5,6,7: 0001= GustWindSpeed10 m/sec
    ----------------------------------------
    Byte8: 00=, 00000000
    Bit0,1,2,3: 0000= AverageWindSpeed0.1 m/sec
    Bit4,5,6,7: 0000= AverageWindSpeed1 m/sec
    ----------------------------------------
    Byte9: 20=, 00100000
    Bit0,1,2,3: 0010= AverageWindSpeed10 m/sec
    Bit4: 0= -
    Bit5: 0= Chill no data
    Bit6:0= Chill over
    Bit7:0= Sign
    ----------------------------------------
    Byte10: 00=, 00000000
    Bit0,1,2,3: 0000= WindChill1&#176;Cdigit
    Bit4,5,6,7: 0000= WindChill10&#176;Cdigit
    ----------------------------------------
    Byte11: 58=, 01011000 = Check-sum
    ----------------------------------------

    Is that, could this be ????????????????

    Not to be disrespectful
    In other words, if not, I did some experimenting, had some fun, and learn something new in the process.
    Sorry for the confusion.
    .

    The answer to your question is Here
    And here
    C:\Program Files\Microsoft Visual Studio\MSDN98\98VSa\1033\SAMPLES\VB98

    Please go to the "Thread Tools" menu at the top of this Thread, and click "Mark Thread Resolved" when you have your answer.
    So I can fine the answer when I need it.

    how to stop the playsound when it is in loop..Play more than 1 sound at a time..
    ini file Check if IP changed Strings 'Split', 'Left' and 'Right'
    Save And Load an Array of list-boxes, to and from a file......list-box and CommonDialog
    Quote Originally Posted by RobDog888

    So please install VB6 service pack 6 as its the latest and last supported service pack MS will ever make.
    http://support.microsoft.com/kb/q198880/ I'm sure this will fix your issue
    The only reason some people get lost in thought is because it’s unfamiliar territory. —Paul Fix

  4. #44
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    I've been put together a packet interpreter engine thing, that might be helpful for those who are playing with serial inputs.

    http://www.vbforums.com/showthread.php?t=588994

    How to Read bit Data in vb, I do not know, but I would like to.
    It's quite easy. You just have to use the AND operator, that will help you to find out a given bit is set or not (true/false)

    Here is an example.

    vb Code:
    1. Public Function ByteToBit10(ByVal b As Long) As String
    2. ' by Jost Schwider, [email]jost@schwider.de[/email], 20001228, rev 001
    3. ' based on ByteToBit02 by Donald, [email]donald@xbeat.net[/email], 20001206
    4.   ByteToBit10 = "00000000"
    5.   If b And &H1& Then MidB$(ByteToBit10, 15&) = "1" '1
    6.   If b And &H2& Then MidB$(ByteToBit10, 13&) = "1" '2
    7.   If b And &H4& Then MidB$(ByteToBit10, 11&) = "1" '4
    8.   If b And &H8& Then MidB$(ByteToBit10, 9&) = "1"  '8
    9.   If b And &H10& Then MidB$(ByteToBit10, 7&) = "1" '16
    10.   If b And &H20& Then MidB$(ByteToBit10, 5&) = "1" '32
    11.   If b And &H40& Then MidB$(ByteToBit10, 3&) = "1" '64
    12.   If b And &H80& Then MidB$(ByteToBit10, 1&) = "1" '128
    13. End Function

    This will output you the bit map as a string data. You can also find more examples here, and speed test which formula is the fastest.
    http://www.xbeat.net/vbspeed/c_ByteToBit.htm

  5. #45
    PowerPoster CDRIVE's Avatar
    Join Date
    Jul 2007
    Posts
    2,620

    Re: Receiving data from serial port

    That is very clever Jim!
    <--- Did someone help you? Please rate their post. The little green squares make us feel really smart!
    If topic has been resolved, please pull down the Thread Tools & mark it Resolved.


    Is VB consuming your life, and is that a bad thing??

  6. #46
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    Jim, Sleep() does not exist in VB6 (or I couldn't find). Even if it exist I'm afraid it is using system clock, is so sleep time is restricted in multiples of about 50ms.

    To convert byte to bit string I'm using a table for nibbles. In Form_Load define 16 array of string as :
    BitPat(0) = "0000"
    BitPat(1) = "0001"
    BitPat(2) = "0010"
    BitPat(3) = "0011"
    BitPat(4) = "0100"
    BitPat(5) = "0101"
    BitPat(6) = "0110"
    BitPat(7) = "0111"
    BitPat(8) = "1000"
    BitPat(9) = "1001"
    BitPat(10) = "1010"
    BitPat(11) = "1011"
    BitPat(12) = "1100"
    BitPat(13) = "1101"
    BitPat(14) = "1110"
    BitPat(15) = "1111"

    Then write the formula for a byte :
    ByteStr = BitPat(Int(ByteValue/16)) & BitPat(ByteValue and 15)
    To assure ByteValue is valid you can filter it by
    ByteValue = ByteValue and 255
    You can extend the formula for words or for longs. If it is used for visualization you can add spaces between the nibble strings.

  7. #47
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    Correct! The Sleep() is an API call from kernel32.dll, it is designed to suspend the application for the given milliseconds. I don't see any side note, nor explanations regarding this 50msec minimum interval, here

    http://allapi.mentalis.org/apilist/Sleep.shtml
    or here
    http://msdn.microsoft.com/en-us/libr...98(VS.85).aspx

    I also didn't noticed this. Since it is an API call it basically needs some extra time to reach and gets execute the actual process for sure. However, Visual Basic is a runtime based programming language, that some of the its functionality is simply gets executed by something similar way you execute an api call. (msvbvm60.dll)

    Whatever way you chose to suspend the application, the Sleep() can be executed only once, to achieve the delay. Moreover, it wont causing any high cpu load.

    I also would like to mention that if you use continous for...next loops to calculate timings that will be pretty much inaccurate, because anything happens outside your application it will cause random delays, there your application wont get the execution all the time, so your calculations will fail in precision. Don't confuse the way you execute a binary application on a microcontroller with an applcation that is running on multi-tasking operating systems. Thats the reason we all use timings, to make it as accurate as much is possible.

    If you're look for high resolution (the most precise) timer, i would recommend you to learn more about the QueryPerformanceCounter() API.

    http://msdn.microsoft.com/en-us/libr...04(VS.85).aspx

    vb6 example:
    http://allapi.mentalis.org/apilist/Q...eCounter.shtml

    Most of the performance sensitive applications are welcome this high resolution timer, for more accurate processes. Unfortunately the countinous calling of the API()'s will also cause high cpu load. So it's better to give an another chance to the Sleep() API. If you do some extensive testings regarding these api calls, i would be interested in the results!
    Last edited by Jim Davis; Oct 24th, 2009 at 06:29 AM.

  8. #48
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    Thanks Jim, I wasn't aware of this high precision counter, it will help me a lot. I had a small test, it is well working with currency data type. In my high speed communication I'll use it.

    In VB6 I don't have sleep, but for .net users it is possible to sleep for some estimated time a bit shorter than the required delay and then check the precise timing in a loop.

    In my timing algorithm it was not necessary to have a precise delay. As can be understood some gap of 50ms (may be up to 200ms) was the aim, so variation up to 50&#37; would not affect. I was using it at the time of quickbasic 4 (MSDOS) in older machines, to be more precise sometimes I was checking 3 times and deciding afterwards (even it was not a multitasking machine). Technology is evolving

    Some note on timer event... In older pc's timer tick is in about 50ms steps. VB6 behaves somewhat different, it is using 4 times precise tick (bacis was already using that interval while creating sounds), so it is possible to enter a periodic procedure every about 13ms. The strange thing is that I faced is, on some pc's I wasn't able to get this 13ms timing.

  9. #49
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    In VB6 I don't have sleep, but for .net users it is possible to sleep for some estimated time a bit shorter than the required delay and then check the precise timing in a loop.
    I'm lack of experiences regarding the .net environment, however the main advantage of the dot net framework is that you can use most of these window API's (without the need of any declaration), because the classes in the framework will provide you them.

    System.Threading.Thread.Sleep(5000)

    It is points to the Sleep() API call in the kernel32.dll that is equialent the following in vb

    Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
    Call Sleep(5000)

    It will provide you the same api, so you can use it in vb6 as well.

    I was using it at the time of quickbasic 4 (MSDOS) in older machines
    Exactly the same applies here, regarding the MultiTasking's. DOS is also single threaded, so you can 'hang' the system as long as you just want, it wasn't really a problem, since there were no other applications were running in the background, so the timing was more precise.

    However there are workarounds to execute applications in a somewhat similar way you execute them on multitasking operating systems. The technique was called TSR http://en.wikipedia.org/wiki/Termina..._Stay_Resident that was designed to provide some of the advantage of the multitaskings. But it no longer matters, since every decent OS the users are using are designed for multitasking operations.

    In older pc's timer tick is in about 50ms steps.
    It seems like that others are confirmed this behavior.
    http://www.daniweb.com/forums/post88977.html#post88977

    I've been got some alternate way to declare timers in vb, by using callbacks. I'm doing some experiments now to check out its precisions, but the first test by using vb's internal Timer property (not the timer control, but the timer property of DateTime class) shown that the precision is around ~15 mseconds. Well, at least thats the resolution (precision) of the timer property. I'm going to implement QueryPerformanceCounter api, and let's see what's the truth.

    i'll post the measurements here.

  10. #50
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    The measurements are done. It seems like that the precision of VB.Timer is 15 milliseconds, while the callback timer can go down as exactly one millisecond, that is pretty good.

    The only side effect of this callback, that it needs to pay more attention, since it can lock up your application, even your IDE if you don't use it properly. To shut down the application that uses this callback timer, you have to set it's class's Enabled property to false. The rest will be done. Don't stop your application by using the Stop button in the ide, that might cause the lock ups.

    Wish i could mention here where the implementation of this winmm callback timer comes from, but i'm forgot it. I didn't made it.

    To measure the precisions, just click one of the option buttons, to measure the one or the other timer. You can click between them while the execution is running, you don't have to interrupt the timers.

    ps: regarding the previous 50msec thing, i'm getting to think that would be 50 micro-seconds (uSec, that is 1/1000 of one millisecond) instead of 50 milliseconds. Unfortunately i still cant find any article that would explain it, it's just what i'm belive in.
    Attached Files Attached Files
    Last edited by Jim Davis; Oct 24th, 2009 at 03:53 PM.

  11. #51
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
    sounds good, another good function for me. I hope sleep() is procedure specific, i.e. it will not block any other event in running program. This way it will be possible to define longer sleep() periods to detect gaps (for our case), which will free CPU time considerably. Anyway it will be tried and seen.

    Yes, the TSR's in MSDOS were the first step in multitasking, and these were the ones that were affecting the timing loops since they were using the timer ticks to do pollings. They were long time ago, but I still use MSDOS in some of my projects

  12. #52
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    Jim, 50ms is correct, to be more precise it is 54.95ms, and the timer event has 54.95/4 = 13.7ms precision (that you measured roughly 15ms).

    I have no experience on callback but after the sleep() and QueryPerformanceCounter it may not be necessary to use it.

  13. #53
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    No, the Sleep will compeltely pass the executions back to the OS, so your app will simply hang. In this time, your application wont responding, simply will not generate any CPU events. As soon as the Sleep() suspension is elapsed, the application will gets the execution again to the next line, right after the sleep() api callings. That means you Can't measure queryperformance while the suspension is up.

    Code:
      MsgBox "The app will wait 5 seconds, and will not responding..."
      Sleep(5000) ' lets wait 5 seconds. the execution will stay here as long as the 5 seconds are elapsed
      MsgBox "5 seconds has been elapsed."



    If you want to make your application to responding while you hang a routine (or lets call it as event this time), you have to use timer's (vb timer, or the winmm callback timer i mentioned in my previous posts) that you can set to fire events in a given time. It is also would be a good idea to implement your event handlings into the timer tick event, there you can use event-matrix to do different things.

    Code:
    Private Enum enumMyEvents
      myEventInitThingie1 = 0
      myEventThingie1 = 1
      myEventThingie2 = 2
      myEventThingie3 = 3
     '.....
    End Enum 
    Private eCurrentEvent As enumMyEvents
    Private bPacketReceived As Boolean
    
    Private Sub Timer1_Timer()
      Select Case eCurrentEvent
        Case myEventInitThingie1
          'do inits here
          eCurrentEvent = 1
        Case myEventThingie1
          'send a packet for example here
          MSComm.... etc..etc
          eCurrentEvent = 2 
        Case myEventThingie2
          If bPacketReceived Then
            'the bPacketReceived can be set at the MSComm_OnComm event, so the packet has been received and saved to the buffer, you can do whatever you want to do with it..
          End If 
    
          'and then, let the events go further...
          eCurrentEvent = 3
        Case myEventThingie3
        '....
      End Select
    End Sub
    Hope it gives you the single idea how it could be done. This way won't cause high cpu loads, and will be as much precise as it just can be. Just like the application will be responding, so wont cause your application hangs.
    Last edited by Jim Davis; Oct 24th, 2009 at 03:29 PM.

  14. #54
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    One more very important side note regarding the timers. If you donwload the demo i provided, you can see if you click on the application's title bar, the VBTimer will not be responding for a one second, just like the application's surface not gets updated. This can be also seen while the measurement is running, because the measured time will jump up a high value for a moment. That means a lots of time has been elapsed since the last execution of the vb timer's timer_tick event.

    However, the winmm callback timer will do! So i recommend you to use it, since it gives even higher precision than the vb.timer control does, and it won't stop with your application, so it might be able to fire events while the application's surface is bugging/hanging because of any reasons. Just use it carefully, try to avoid using DoEvents or Sleep() (there might be some other things also that you have to pay attention) to not to confuse the 'execution pointers'.

  15. #55
    PowerPoster CDRIVE's Avatar
    Join Date
    Jul 2007
    Posts
    2,620

    Re: Receiving data from serial port

    Be aware that Sleep freezes everything in your app and can return some unexpected results, Even with DoEvents. Run this once and then run it again and try to close the form while it's looping.

    Code:
    Option Explicit
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    
    Private Sub Form_Load()
       Dim i As Integer
          For i = 1 To 10
             DoEvents
             Me.Show
             Me.Caption = i
             Sleep 1000                    ' Sleep for 1 Sec
          Next i
    End Sub
    <--- Did someone help you? Please rate their post. The little green squares make us feel really smart!
    If topic has been resolved, please pull down the Thread Tools & mark it Resolved.


    Is VB consuming your life, and is that a bad thing??

  16. #56
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    Run this once and then run it again and try to close the form while it's looping.
    That wouldn't be a good idea. The problem you are experiencing is because of the DoEvents. It lets the application to run some other things (like redrawing the application's surface, and therefore lets you to close the application) while the execution pointer is ping-pong'ing between the loop inside the Form_Load and the form's internal routines.

    To avoid the above to happen you can watch for these loops, to not let the application to unload itself, while a process is still running.

    Code:
    Option Explicit
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Private bRunning As Boolean
    
    Private Sub Form_Load()
       Dim i As Integer
          bRunning = True
          
          For i = 1 To 10
             DoEvents
             Me.Show
             Me.Caption = i
             Sleep 1000                    ' Sleep for 1 Sec
          Next i
          
          bRunning = False
    End Sub
    
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
      If bRunning Then Cancel = 1
    End Sub
    Theres nothing wrong with the Sleep. Cosmetically yes, it will freeze your app, but the main point is that it will freeze it for a given amount of time. You can use it for small timings, like 1-100 msec, that the user wont notice, but you can align the timings in your application to keep it sync for a given asyncronous process (just like the communication between the PC and a microcontroller).

  17. #57
    Hyperactive Member
    Join Date
    Sep 2009
    Location
    Lost in thought
    Posts
    349

    Re: Receiving data from serial port

    EndlessNameless Started/Made this Thread, not me.

    Quote Originally Posted by EndlessNameless View Post
    Hello. I am new to vbasic and am working with the mscomm controls. My goal is to receive data from an Oregan Scientific WMR-968 weather console. So far I have figured out the protocol and am receiving input fine from it. My problem is parsing the information. The station sends variable length packets beginning with FF FF followed by the data and then a checksum. Here are some examples I obtained from Device Monitor(there are many other types, these are only a few):

    FF FF 00 00 39 00 01 00 20 00 58 (Anemometer and Wind Data)

    FF FF 06 40 23 02 37 07 8B 21 17 00 06 70 (Inside Temp, Humidity, etc)

    FF FF 0E 48 54 (sequence number)

    FF FF 02 31 73 01 25 00 CA (extra sensors)
    WMR918 PCLINK protocol
    WMR918 PCLINK protocol (Version 0.2 with 600mb barometer supported)

    1. Serial data is sent in 9600 bps from Main unit to PC through RS232
    2. For the PC to receive the data from WMR918, the 'Request to send' pin of the PC must be setted to request data, otherwise no data will be sent.
    3. When WMR918 is going to send the data, it will send a header 'FFFF' first, then follow by the code of the type of data
    4. At the end of data, WMR918 will send the checksum of the data
    5. WMR918 will send data to the PC when new data is received.
    6. WMR918 will send the 'Minute' data to the PC every minute to ensure connection is OK.
    7. WMR918 will send the clock data every 1 hour or when new RF clock time is being received
    8. WMR918 will not send the data continously to the PC, it will send the data byte by byte. (ie. If there is other task for WM918 to complete such as to receive sensor data, WMR918 will go to receive the data first, then resume the sending of PC data).
    #1
    Serial data is sent in 9600 bps from Main unit to PC,
    "so lots of time"

    WMR918 will send the clock data every 1 hour or when new RF clock time is being received
    "so lots and lots of time"

    #2:
    For the PC to receive the data from WMR918, the 'Request to send' pin of the PC must be setted to request data, otherwise no data will be sent.

    "So get info when you wont, gut set 'Request to send'"

    #3:
    When WMR918 is going to send the data, it will send a header 'FFFF' first, then follow by the code of the type of data

    NOTE: #8:
    WMR918 will not send the data continously to the PC, it will send the data byte by byte. (ie. If there is other task for WM918 to complete such as to receive sensor data, WMR918 will go to receive the data first, then resume the sending of PC data).

    Byte1=FF
    Byte2=FF
    Byte3= code of the type of data
    So gust make array of user-defined Type arrays, so when you get Byte3 you
    Check the type, i.e Wind=00

    If you wont every hour then make Myarray(1 to 24) else Myarray(1 to 60) for min or secs

    i.e
    user-defined Type arrays

    Public Type aCommDataPackets
    WindData(1 To 8) As Byte
    RainData(1 To 13) As Byte
    '.....so on
    End Type

    Myarray(1 to 24) as aCommDataPackets

    Save Data
    Myarray(hour).WindData(ByteCount)=theByte
    Or
    Myarray(sec).WindData(ByteCount)=theByte

    when you are dun set MSComm1.DTREnable = False or MSComm1.PortOpen = False, "It's the inverse of Start getting data", but if hourly then dump new data.


    Sub ProcessWMR968Data()

    Case WindData
    thisByte= Myarray(hour).WindData(ByteCount)

    Code:
    Public Function ByteToBit10(ByVal b As Long) As String
    ' by Jost Schwider, jost@schwider.de, 20001228, rev 001
    ' based on ByteToBit02 by Donald, donald@xbeat.net, 20001206
      ByteToBit10 = "00000000"
      If b And &H1& Then MidB$(ByteToBit10, 15&) = "1"
      If b And &H2& Then MidB$(ByteToBit10, 13&) = "1"
      If b And &H4& Then MidB$(ByteToBit10, 11&) = "1"
      If b And &H8& Then MidB$(ByteToBit10, 9&) = "1"
      If b And &H10& Then MidB$(ByteToBit10, 7&) = "1"
      If b And &H20& Then MidB$(ByteToBit10, 5&) = "1"
      If b And &H40& Then MidB$(ByteToBit10, 3&) = "1"
      If b And &H80& Then MidB$(ByteToBit10, 1&) = "1"
    End Function
    Thank Jim Davis for this, HELPFUL guy
    This code is from http://www.xbeat.net/vbspeed/c_ByteToBit.htm

    you mite like this to http://www.xbeat.net/vbspeed/c_LoByte.htm

    you mite like this to

    have a look at post #41

    Note!!!!!!!!
    Check sum = the lower byte of the sum of the data send (include header).

    If you are Checking Check sum of Wind,you need to start the sum header1, header2 and Wind
    i.e 11111111,11111111, 0000000



    .
    Last edited by 5ms?; Oct 25th, 2009 at 01:54 PM. Reason: Wonted to add, All the guys here are HELPFUL

  18. #58
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    Check sum = the lower byte of the sum of the data send (include header).
    Yeah well i did made my own chksum calculations, but not compared them to the actual data is @EndlessNameless shown us. If someone want's to use my code, he/she have to implement the individual packets od the actual device, therefore the checksum calculating routines should be altered too, to make it compatible with it.

  19. #59
    Hyperactive Member
    Join Date
    Sep 2009
    Location
    Lost in thought
    Posts
    349

    Question Re: Receiving data from serial port

    Quote Originally Posted by Jim Davis View Post
    Yeah well i did made my own chksum calculations, but not compared them to the actual data is @EndlessNameless shown us. If someone want's to use my code, he/she have to implement the individual packets od the actual device, therefore the checksum calculating routines should be altered too, to make it compatible with it.
    Thanks Jim, for code and helping me.

    Wot do you Think of this?
    Code:
    Private Sub MSComm1_OnComm()
     If MSComm1.CommEvent = comEvReceive Then
            ByteCount = ByteCount + 1
            If ByteCount = 3 Then PacketsType = MSComm1.Input
        If ByteCount > 3 Then
            If PacketsType = 0 Then Myarray(sec).WindData(ByteCount - 3) = MSComm1.Input
            If PacketsType = 1 Then Myarray(sec).RainData(ByteCount - 3) = MSComm1.Input
        End If
     End If
    End Sub
    Last edited by 5ms?; Oct 25th, 2009 at 01:30 PM. Reason: End Sub

  20. #60
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    Not much i think because i'm not that experienced with the MSComm control. However, if your rx buffer (the Input) is contains more than one byte, the PacketsType = MSComm1.Input will fail. Well, at least i'm not sure what will be assigned then.

    However the rest is seems fine! Maybe you should reset the ByteCount when the packet has arrived.

    I would just like to point out, that these packet handling routines have to encapsulate some error handlings too. What i mean on error handling is packet fragmentation handlers. If a byte is losing, or some extra byte is appears because of noise or other electrical corruption is happening (light/storm/contact issues), the packets might be altered, and fragmentation occurs. In this case your code will fail, because the missing packets have to be cut out from the data stream, and the pointers have to be re-aligned. Think on it!

  21. #61
    Hyperactive Member
    Join Date
    Sep 2009
    Location
    Lost in thought
    Posts
    349

    Re: Receiving data from serial port

    However, if your rx buffer (the Input) is contains more than one byte, the PacketsType = MSComm1.Input will fail. Well, at least i'm not sure what will be assigned then.
    the WMR918 PCLINK protocol
    #8:Says it will send the data byte by byte.
    And there is, If MSComm1.InputLen > 1, but this would come under error handling


    making Packet arrays byte by byte
    If there is a bad byte,dump bad Packet, in the Checking of the Check sum.
    1 or 2 Packet dumped, you still have 58 good ones.
    I would just like to point out, that these packet handling routines have to encapsulate some error handlings too.
    Oh......... Yes!!!!!!!!!!.

    Maybe you should reset the ByteCount when the packet has arrived.
    something like post #41

    Ok,
    Thank you Jim, you'r gr8

  22. #62
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    From 'One by one' I understand that there may be random gaps between them. If I think of the behavior of a slow device like this (I'm working on these types of devices too) I expect these gaps will be much shorter than the gap between messages, a slow device, to finish another job, may suspend data transmission at most about 100ms. So it still would be better idea to set a higher gap wait time and check number of bytes received to understand which data is presented.

    Define global RcvStr, initial status of Timer1 is false, below code will do the job without any unnecessary CPU loading.

    Code:
    MSComm1_OnComm()
    
       If MSComm1.ComEvent <> comEvReceive then
          Exit Sub
       End If
    
       Timer1.Enabled = False    ' restart gap timer
       Timer1.Interval=1000     
       Timer1.Enabled = True
    
    .... append the bytes got from comm port to RcvStr
    
    end sub
    
    Private Sub Timer1_Timer()
       If Len(RcvStr) = ... then
          ...
       ElseIf Len(RcvStr) = ... then
          ...
          ...
       End If
       Timer1.Enabled = False
       RcvStr = ""
    end sub

  23. #63
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    It seems sometimes we are going far away from the original thread, but these experiences may help somebody.

    I tested the sleep(), it worked well. But it didn't speed-up the overall code. I discovered that MSComm1_OnComm() event is triggered at most every 15ms, that is the system timing clock. So to be sure that the gap is present it is required to wait for at least 16ms even if my slave system may work with 2ms gap. Taking care of the other events that may last for some ms's I'm lasting with about 40ms minimum gap

    Do you know any other comm check that responds quicker ? Or do I making something wrong ?

  24. #64
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    Back in time, in the old dos basic, there were "COM1:" and such properties available for the Open method (afair). However i'm not sure that you really need any alternative. The MSComm will buffers the input, then passes it to the application in every 15th msec. You just have to split up the accumulated (buffered) data and puzzle them to the previously received packets. The example i put together to the codebank post, does exactly this. get it if you're interested.

  25. #65
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    I don't have problem with receiving any length of data any time, only want to communicate faster. Dealing with some special hardware which is capable of communicating with 2ms frame gaps I would be able to handle 4 half duplex frames of 10 bytes in 16ms (using 115200 baud), now only a small fraction of it is possible.

    If you have sample codes ready it would be nice to see. Getting new ideas always worth

  26. #66
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Receiving data from serial port

    This really is tricky, and (IMO) there isn't a totally "good" solution, where throughput is the issue. Windows is non-deterministic, and high-level programming doesn't change that, it only increases the timing uncertainty.

    A protocol that depends on inter-packet gaps to mark the start and stop of a each packet is designed for use in an environment that does not use multitasking and multithreading -- that is, in general, it is designed for microprocessor to microprocessor communications where program timing can be specified in a very tight fashion. This is outside the purvue of what Windows is designed to do well.

    Is there anything else (the packet stucture itself) that you can use to determine the beginning and end of each packet? If so, then your VB code should be able to process the associated data just as quickly as it is sent, within limitations that will be controlled by the details of the process, and not the protocol itself.

    Dick

  27. #67
    Hyperactive Member
    Join Date
    Sep 2009
    Location
    Lost in thought
    Posts
    349

    Re: Receiving data from serial port

    NOTE: #8:
    WMR918 will not send the data continously to the PC, it will send the data byte by byte. (ie. If there is other task for WM918 to complete such as to receive sensor data, WMR918 will go to receive the data first, then resume the sending of PC data).
    Last edited by 5ms?; Oct 26th, 2009 at 03:46 PM.

  28. #68
    Lively Member
    Join Date
    Jan 2005
    Posts
    86

    Re: Receiving data from serial port

    Yes Dick, the problem is windows is designed for desktop applications. But in time it appeared to be used in many industrial machines, that is why industrial pc's appeared. As for the new API call sleep() there may be some function that can check incoming data stream without waiting for the 15ms tick, I'm searching for it. In that case it would solve the fast data transfer problem.

    Accessing the USART directly instead of using windows drivers may be a solution but it already means getting away from the high level language and writing a new driver software.

  29. #69
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Receiving data from serial port

    Hi,

    The DataReceived event (and the OnComm event in MSComm32.ocx) are not 15 mS, or some arbitrary number. Rather, they are generated "whenever" by the control. This might be 1 mS, or much longer. Naturally, the ReceiveThreshold or RThreshold (MSComm) must be set to 1 to minimize this time. However, you will never get a deterministing operation.

    There are two things happening. First (and foremost), the PC UART receive FIFO, nominally, has a hardware buffer of 16 bytes, and a receive interrupt will not be generated until the FIFO has a specified number of characters in it -- by default, this is 14 for the 8250x processors using in many PCs. But, this receive threshold may be longer for some USB virtual serial port UART. Thus, if data are continuous, or approach continuous, and if the serial speed is 9600 bps (960 bytes per second), the 15 mS result becomes obvious. It is a function of the receive threshold of the UART FIFO.

    Now, there is way to change the receive threshold programmatically, say to 1 (you can do this manually through Control Panel), and this may meet your needs. This can be done through VB, but there is nothing built-into Windows that supports it, AFAIK, so you have to bypass Windows/VB APIs, if you want to do it programmatically.

    However, the second issue is that you need to understand is why the UART FIFO may be needed, and reducing the FIFO receive threshold to 1 may cause data loss. If the UART is not serviced by the ISR associated with it before another byte is received, the pending byte will be lost, due to data overrun.

    If you choose to reduce the UART FIFO receive threshold to 1, you must read data in a loop (and pray, if appropriate, that data are not lost), avoiding the extra overhead of the OnComm or DataReceived event process.

    All in all, I'd look for something in the data, not timing, to determine the arrival of a full packet. Otherwise, you will be fighting the "good fight" but have the potential to loose the battle.

    Dick

  30. #70
    PowerPoster CDRIVE's Avatar
    Join Date
    Jul 2007
    Posts
    2,620

    Re: Receiving data from serial port

    Quote Originally Posted by kiymik View Post
    ... there may be some function that can check incoming data stream without waiting for the 15ms tick, I'm searching for it. In that case it would solve the fast data transfer problem.
    That's what RThreshold is for.
    <--- Did someone help you? Please rate their post. The little green squares make us feel really smart!
    If topic has been resolved, please pull down the Thread Tools & mark it Resolved.


    Is VB consuming your life, and is that a bad thing??

  31. #71
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Receiving data from serial port

    RThreshold specifies the minimum number of bytes that must be received before the OnComm event is generated. It does not say that an event will be generated when that number of bytes have been received. Generally, multiple bytes have been received and buffered by the UART FIFO and the Windows serial port driver, long before an OnComm event has been generated. Thus, if you specify RThreshold = 1, all that you are sure of is that you will get an event -- not how many bytes have been received prior to that event having been generated.

    This is obvious when you study the architecture of the PC "serial system." First to see receive data is the serial port UART. The UART buffers data in the FIFO, and an interrupt is generated only when the receive threshold for the UART FIFO has been reached (or a timeout causes the serial driver to poll the UART). The default setting for the threshold is 14 bytes for a common internal UART, though it may be much higher on some hardware or virtual serial port implementations. Then, the PC has to service that interrupt (meanwhile, it is possible for additonal serial data to have been received and buffered by the UART FIFO), and the data is transferred to the serial port driver. The serial port driver then generates an OnComm event.

    Dick

  32. #72
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    I didn't found any application there real-time processing is the case. But if you just have to build time-critical applications, you have to deal with some tiny delays. While the receive buffer got some data input, and passes to yout app there you can process the content by implementing the sleep() method, and therefore 'simulating' the original input.

    Well.. it is hard to me explain what i mean, but i hope you get it.

  33. #73
    PowerPoster CDRIVE's Avatar
    Join Date
    Jul 2007
    Posts
    2,620

    Re: Receiving data from serial port

    Quote Originally Posted by DickGrier View Post
    RThreshold specifies the minimum number of bytes that must be received before the OnComm event is generated. It does not say that an event will be generated when that number of bytes have been received. Generally, multiple bytes have been received and buffered by the UART FIFO and the Windows serial port driver, long before an OnComm event has been generated. Thus, if you specify RThreshold = 1, all that you are sure of is that you will get an event -- not how many bytes have been received prior to that event having been generated.


    Dick
    Are you saying that if RThreshold = 1 and only one Byte was sent to and received by the InBuffer, OnComm won't fire?
    <--- Did someone help you? Please rate their post. The little green squares make us feel really smart!
    If topic has been resolved, please pull down the Thread Tools & mark it Resolved.


    Is VB consuming your life, and is that a bad thing??

  34. #74
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Receiving data from serial port

    Not at all. As I said, RThreshold = 1 assures that an OnComm event will be generated for the single byte.

    However, if many bytes are received (for arguments sake, let's say 50 bytes, back to back at 9600 bps), one or more OnComm events will be generated. At a guess, I'd say there will be about three or four events generated for these 50 bytes. This, of course, assumes that you actually read (call the Input property of MSComm) from within the OnComm event. There certainly will not be one event for each byte, under normal operation.

    Now, you can through a "monkey wrench" into the process by setting the InputLen property to some value other than the default value (0). If you set InputLen = 1, then you will read only a single byte every time you call Input... And the result will be performance that is so bad that you would think that teletype machines were an invention from the future. Never, never (repeat) set InputLen = 1, stick with the default.

  35. #75
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    And the result will be performance that is so bad
    But. How the performance will be affected if the application can process the actual received byte less than a milliseconds for example? There i dont see any complications.

  36. #76
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Receiving data from serial port

    Latency is the issue, not processing time. That is, how long is the time after data have been buffered by the UART FIFO until an OnComm event is generated? Sometimes this is a problem.
    Any protocol that requires Real-time processing of serial data can problematic. Not because data may be lost (though this can happen at higher speeds, if CTS/RTS flow control are not used), but because there is no assurance that events (such as OnComm) are generated at a time that is closely related to the actual data arrival time. If CTS/RTS flow control are used, then you can kiss goodby the idea of determining when data have arrived.

  37. #77
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    Thats why i tried to mention the delayings. You can buffer the input that arrives from the MSComm, and by implementing a short delay you can start to process them, that can be then processed on the given frequency (time sync) by using the Sleep() for millisecond precision, or a Do...Loop that implements QueryPerformanceCounter to find out the ticks. This way will grant you a relatively stable frequency for the time-critical processings.

    Or am i speaking dumb?

  38. #78
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Receiving data from serial port

    This may work in some cases. However, the likelyhood of it being reliable over the span of time is (IMO) problematic. QueryPerformanceCounter has plenty of resolution for the task. Accuracy and resolution are not equal. You need the resolution, but the actual raw accuracy will be much much less than the resolution of the timer. It, like everything in Windows, is non-determistic. There are articles exploring this sort of real-time issue available online.

    I don't want to discourage you, or OP, from the task. You may get satisfactory operation. However, you should anticipate that it may fail at times (just load Word by double-clicking a large .docx file while you are running your application and see what happens to timing). So, with this in mind, you should craft your code such that you can detect malformed packets, and discard them. Also, use as much computer horsepower as you can. Don't try this on a vintage machine!

    Dick

  39. #79
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Receiving data from serial port

    You are right, running applications on windows are not suitable for these kind of processes. That's why hardware components can be built for these time-critical process, there bypassing the windows, its kernel, but most of the hardware components (by using microcontrollers for example) you can do these processes on-board, and the windows application will just show you the results, that will not be time-critical anymore, therefore will not affect the actuall process. An event queue on the hardware component would also be provide, no any results will be lost between the HW and the windows application. Gosh its getting way too complicated, isn't it? :_)

  40. #80
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Receiving data from serial port

    It can be troubling, or at least irritating. Issues like these are why I've written (well, rewritten, a number of times over 13 years) my book. I also work with PC based data acquisition systems (see: www.mvps.org/rgrier), where similar things often come up.

    Dick

Page 2 of 3 FirstFirst 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width