Solved

Serial port read/write

Posted on 2009-04-05
22
4,055 Views
Last Modified: 2012-05-06
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/



0
Comment
Question by:calinutz
  • 13
  • 9
22 Comments
 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
What port, baud rate, handshake settings?
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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.

0
 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
So you don't have any documentation on the protocol? Do you know how to parse the result?
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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
0
 
LVL 19

Assisted Solution

by:MerijnB
MerijnB earned 20 total points
Comment Utility
OK, I don't have a complete working example, but some quite useful stuff.

First of all, this is all quite simple, nothing to worry about.

I suggest you use this open source component: https://sourceforge.net/projects/comport/

See below a chunk of code which probably works all the way, but I can't test it (I don't have your device).
Come back with questions if you have any!

unit main;
 

interface
 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, CPort, StdCtrls;
 

type

  TForm2 = class(TForm)

    Button1: TButton;

    procedure FormCreate(Sender: TObject);

    procedure Button1Click(Sender: TObject);

  private

    { Private declarations }

    fCPort: TComPort;
 

    procedure OnRxBuf(Sender: TObject; const Buffer; Count: Integer);

  public

    { Public declarations }

  end;
 

var

  Form2: TForm2;
 

implementation
 

{$R *.dfm}
 

procedure TForm2.Button1Click(Sender: TObject);

begin

 // write the 'magic string'

 fCPort.WriteStr(#$F0#$41#$30#$4F#$F7);

end;
 

procedure TForm2.FormCreate(Sender: TObject);

var s: string;

begin

 // create the comport component

 fCPort := TComPort.Create(Self);
 

 // configure it

 fCPort.BaudRate := br9600;

 fCPort.Parity.Bits := prNone;

 fCPort.DataBits := dbEight;

 fCPort.StopBits := sbOneStopBit;

 fCPort.FlowControl.XonXoffOut := true;

 fCPort.FlowControl.XonXoffIn := true;

 fCPort.Port := 'com1';
 

 // set the rx data event handler

 fCPort.OnRxBuf := OnRxBuf;
 

 // all set, now open the port

 fCPort.Open();

end;
 

procedure TForm2.OnRxBuf(Sender: TObject; const Buffer; Count: Integer);

begin

 // here you receive data, you can check if Count = 73 so you know you're data is all there

end;
 

end.

Open in new window

0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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.
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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.
0
 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
> But only if your solution works ;)

Big guess since I couldn't test it :p
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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.
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
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

0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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

0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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

0
 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
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...
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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
0
 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
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?
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
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
0
 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
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?
0
 
LVL 11

Author Comment

by:calinutz
Comment Utility
:(
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... :)
0
 
LVL 19

Expert Comment

by:MerijnB
Comment Utility
send it to merijnb@xs4all.nl
0
 
LVL 11

Accepted Solution

by:
calinutz earned 0 total points
Comment Utility
I solved my problem using a timer.
Thank you anyway.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now