Modbus RTU Problem

  • 1
  • 2
  • 3
  • Page 2 of 3
Hans K.
 
Avatar
 
Subject:

Re: Modbus RTU Problem

 · 
Posted: 14.11.2011 - 17:04  ·  #9
Hello Avra

Thanks for your reply and recommendations. I will do the tests while you are setting up your environment, and prepare a skeleton application for you to test. One question arises from the demo applications: None of these applications actually implements an mb_AfterRegisterWrite procedure. As stated before, reading of Modbus registers works fine, the problem appears to be related to the write callback. Maybe you can investigate in this direction.

Regards,
Hans
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: Modbus RTU Problem

 · 
Posted: 15.11.2011 - 09:08  ·  #10
Can you try to write something to a register and check if it is properly written by reading that register back without using mb_AfterRegisterWrite callback procedure at all? Does it work as it should? Do you use AvrCo Modbus Tester or something else? Anyway, please do as much as you can from my previous message.
Hans K.
 
Avatar
 
Subject:

Re: Modbus RTU Problem

 · 
Posted: 15.11.2011 - 10:42  ·  #11
Hi Avra

I have now ported the skeleton application to another hardware platform. The results are exactly the same.
- Writing to a register, without write callback: The contents of the register is correctly written and can be read back ok.
- Writing to a register, with empty mb_AfterRegisterWrite: The contents of the register is correctly written and can be read back ok.
- Writing to a register, with mb_AfterRegisterWrite where a LED is flashed: The contents of the register is correctly written and can be read back ok, but the LED flash function is not executed.
- Writing to a register, with mb_AfterRegisterWrite where a short string is output on second serial port: The contents of the register is correctly written and can be read back ok, but the string is not output.
- Writing to a register, with mb_AfterRegisterWrite where a string, concatenated with IntToStr function, is output on second serial port: The contents of the register is not written, the string is not output and the application restarts after the next read of the register.

Does this help to investigate the problem?

Regards,
Hans
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Modbus RTU Problem

 · 
Posted: 15.11.2011 - 14:35  ·  #12
Hello Avra,

don't you read your PMs here in the forum?

rolf
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: Modbus RTU Problem

 · 
Posted: 16.11.2011 - 19:38  ·  #13
I have just logged in and downloaded the sample. I'll get back when I investigate the problem.
Hans K.
 
Avatar
 
Subject:

Re: Modbus RTU Problem

 · 
Posted: 17.11.2011 - 21:09  ·  #14
Hi Avra

Any progress with this investigation? What have you found out so far?

Regards,
Hans
Avra
Schreiberling
Avatar
Gender:
Location: Belgrade, Serbia
Age: 53
Homepage: rs.linkedin.com/in…
Posts: 653
Registered: 07 / 2002
Subject:

Re: Modbus RTU Problem

 · 
Posted: 18.11.2011 - 01:41  ·  #15
To cut the long story short, it turned out that I have to send ISP-3 to Germany for an upgrade, so I have to use thinking instead of testing. Callback functions were ment to be very fast, almost like you have to do in interrupts. It's not your fault at all since I might have forgotten to put it in the documentation. You should just fire some flag or do a quick memory move in a callback procedure, and never write to a serial port like you do. Then other process can pick that flag (or for example a record with register number and value) and output it safely to serial. Callback procedures were not ment for something like this from your sample:
Code
procedure mb_BeforeRegisterRead (RegisterNumber: word);
begin
   FlashLed;
   Writeln (SerOut, 'Rd reg ' + IntToStr (RegisterNumber));
end;

procedure mb_AfterRegisterWrite (RegisterNumber: word);
begin
   //   FlashLed;
   Writeln (SerOut, 'wr ' + IntToStr (RegisterNumber));
end;

You have put WriteLn and IntToStr in callback procedures, and that is too much. Just think about it. Your WriteLn might be longer then period between two MODBUS register read messages (callback is not finished until all characters are written to serial). If it is longer then it might be called again before previous callback has been finished, and BOOOOM!!! Let me show you how MODBUS callback procedures are called, and it might be more clear:

Code
function mb_ReadRegister(RegisterNumber: word): word; // return value of analog tag
var
   ReturnValue: word;
begin
   if BeforeRegisterRead <> NIL then
      BeforeRegisterRead(RegisterNumber); // if event exists call it
   endif;

   ReturnValue := mb_tags[RegisterNumber];

   if AfterRegisterRead <> NIL then
      AfterRegisterRead(RegisterNumber); // if event exists call it
   endif;

   return(ReturnValue);
end;

Since I can not test yet, you can do it for me. Just replace procedures in your code with these:
Code
procedure mb_BeforeRegisterRead (RegisterNumber: word);
begin
   LED := 1;
end;

procedure mb_AfterRegisterWrite (RegisterNumber: word);
begin
   LED := 0;
end;

First register reading message should light a led on, and first register write message should light a led off. Of course, you must use both read and write register messages to see the effect. If this led light does not show as advertised, then we might really have a bug and I should investigate in another direction.
Hans K.
 
Avatar
 
Subject:

Re: Modbus RTU Problem

 · 
Posted: 18.11.2011 - 08:30  ·  #16
Hi Avra

Thank you for your response, which indeed is very helpful. It turned out that reducing the callback function to a minimum solved the problem. What was misleading was mainly the fact that the read and write callbacks behave differently (i.e. the read callback executed the same code without a problem, while the write callback wouldn't).

I have now built the application like this:
Code

var
   Regs:  Pipe[20] of Word;

procedure mb_AfterRegisterWrite (RegisterNumber: word);
begin
   PipeSend (Regs, RegisterNumber);
end;

// Main program loop
   loop
      if PipeStat (Regs) > 0 then
         w:= PipeRecv (Regs);
         Writeln (SerOut, 'wr ' + IntToStr (w));
         // Do whatever else needs to be done...
      endif;
   endloop;



Best Regards,
Hans
  • 1
  • 2
  • 3
  • Page 2 of 3
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   125   139 · Page-Gen-Time: 0.025135s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI