Recent

Author Topic: TLazSerial  (Read 7839 times)

johnsolomon

  • New Member
  • *
  • Posts: 11
TLazSerial
« on: October 05, 2017, 04:54:54 pm »
OK, I give up. I need help. Forgive me, I am new to this.

I am communicating via an RS-232 through a usb-232 adapter to a mettler toledo balance. When I send a command, I get a response. example:

procedure TForm1.Button2Click(Sender: TObject);
begin
        //Get Serial Number
        LazSerial1.WriteData('I4'+#13#10);
        Memo1.lines.Add(LazSerial1.ReadData);
        Button3.Enabled:=True;

then the scale will respond back:
I4 A "B346986532"

the program is pretty simple:

unit MT1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  StdCtrls, ExtCtrls, LazSerial;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    Label1: TLabel;
    LazSerial1: TLazSerial;
    Memo1: TMemo;

    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);

    //Function TLazSerialReadData: String;

  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
  CurPos : integer;


implementation

{$R *.lfm}

{ TForm1 }


procedure TForm1.FormCreate(Sender: TObject);
begin
        Memo1.DoubleBuffered := True;
        Button2.Enabled:=False;
        Button3.Enabled:=False;
        Button4.Enabled:=False;
        Button5.Enabled:=False;
        Button6.Enabled:=False;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
        //Setup Comm Port
        LazSerial1.ShowSetupDialog;
        Button2.Enabled:=True;
        LazSerial1.Active:= True;
        LazSerial1.Open;
        LazSerial1.WriteData('@'+#13#10);
        LazSerial1.WriteData('ZI'+#13#10);
        sleep(2);
        LazSerial1.SynSer.flush;

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
        //Get Serial Number
        LazSerial1.WriteData('I4'+#13#10);
        Memo1.lines.Add(LazSerial1.ReadData);
        Button3.Enabled:=True;

end;

procedure TForm1.Button3Click(Sender: TObject);
begin
        //Get Calibration Weight
        LazSerial1.WriteData('M19'+#13#10);
        Memo1.lines.Add(LazSerial1.ReadData);
        Button4.Enabled:=True;

end;

procedure TForm1.Button4Click(Sender: TObject);
begin
        //Unlock for calibration with external weights
        LazSerial1.WriteData('C0 1 1'+#13#10);
        Memo1.lines.Add(LazSerial1.ReadData);
        Button5.Enabled:=True;

end;

procedure TForm1.Button5Click(Sender: TObject);
begin
        //Initiate calibration sequence
        LazSerial1.WriteData('C2'+#13#10);
        Memo1.lines.Add(LazSerial1.ReadData);
        Button6.Enabled:=True;

end;

procedure TForm1.Button6Click(Sender: TObject);
begin
        //lock out calibration with external weights
        LazSerial1.WriteData('C0 0 0'+#13#10);
        Memo1.lines.Add(LazSerial1.ReadData);
        LazSerial1.Active:= False;
        Button2.Enabled:=False;
        Button3.Enabled:=False;
        Button4.Enabled:=False;
        Button5.Enabled:=False;
        Button6.Enabled:=False;
        LazSerial1.Close;
end;

end.

The problem I am seeing is that it looks like a buffering issue. I click the first button (not including comsetting), I get the first  response (its correct). I click the second button, I get the response as if I clicked button 1 (not correct).. I click the third button, I get the response as if I clicked button 2... and so on. I get the correct action from the unit, but the response I get seems to get out of sync. the responses I get are correctly displayed, but for the previous command.

Do I need to flush the buffer on readdata?
how do I do that?
am I missing something else?

any help is appreciated.

any additional info you need, I will be happy to get for you.
 

Noodly

  • Jr. Member
  • **
  • Posts: 70
Re: TLazSerial
« Reply #1 on: October 05, 2017, 05:26:41 pm »
Is the code for TForm1.Button2Click missing a line?

Memo1.lines.Add(LazSerial1.ReadData);
Windows 10 Home, Lazarus 2.02 (svn 60954), FPC 3.04

Paul Breneman

  • Sr. Member
  • ****
  • Posts: 290
    • Control Pascal
Re: TLazSerial
« Reply #2 on: October 05, 2017, 06:07:39 pm »
Without more info on the correct sequence of data it is hard for me to determine what is going wrong.

If you could use Control Terminal (http://ctrlterm.com/) and manually do the sequence of commands, then save the log file and share that then it would probably be easier to figure things out.
Regards,
Paul Breneman
www.ControlPascal.com

johnsolomon

  • New Member
  • *
  • Posts: 11
Re: TLazSerial
« Reply #3 on: October 05, 2017, 06:28:11 pm »
Noodly, although you are correct, I have been hacking and slashing away at this code for two days trying this, that and the other thing. I must have removed that bit when I trimed out my last attempt. its there now and still no difference.

Paul,

   being new, I am not sure what you mean as far as sequence of commands. I tried to make this so simple. button 1 allows user to enter com port data. button2, to read the serial number. button3 is to get the preprogramed weight for calibration, button 4 is to unlock the calibration function, button5 is to activate the calibration sequence. and finally button6 is to lock it back so line users cant run the cal sequence after its been ran. I enable the buttons as the cal techs step though the process keeping them in order.

This is the response I get from the balance:
I4 A "B346986532"    (when button2 is pressed) correct
I4 A "B346986532"    (when button3 is pressed) this is button2 response
M19 A 500.000 g       (when button4 is pressed) this is button3 response
C0 A                         (when button5 is pressed) this is button4 response
C2 B                         (When button6 is pressed) this is button5 respose.

so when I press button3...I should get "M19 A 500.000 g". I hope you understand what I am sttemting to discribe...



johnsolomon

  • New Member
  • *
  • Posts: 11
Re: TLazSerial
« Reply #4 on: October 05, 2017, 07:04:30 pm »
this is output from another program called Advanced Serial Port Monitor. I hope it helps.

<20171005130029.747 SYS>
COM is open
<20171005130029.747 SYS>
In/out queue size 4096/0
<20171005130029.747 SYS>
Set timeouts: ReadInterval=65535, ReadTotalTimeoutMultiplier=0, ReadTotalTimeoutConstant=0, WriteTotalTimeoutMultiplier=0, WriteTotalTimeoutConstant=0
<20171005130029.747 SYS>
RTS on
<20171005130029.747 SYS>
DTR on
<20171005130029.747 SYS>
Purge the serial port: RXABORT, RXCLEAR, TXABORT, TXCLEAR
<20171005130029.753 SYS>
Baud rate 9600
<20171005130029.753 SYS>
RTS on
<20171005130029.753 SYS>
DTR on
<20171005130029.753 SYS>
Data bits=8, Stop bits=1, Parity=None
<20171005130029.753 SYS>
Set chars: Eof=0x00, Error=0x00, Break=0x00, Event=0x00, Xon=0x11, Xoff=0x13
<20171005130029.753 SYS>
Handflow: ControlHandShake=(DTR_CONTROL), FlowReplace=(AUTO_TRANSMIT, AUTO_RECEIVE, TRANSMIT_TOGGLE, RTS_CONTROL), XonLimit=1024, XoffLimit=1024
<20171005130029.754 TX>
@ [len=1]
<20171005130029.754 TX>
ZI [len=2]
<20171005130037.281 TX>
@ [len=1]
<20171005130037.281 TX>
ZI [len=2]
<20171005130038.766 TX>
I4 [len=2]
<20171005130038.766 RX>
I4 A "B346986532" [len=17]
<20171005130038.766 RX>
I4 A "B346986532" [len=17]
<20171005130041.219 TX>
M19 [len=3]
<20171005130044.642 TX>
C0 1 1 [len=6]
<20171005130044.642 RX>
I4 A "B346986532" [len=17]
<20171005130044.642 RX>
M19 A 500.000 g [len=15]
<20171005130049.158 TX>
C2 [len=2]
<20171005130053.123 TX>
C0 0 0 [len=6]
<20171005130053.123 RX>
C0 A [len=4]
<20171005130053.123 RX>
C2 B [len=4]
<20171005130053.123 RX>
C2 "     0.000 g" [len=17]
<20171005130053.123 SYS>
Purge the serial port: RXABORT, RXCLEAR, TXABORT, TXCLEAR
<20171005130053.123 SYS>
Purge the serial port: RXABORT, RXCLEAR, TXABORT, TXCLEAR
<20171005130053.123 SYS>
RTS off
<20171005130053.123 SYS>
DTR off
<20171005130053.186 SYS>
COM is closed

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Re: TLazSerial
« Reply #5 on: October 05, 2017, 07:14:27 pm »
Replace
Code: Pascal  [Select][+][-]
  1. Memo1.lines.Add(LazSerial1.ReadData);
  2.  
with
Code: Pascal  [Select][+][-]
  1. Memo1.lines.Add(LazSerial1.ReadData);
  2. Sleep(1000);
  3. Application.ProcessMessages;
  4. if LazSerial.DataAvailable then
  5. begin
  6.   Memo1.Lines.Add('You forgot to read this data:');
  7.   Memo1.Lines.Add(LazSerial1.ReadData);
  8. end;
  9.  
and report what happens.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

johnsolomon

  • New Member
  • *
  • Posts: 11
Re: TLazSerial
« Reply #6 on: October 05, 2017, 08:38:22 pm »
Unit1.pas(66,36) Error: Identifier not found "DataAvailable"
Unit1.pas(81,36) Error: Identifier not found "DataAvailable"
Unit1.pas(96,36) Error: Identifier not found "DataAvailable"
Unit1.pas(112,36) Error: Identifier not found "DataAvailable"
Unit1.pas(128,36) Error: Identifier not found "DataAvailable"
unit1.pas(145) Fatal:There were 5 errors compiling module, stopping.


johnsolomon

  • New Member
  • *
  • Posts: 11
Re: TLazSerial
« Reply #7 on: October 05, 2017, 08:44:29 pm »
Gee, I think it might be helpfull if I put a 1 in the "if LazSerial.DataAvailable then" line... sorry.

I now get the correct results..just got to deal with the memo scrolling.

Thank you very much. very helpfull.

I got lucky...crashed my lazarus in the middle of this mess..

johnsolomon

  • New Member
  • *
  • Posts: 11
Re: TLazSerial
« Reply #8 on: October 05, 2017, 08:49:26 pm »
So what was going on?

Noodly

  • Jr. Member
  • **
  • Posts: 70
Re: TLazSerial
« Reply #9 on: October 05, 2017, 08:56:44 pm »
I think Avra had a typo in his code, try changing:

if LazSerial.DataAvailable

to

if LazSerial1.DataAvailable

I see you just spotted it  :D
« Last Edit: October 05, 2017, 08:59:21 pm by Noodly »
Windows 10 Home, Lazarus 2.02 (svn 60954), FPC 3.04

Noodly

  • Jr. Member
  • **
  • Posts: 70
Re: TLazSerial
« Reply #10 on: October 06, 2017, 01:23:52 am »
So what was going on?

RS232 is asynchronous so when you send a command to the scales your Lazarus program does not wait for a reply - unless you code for it.

Meanwhile your scales receives and processes the command - relatively slowly as it's probably not got a top of the range CPU - and replies back in milliseconds via RS232 which is also a very slow communication method by modern standards.

By the time your program gets the reply it could have processed hundreds of lines of code. This is why Avra put a one second sleep in his code.

Rather than read the data every time you press one of your buttons you could read the data in a thread and add it to a stringlist acting as a buffer, but a simpler solution for your example would be to put the read in a timer event running, say, every 500 ms and include Application.ProcessMessages to ensure that the memo is updated straight away when something is received.

So, in your example, remove all the Memo1.Lines.Add(LazSerial1.ReadData) lines from your button clicks and create a TTimer with an interval of 500 and put this code in the OnTimer event:

---
if LazSerial1.DataAvailable then
begin
  Memo1.Lines.Add(LazSerial1.ReadData);
  Application.ProcessMessages
end;
---
 
Start the timer after you've opened the serial port, before you send anything.

I haven't tested any of this, but it should work.
Windows 10 Home, Lazarus 2.02 (svn 60954), FPC 3.04

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: TLazSerial
« Reply #11 on: October 06, 2017, 01:38:11 am »
hello,
don't forget that TLazSerial component is an event-driven version of synaser : you can work with the onRxData event --> see the project example of TLazserial sertest.
Friendly, J.P
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

johnsolomon

  • New Member
  • *
  • Posts: 11
Re: TLazSerial
« Reply #12 on: October 06, 2017, 02:28:10 pm »
Hello JP,

btw, thank you for your work on LazSerail. It works great for exactly what I needed. I tried 3 others, but they did not work for me. My guess is there are errors. One big question, Is there any documentation on the properties for this component. I did a bunch of hunting, but could not find any. dumb people like me need the docs to help navigate our way through the component.

thanks again to all.

knuckles

  • Full Member
  • ***
  • Posts: 122
Re: TLazSerial
« Reply #13 on: October 06, 2017, 03:18:15 pm »
If I understand right for the memo scroll use memo1.lines.beginupdate and memo1.lines.endupdate in a try finally block

 

TinyPortal © 2005-2018