Search code examples
delphiserial-portarduinodelphi-7

String Operation so Slow


I made an interface software using Delphi 7 to fetch data from arduino. Arduino has 3 sensors. Arduino will send 16 characters for sensor value. The example is :

 m  0  0  .  0  1  0  0  .  0   2   0   0   .   0   3
[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16]

[1] Flag for Start value
[2],[7],[12] are sensors status (0=disconnected, 1=connected)
[3][4][5][6] first sensor value
[8][9][10][11] second sensor value
[13][14][15][16] third sensor value

I assign the string value from arduino to an editText called Edit1. After that I use string "Copy" to get the sensor value one by one. The sensor value then will be displayed one by one in a label. But it takes long time for label to change the value. First time, I think it caused by label that slow on update. Then I change the label with editText, but work the same way (still takes long time to update the value). So is there a way to make this things faster? or there's something wrong with string operation?

This is my code:

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
  Str,Buffer,Rstatus,Sstatus,Tstatus: String;
  arus : real;
  i : integer;
begin
  DecimalSeparator:='.';   
  ComPort1.ReadStr(Str, 1);
  begin
    Buffer:=Buffer + Str;
    Edit1.Text:=Edit1.Text+Str;
    if Str='m' then
    edit1.Text:='';
      if Length(Edit1.Text) >=15 then
      begin
        Rstatus:=copy(Edit1.Text,1,1);
        Sstatus:=copy(Edit1.Text,6,1);
        Tstatus:=copy(Edit1.Text,11,1);
        if Rstatus='0' then
          begin
          Label1.Caption:='0 A';
          Label1.Update
          end
        else
          begin
          Label1.Caption:=copy(Edit1.Text,2,4)+' A';
          Label1.Update
          end;
        if Sstatus='0' then
          begin
          Label2.Caption:='0 A';
          Label2.Update
          end
        else
          begin
          Label2.Caption:=copy(Edit1.Text,7,4)+' A';
          Label2.Update;
          end;
        if Tstatus='0' then
          begin
          Label3.Caption:='0 A';
          Label3.Update
          end
        else
          begin
          Label3.Caption:=copy(Edit1.Text,12,4)+' A';
          Label3.Update;
          end;
      end;
    end;
end;

Solution

  • The header of the procedure has an important parameter, Count:

      procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
    

    It tells you how many characters are received and ready for you to read. Mostly, with low comm speed there will be only one, but sometimes there could be two or more. If you only read 1 character as in

      ComPort1.ReadStr(Str, 1);
    

    the remaining characters will be lost or they will not be read before the next OnRxChar occurs. For the last characters in a message, that will not take place before the next message triggers the event. That may explain why you percieve the process to be so slow. The cure is to read Count characters instead of only one.

    But there seems to be an error and you were not at all able to receive complete measurements. Let's look at the code:

    Edit1.text := Edit1.text + Str;
    if Str = 'm' then
      Edit1.text := '';
    if Length(Edit1.text) >= 15 then
    

    Your intention is to wait for the m flag, and clear Edit1.Text when you do receive it. That's fine. Then you receive and collect the rest of the message until you have 15 characters in Edit1.Text, which is also ok. But then, you overwrite the received message with a '2' ?

    begin
      Edit1.text := '2';
    

    Of course the rest of the message parsing will then fail.

    If you correct above two errors, I believe that your code might actually work.

    Edit after comment

    Replace these lines

    Edit1.text := Edit1.text + Str;
    if Str = 'm' then
      Edit1.text := '';
    

    with

    for i := 1 to Length(Str) do
    if Str[i] = 'm' then
      Edit1.text := ''
    else
      Edit1.Text := Edit1.Text + Str[i];
    

    And then you could also remove Buffer as you are not using it as well as the superfluous begin .. end; pair.