Link to home
Start Free TrialLog in
Avatar of calinutz
calinutzFlag for Romania

asked on

Serial port read/write

I need complete code of writing to serial port.
This is what I need:

I need to send a string of hexa to the serial port and receive another string of hexa from there (and translate it later)
The string I need to send is:
\$f0\$41\$30\$4f\$f7
The received data will also be hexa, and I need to append it to a table in specific columns of a table (but that is not a problem for me, so don't bother)
The sending of the data will happen periodically (but that's also my problem to solve, not yours)

Please do not point me to various other links in experts-exchange or links to components... I've been there already. But sadly I have no experience in communicating with the serial port (not even using any third party component to do it).
So please give me working code (perhaps using a specific third party component)

I must give you here a list of freeware components that seem to work just fine with the serial port (but obviously they work for someone that has some experience with serial ports):
http://www.torry.net/pages.php?id=198
http://www.domis.de/cms/index.php?module=ContentExpress&func=display&ceid=8
http://www.ciemmesoft.com/release3/Forum_Componenti/Topic.asp?ID=972
http://sourceforge.net/projects/tpapro/



Avatar of MerijnB
MerijnB
Flag of Netherlands image

What port, baud rate, handshake settings?
Avatar of calinutz

ASKER

port - COM1,
baudrate - 9600,
FlowControl - XOnXOff,
parity - none
StopBits - 1
ByteSize - 8

I am confused... I have no ideea how to manage this. I happen to have another software (without source) that does this communication but I do not seem to be able to make it work, and to get responses from the other side.

Maybe it's the way I send the data through, or maybe the way I read it... But I think mainly the problem it's my sending the string of hexa...

So another program called ZeitControl Windowed Einzel works like a charm for sending and receiving the hexa information... But I can't seem to get it done.
As I already said... the string to send looks like this:\$f0\$41\$30\$4f\$f7, and I don't even know if the sent text is normal to look like this... Because I don't know what the serial port wants to receive and what transmits forward, what does it look like...

All I know is that when I send this text to the serial port, on the terminal, only the hexa appears without "$" and "\", so:
I send: \$f0\$41\$30\$4f\$f7, and in the terminal appears:F0 41 30 4F F7, and then come the response of the machine on the other side of the serial port... also in hexa...
And I also have an option to see the communication (not hexa) and the response looks more intelligible.

The software I am talking about I believe is made and given by the manufacturer of the hardware, but we do not get any other support to develop our own communication software. So I am stuck here.
This is how it looks like:

http://www.softwarex.ro/zeitControl.JPG

I need to be able to do the same in my software. Send a hexa string and receive another hexa string.
As you can see the blue string is the sent string and the rest is the response. Also I need to send all those 6 strings, and receive responses for each one of them, then save them to a database table. All this mus be in a timer. That's all... I should not be so complicated...

Please help.

So you don't have any documentation on the protocol? Do you know how to parse the result?
Nothing... I just know how the result should look like...
Like you saw there(in the picture) in hexview... I am sending a string of 5 hexa numbers... and I receive 73 hexa numbers.
If I uncheck the hexview, then intelligible information is visible...
I figure... if I know this, I could decode the hexa.
Is there any way of sending 5 hexa chars.... and just read the response? Is it more complicated than that?
If it is then tell me what should I be looking for...
But if it is possible to do the sending and receiving without anything else there... please tell me how can I do that?
I believe there must be a way of reading the response of the serial port... no matter what that would be... The problem is that I could not manage to get a response from the serial port... with any component...
Maybe it's the way I am sending the data to the serial port...? Maybe I do not know how to read from it?


Cand you give me a code that will send the above string to the serial port using any component  (freeware) ?
 And then receive the response from the serial port?
I made a scrrenshot of the Einzel software when sending the same string of hexa... viewed in hexa then viewed not in hexa...:
http://www.softwarex.ro/zeitControl2.JPG

So it is pretty clear to me that I must send a string of 5 hexa numbers to the serial port...
Then the serial port will reply with another string of hexa numbers. And when I convert the hexa cu ASCII, I will obtain my needed values.
Watch this:
In hex view
Send string:
F0 41 30 4F F7
Receive:
F0 61 20 30 20 30 2E 30 30 30 20 30 30 30 30 2E 30 30 20 30 30 30 30 30 30 30 31 2E 39 31 20 30 30 30 30 32 37 36 33 2E 34 38 20 2E F7

Conversion to ASCII:
Sent string:
ðA0O÷
Received string:
ða 0 0.000 0000.00 00000001.91 00002763.48 .

The interesting part is that when I use the zeitcontrol software the "ð" char is replaced with "-". That-s all the difference.

So the zeitcontrol software non-hex terminal display looks like this:
Sent string:
-A0O,
Received string:
-a 0 0.000 0000.00 00000001.91 00002763.48 .,

Basically I converted manually the hexa to ASCII and confronted with the non-hexview of the zeitcontrol software display

So actually I need to take the numbers generated after the conversion and enter them into a database.
But please help me obtain the result hex string, after sending the initial string...

It's like this: on the other side of the serial port there are 6 weighing machines that send back their measurements. So in the initial string that I am sending... there is probably an id of the machine and the command that tells it to reply with the measurements needed. The ID of the machine is probably the third and fourth hexa numbers from the string that I am sending (because only they differ)
Same way... in the result obtained, as you can see (in the translated string)
-a 0 0.000 0000.00 00000001.91 00002763.48 .,
"-a" stays the same, and the next number (in this case 0 ) represents the ID of the weighing machine... because for the other 5 input strings the resulted number will be 1,2,3,4,5

So this is what I discovered.
I am 99.99% sure that the reply from the machines is formated to use the exact same number of hexa numbers to represent their measurements (hence "0000.00").
So can you help me building the code that sends the string of hexa and receive the other string of hexa?
All the rest of the translation and the database is piece of cake.

Thank you so far
Correction:
Conversion to ASCII:
Sent string:
ðA0O÷
Received string:
ða 0 0.000 0000.00 00000001.91 00002763.48 .÷

And the zeitcontrol software replaces 2 ASCII chars:
The "ð" with "-"
and the "÷" with ","

Not that this is important... i just corrected myself so you don't see incomplete information above
SOLUTION
Avatar of MerijnB
MerijnB
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Apparently I wasn't doing the job correctly.
I had to convert the sent string to a Binary Array and convert it to AnsiString before sending it.
Now it works like a charm.
Thank you for your time.
I will ask for deletion of the question and a refund.
Sorry... I did not see your answer when I posted my comment.
If your code works I'll award you with the points even if I found my solution. I think it's only fair.
But only if your solution works ;)
Thank you again.
> But only if your solution works ;)

Big guess since I couldn't test it :p
Any suggestions on reading the result string in the OnRxBuf event?
I would appreciate it.
I cannot test your solution without it. (I really don't know how to convert the serial port response to hexa or ascii)
I solved my problem using another freeware component called serialPortNG... and it returns a string already converted from hexa to ASCII... so all I need to do now is split it into pieces and write it in the database.

I am open to use your solution, or at least award you with the points for your time, but I will need a full solution for sending the input string and receiving the result string.
Here's my code... very easy (I'm angry with myself for not solving it sooner)
// all the settings of my port are being done in Object inspector since I only need this code to work on a specific port, with specific settings, so I do not setup the components properties in the code.

procedure TForm1.Button1Click(Sender: TObject);
var
  BinArr: array of Byte;
begin
  SetLength(BinArr, 5);
  BinArr[0]:=240;
  BinArr[1]:=65;
  BinArr[2]:=48;
  BinArr[3]:=79;
  BinArr[4]:=247;
//240 65 48 79 247 that represent the decimal values of the hexa string
  SerialPortNG1.Active:=True;
  SerialPortNG1.SendString(AnsiString(BinArr));
  SerialPortNG1.ReadRequest:=True;
end;

procedure TForm1.SerialPortNG1RxClusterEvent(Sender: TObject);
begin
Memo1.Lines.Add(SerialPortNG1.ReadNextClusterAsString)
end;



And this is all... My memo receives the result like this
ða 0 0.000 0000.00 00000001.91 00002763.48 .÷

So it's perfect for me now.
But I repeat... If you give me the code that works with the other component... I will reward you with the points
Since you already receive a string, so this should do:

procedure TForm2.OnRxBuf(Sender: TObject; const Buffer; Count: Integer);
var Data: string;
begin
 SetLength(Data, Count);
 CopyMemory(@Data[1], @Buffer, Count);
 Memo1.Lines.Add(Data);
end;

Open in new window

Your code shows me this error...:

"COM port error. Unable to get async status on COM1."

?!?!?!?

Actually I had to modify the code a little because it's not working as you wrote it. Here is the code changed:

procedure TForm1.Button1Click(Sender: TObject);
begin
  ComPort1.WriteStr(#$F0#$41#$30#$4F#$F7);
end;
 
procedure TForm1.ComPort1RxBuf(Sender: TObject; const Buffer: PAnsiChar;
  Count: Integer);
var Data: string;
begin
 SetLength(Data, Count);
 CopyMemory(@Data[1], @Buffer, Count);
 Memo1.Lines.Add(Data);
end;

Open in new window

Having the component set up on design time...
This is the dfm
object Form1: TForm1
  Left = 366
  Top = 178
  Width = 524
  Height = 398
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 56
    Top = 60
    Width = 457
    Height = 305
    Lines.Strings = (
      'Memo1')
    TabOrder = 0
  end
  object Button1: TButton
    Left = 56
    Top = 32
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
    OnClick = Button1Click
  end
  object ComPort1: TComPort
    BaudRate = br9600
    Port = 'COM1'
    Parity.Bits = prNone
    StopBits = sbOneStopBit
    DataBits = dbEight
    Events = [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR, evError, evRLSD, evRx80Full]
    FlowControl.OutCTSFlow = False
    FlowControl.OutDSRFlow = False
    FlowControl.ControlDTR = dtrEnable
    FlowControl.ControlRTS = rtsDisable
    FlowControl.XonXoffOut = True
    FlowControl.XonXoffIn = True
    OnRxBuf = ComPort1RxBuf
    Left = 172
    Top = 8
  end
end

Open in new window

Ah, that's probably since I don't use the last version on the website :)
 
As far as I'm concerned you don't have to continue your search if you already have a working solution, only if you're interested in it yourself...
If you still want the points I can ask you to help me forward with my code and give you the points for the next help...
That is... I am struggling now with sending and receiving.
So In the end I need to do the following:
STEP1: Send hex string \$f0\$41\$30\$4f\$f7
STEP2: Receive the answer and place it somewhere
STEP3: Send another hex string \$f0\$41\$31\$4e\$f
STEP4: receive the answer and place somewhere
... and so on.
(I have 6 hex strings to send, so I need to obtain 6 results in connection with the sent string)
Basically I have a stringgrid with 2 columns I need to place the input string on first column and the received string on the second column, for each 6 input strings.
I have difficulties (probably setting up the component) with the received string.
I need to wait until a full response has arrived before sending the next string.

Can you help here?
I'll attach the project in a zip file and you-ll get in the zip file a picture of the result of the execution.
Are you interested?




These steps must
You said you have this working with the other serial component, didn't you?

So it's just a matter of keeping track where you are in the process, or am I mistaken?
That is my problem actualy. Since I don't seem to know when is the received string complete... I mean when to start the next sending of string.
Can you assist me? I could send you my sourcecode and you could look at it. Especially at the component... there has to be a way to know when the receiving is over.
I even tried to stop the port and start it again for the next string, but I am doing something wrong. Perhaps you have a more rested mind.

The components  use are: KStringGrid and SerialPortNG. I'll include them also in the zip, together with a screenshot of the result. Give me an email address
It's not really useful to sent me the sources since I can't test anything here (I don't have your device).

But I don't really see the problem though: you know how much data you expect back after each string you sent.
You can simply wait until you receive all 73 bytes before you sent the next command?
:(
This is exactly where I need your help.
How to wait until I receive all the bytes?
Considering that the component receives the response through this procedure:

SerialPortNG1.ReadNextClusterAsString

?
Perhaps you can see something I don't...
Maybe your solution could do the work better than my solution.
All you need to do is analyze my code (meybe find something I did not), and maybe suggest something... maybe another approach. Perhaps your component works better than mine, offers more info to work with.
I would attach the code here in a zip file but it does not let me, this is why I was asking for your email address.
I'm waiting... :)
send it to merijnb@xs4all.nl
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial