|
I am trying to connect to a serial port and transmit a string to tell a device that I want to communicate. I can open port fine. The problem is when I send my string. My write does not work everytime. Do you have any suggestions on what could be causing this and how to fix.
If serialPort.IsOpen Then
serialPort.Write("SERIELL")
End If
When my device gets this it sends back as string "OK"
I tried doing a loop to write "SERIELL" until it gets the "OK" but I must be missing something. Please look at my code:
Dim readcollect(1) As Char
Do While readcollect(0).ToString <> "79"
If serialPort.IsOpen Then
serialPort.Write("SERIELL")
End If
serialPort.Read(readcollect, 0, 1).ToString()
Loop
I search for "79" because it is "O" and this worked somewhere else in my program.
serialport.read() seemed like the best way but I don't know.
Thank you.
-- modified at 12:59 Friday 17th August, 2007
|
|
|
|
|
Hi Cory,
I have several remarks:
1.
readcollect(0).ToString <> "79" is terrible code; if you mean character O
then write that, nothing else; if you want to compare characters, then do that,
nothing else. Hence: readcollect(0) <> "O"c
2.
Your serialPort.IsOpen test is inside the while loop, so if it fails, you will
never exit the loop??? Either you know the port is open, so you don't need the
test, or you don't know and you test once, outside the loop, and if the test
fails you take appropriate action (such as return an error code, or throw an
exception, but not hang your thread in an infinite loop).
3.
serialPort.Read(readcollect, 0, 1).ToString()
Read returns an int, why would you convert it to string and then ignore it?
And more importantly, why do you ignore a significant return value, that tells
you how many chars/bytes have been read ?
4.
I don't think it is wise to create a loop that transmits data without any rest;
if it fails the first time, it will very likely continue to fail. At least
include some throttling, such as a Trhead.Sleep(1000) or so (i.e. trying
once per second).
5.
If you send once, the reply will not be there immediately; it takes a while for
the characters to be transmitted, then received on the other side, interpreted,
understood, reacted upon, reply transmitted, then received and be ready for
the Read() method. In the mean time the PC is long past it's first Read
attempt. That's another reason to have a Sleep just after the Write, I would
use 100 msec for starters.
6.
a serial read may fail to return chars/bytes for one of many reasons, such as:
- cable disconnected
- nothing was sent by the other party
- dataflow has disabled communication (XOFF char, control line has wrong polarity)
- all chars received have been rejected (e.g. because they are NULL, or
equal to newline terminator, wrong baudrate/parity/bitcount, ...)
7.
a serial write may fail to transmit chars/bytes for a couple of reasons, they
are fewer as the previous list; the main reason is your side is told not to
transmit, i.e. dataflow control prevents transmission because XOFF was received
or control lines have wrong polarity (depends on SerialPort.HandShake).
My best guess is you are transmitting but you are not receiving. You can check this
by using a null modem cable (which has two female connectors) and connect
either another port of same PC, or another PC, instead of your current target;
then use a terminal emulator (such as HyperTerminal) on that port or PC.
BTW: you'd better have that Sleep included if you want to be able to read
what HyperTerminal receives...
-- modified at 13:28 Friday 17th August, 2007
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
I put the thread.sleep in and it is working better. Thank you. I still have this issue. When my device send a certain data stream (in a packet) like {006 002 051 001 057 001 043 003} 006 starts transmission 002 means start packet, 001 separates segments in the packet and 003 is the end. The first segment tells me what is being sent. How can I capture that and test it.
serialport.read()
serialport.readline()
serialport.char()
serialport.byte()
serialport.readline()
serialport.existing()
In one part of my program I use serialport.existing() but it sends me like 20 006 before I get the 002.
Any suggestions.
Thanks.
|
|
|
|
|
Yep, that is the real problem in communication: several kinds of ports don't know
about packets, SerialPort is one of those. Hence, the data you get from a Read
may not (or not always) correspond to one (or many) complete packets.
There are three ways around that:
1. by collecting all bytes yourself until you get a full packet, then dealing with
that packet, keeping the remainder; adding to it when more arrives, etc.
2. if both parties agree, by having one packet sent for every special action taken.
A special action could be pulsing one of the control lines, or sending a special
character (such as ASCII ENQ).
3. if the "protocol" has a special character (say ASCII ETX) that always
terminates the packet, AND is guaranteed not to appear inside a packet, then
you could do the equivalent of a ReadLine, i.e. let the driver keep its data
until it has seen that ETX, then return the entire packet to the Read() caller.
It seems your inbound packets end on 003, that's ASCII ETX (I assume this is hex,
for some unclear reason printed with 3 digits); so if you can prove ETX does not
occur in the middle of a packet, you could consider the third method.
Now the only support .NET offers for this is by setting SerialPort.NewLine
and then call ReadLine which works fine for text; but yours probably does
not fit, it has those 01 and 02 bytes in between text pieces (and I still
don't know how the checksum looks like).
So my advice is:
A. try setting NewLine to the char whose byte value is hex 03; don't use WriteLine
any more since that will now also emit those 03 chars; try using ReadLine and
check whether hex 01 is accepted as a true character; if it is, this is the
way to go. If it is not:
B. consider the second way (the one with ENQ or handshake toggle).
Your description somewhat fits this: often on an ENQ the reply starts with ACK,
which is hex 06. You could ask for data, wait a while (say 200 msec) then
do a "read all available" (which is ReadExisting for text, or a little Read loop
for binary data).
C. if that fails to, prepare for the most clumsy one, with software repacketing.
Whatever the approach is, you must accomodate for transmission errors, i.e.
a character being mutilated, or a packet being broken off (e.g. by removing/inserting
the cable or starting/stopping the other side); this typically means if you have
some integrity check (like a fixed format, your 03 at the end; and/or a checksum),
and it tells you it does not pass, then you must "resynchronize", i.e. be prepared
for more junk of arbitrary length before a valid packet suddenly pops up.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
How do you get the progress bar to work in vb.net 2005?
jds1207
|
|
|
|
|
By using it properly??
What's the real question behind this? What kind of problem are you having?
|
|
|
|
|
|
I am trying to index with this regex but it does not pick text that's stored in a HTML tag.
Example: Johnson <b>Peter</b> Smith for the keywords "John" and "Peter" returns only "John"
\\b("+keyword+"'?s?)\\b|(^"+keyword+"'?s?)\\b|\\b("+keyword+"'?s?$)
So how do I go about making the regex pick-up Peter, which is in a HTML tag. can this be done by regex, or some other process? :S
Thanks, Anthony, Canada.
|
|
|
|
|
I already replied to this in your other thread.
---
single minded; short sighted; long gone;
|
|
|
|
|
I have a list of database files that I want to open and have access to the data. The original files are stored in .dbf as OEM data, and are used by a Visual Objects 2.0 program.
Right now I open the files with Excel and save them as dbaseIV files to use them.
Is there an easyer way to open / convert these files to use with my VB /(MSAccess back end) database?
-- modified at 10:24 Friday 17th August, 2007
|
|
|
|
|
|
Thanks for the quick reply,
I have looked at that and it works great on a per file bases.
I am looking at doing about 700 small files at any given time and combining them into one large one to do queries and reporting.
Do you know of a mass convert utility? or have any coding help you can extend?
Thanks
|
|
|
|
|
suppose sql server is installed in a network server(or a network attached computer running XP)
and another computer wish to connect to that server through a vb application, what is the connection string
that we need to provide.
Or does it have a different approach????
raamay
|
|
|
|
|
|
hello,
I'm programming app to change the system time, but everytime I run this it only resets the time to "31/12/2007, 00:00"
can anyone take a look at my code and tell me where's my mistake?
Imports System.Runtime.InteropServices<br />
Public Class Form1<br />
Private Structure SYSTEMTIME<br />
Dim wYear As Integer<br />
Dim wMonth As Integer<br />
Dim wDayOfWeek As Integer<br />
Dim wDay As Integer<br />
Dim wHour As Integer<br />
Dim wMinute As Integer<br />
Dim wSecond As Integer<br />
Dim wMilliseconds As Integer<br />
End Structure<br />
<br />
Private Declare Function SetSystemTime Lib "kernel32" _<br />
(ByVal lpSystemTime As SYSTEMTIME) As Boolean<br />
<br />
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load<br />
Dim NewTimeDate As SYSTEMTIME<br />
NewTimeDate.wYear = 2006<br />
NewTimeDate.wMonth = 10<br />
NewTimeDate.wDay = 4<br />
NewTimeDate.wHour = 5<br />
NewTimeDate.wMinute = 5<br />
NewTimeDate.wSecond = 5<br />
NewTimeDate.wMilliseconds = 5<br />
If SetSystemTime(NewTimeDate) = True Then<br />
MsgBox("Done")<br />
End If<br />
End Sub<br />
End Class
thanks.
|
|
|
|
|
Hi,
the SetSystemTime() prototype states:
BOOL SetSystemTime(const SYSTEMTIME *lpSystemTime);
which means it needs a pointer to a SYSTEMTIME structure, hence passing "ByVal"
is wrong.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
didn't notice that
I tried now with ByRef, same result
SetSystemTime() is really called, but time changes to 31-12-2007 00:00 which means that it's not passing parameters to the function?
|
|
|
|
|
Where did you get your SYSTEMTIME Structure? It is completely wrong.
Check the documentation, stop your trial-and-error methods.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
You should be passing the structure in ByRef AND you've defined all the fields in the structure as Integers (32-bit signed). They should be Shorts or Int16, 16-bit signed numbers:
Private Structure SYSTEMTIME
Public wYear As Int16
Public wMonth As Int16
Public wDayOfWeek As Int16
Public wDay As Int16
Public wHour As Int16
Public wMinute As Int16
Public wSecond As Int16
Public wMilliseconds As Int16
End Structure
WORD types in the documentation convert to Int16's (Short). DWORD's convert to Int32's (Integer).
|
|
|
|
|
thank you very much, works as a charm now
I'm not too much into winAPI programming just started to learn.
tnx for the help.
|
|
|
|
|
hi frnds,
i am using VB 6.0 (classic) and i want to get the amount of space remaining on my HDD including partitions.
the out put should be like
C: = 2 GB
D: = 7 GB
how can i do ....?
should i use WINAPI32 ....
regards,
koolprasad2003
If the message is useful for U then please Rate This message...
Be a good listener...Because Opprtunity knoughts softly...N-Joy
|
|
|
|
|
Hi,
you probably need to call function GetDiskFreeSpaceEx() in kernel32.dll
Another question by VIP Commando, right above this one, would show you how
these things can be done.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
thankx buddy for reply,
but the real problem is it returns the free space in Numbers of Bytes if there is HDD capacity more than 200GB then VB 6.0 fails to accept the range and throws the exception as "Sunscript outof range OVERFLOW"
what should i do ?
i have tried with "Long" and "Double" Type
regards,
koolprasad2003
Be a good listener...Because Opprtunity knoughts softly...N-Joy
|
|
|
|
|
koolprasad2003 wrote: what should i do ?
show the code.
Luc Pattyn [Forum Guidelines] [My Articles]
this weeks tips:
- make Visual display line numbers: Tools/Options/TextEditor/...
- show exceptions with ToString() to see all information
- before you ask a question here, search CodeProject, then Google
|
|
|
|
|
Hi koolprasad2003,
I found this (put in in a new form ...)
Private Declare Function GetDiskFreeSpaceEx Lib "kernel32.dll" Alias _
"GetDiskFreeSpaceExA" (ByVal lpDirectoryName As String, _
lpFreeBytesAvailableToCaller As ULARGE_INTEGER, lpTotalNumberOfBytes As _
ULARGE_INTEGER, lpTotalNumberOfFreeBytes As ULARGE_INTEGER) As Long
Private Type ULARGE_INTEGER
LowPart As Long
HighPart As Long
End Type
Private Sub Form_Load()
Dim result As Long
Dim x As ULARGE_INTEGER
Dim y As ULARGE_INTEGER
Dim z As ULARGE_INTEGER
result = GetDiskFreeSpaceEx("c:\", x, y, z)
Debug.Print result
Debug.Print x.HighPart, x.LowPart
Debug.Print y.HighPart, y.LowPart
Debug.Print z.HighPart, z.LowPart
End Sub
Greetings, Thomas
|
|
|
|
|