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.
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
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 = -
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.
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
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.
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
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:
Public Function ByteToBit10(ByVal b As Long) As String
' by Jost Schwider, [email]jost@schwider.de[/email], 20001228, rev 001
' based on ByteToBit02 by Donald, [email]donald@xbeat.net[/email], 20001206
ByteToBit10 = "00000000"
If b And &H1& Then MidB$(ByteToBit10, 15&) = "1" '1
If b And &H2& Then MidB$(ByteToBit10, 13&) = "1" '2
If b And &H4& Then MidB$(ByteToBit10, 11&) = "1" '4
If b And &H8& Then MidB$(ByteToBit10, 9&) = "1" '8
If b And &H10& Then MidB$(ByteToBit10, 7&) = "1" '16
If b And &H20& Then MidB$(ByteToBit10, 5&) = "1" '32
If b And &H40& Then MidB$(ByteToBit10, 3&) = "1" '64
If b And &H80& Then MidB$(ByteToBit10, 1&) = "1" '128
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
<--- 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??
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.
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
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.
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.
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% 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.
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.
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.
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.
Last edited by Jim Davis; Oct 24th, 2009 at 03:53 PM.
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
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.
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'.
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??
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).
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):
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
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.
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
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!
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.
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
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 ?
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.
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
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.
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).
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.
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.
... 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??
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.
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.
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??
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.
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.
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.
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.
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!
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? :_)
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.