2024-Dec-09
Version 8.21.2.9 is the current version.
This project is a fork of mod_RSsim (www.sourceforge.net/projects/modrssim) which is also hosted on this site.
I had run into this program a couple of times in the past, but I did not have time to try and learn a new program then.
At the end of 2014 I had a project where I needed a good Modbus simulator.
I was reminded of this on the forum for www.advancedhmi.com and I decided to review it for use in this application..
There were many things that I liked about this program such as:
1) It is free.
2) It has source code available.
3) It is programmed in a language that I might be able to use to modify, fix, or improve it.
4) It supports the full range of ALL of the four Modbus data types by default.
5) It has a diagnostics screen that shows you the traffic for the Modbus commands and responses.
6) It supports both RS-232 and TCP/IP connections.
7) It has support for Rockwell/Allen-Bradley protocols in which I have an interest.
8) It supports scripting which is interesting for simulations.
9) It has a support site where people had listed problems and some solutions.
10) It has built-in help by pressing the "F1" key.
11) It provides for handling all of the Modbus device ID's from 0 to 255 at once.
I started testing and trying to get it to compile in VC6. After several days and deleting many lines I could compile it.
The deleted code did not affect the functionality, but mostly registration and website update testing.
I was able to test a fix that was posted on the support page and it worked for me, so I thought that this was good.
Eventually I moved the project to Visual Studio 2010 and was able to compile it without deletions.
Shortly though I ran into several annoyances. The Editor did not allow me to edit CHAR or HEX data.
Another thing is that when I set the data format (Fmt:), when I used the program again it did not remember my setting.
The "CSV Read" was not documented and when I tried to use it based on what I saw in the code there were problems.
After a bit of testing I was able to fix the issues mentioned above and continue with my testing.
Other problems occurred such as the inconsistency of 5-digit versus 6-digit Modbus addressing that you can see here..
I was able to fix these errors as well and make other changes, fixes and improvements.
For instance I was writing a group of about 32 bits to the program, but only the first few bits were showing changes.
What I found is that the update count was based on bytes and not bits and needed to be multiplied by eight.
After I made this change, the bits updated on the screen as I expected.
Eventually I decided that I wanted to make my changes and improvements available to others.
I created this SourceForge project to do that and continue to make updates as I find the need.
This project has been cloned on Github by Pavel Kostromitinov and can be found here:
https://github.com/Cavaler/ModRSsim2/
How are two register 32bit floats simulated? Do I have to manually figure out the bytes and put in two consecutive registers or is there a way to enter the single value and the simulator can populate both registers?
Yes. If you select the format (Fmt:) as "float 32" this will show the numbers as floating point values and you can enter them directly here. Because we cannot know whether the two consecutive words start on an even or odd address, all addresses are displayed as if they were the beginning value, so you will have to know to use and look at only the odd or even displayed values. This does not allow for any word or byte swaps, but only uses the standard IEEE-32 bit floating point format as used in the later Modicon PLC's.
How do you write scripts?
I have a customer with a Modbus client with no user I/O and they want to set the real-time clock. They suggested Open ModSim, and I learned enough javascript to write a script that reads the PC clock and writes time into holding registers. But I can't get it to respond to my requests.
I downloaded ModRSsim2 and it replies to the request, but I need to get the time values from the PC's RTC into the registers.
Thanks in advance.
Don, Please see if you don't have "clock.vbs" in your sources download folder. It shows how you can use the "timer" variable that is part of Visual Basic Script to get the time.
Since it is small I will include it here:
dim x
dim n
dim hr
dim min
dim sec
n = int(timer/100)
x = timer - n*100
h = timer
SetRegisterValue 3, 0, n
SetRegisterValue 3, 1, x
if ((int(x/10)*10 - x) >= -1) then
SetRegisterValue 3, 2, x
' Or your code here
end if
hr = int(timer/60/60)
min = int((timer - hr * 3600)/60)
sec = timer - hr * 3600 - min * 60
SetRegisterValue 3, 10, hr
SetRegisterValue 3, 11, min
SetRegisterValue 3, 12, sec
For information on how to enable scripts use the "F1" help key from the main screen and search for "script".
This does not handle the date. If you need more help, please respond back to me here.
You might also want to review stack overflow on this topic here:
https://stackoverflow.com/questions/7011357/how-do-i-get-the-date-time-vbs
Thanks, Doug Lyons
Last edit: Doug Lyons 2024-03-20
Hi Doug,
Thanks for the fast response. I was going to post a message this morning that I had figured it out, but you beat me to it.
I found the help page, and that told me I needed a VB script and some of the syntax I needed. Then googling 'vb script date' gave me the functions I needed. I ended up with this:
dim d
d = Now()
SetRegisterValue 3, 1, DatePart("s", d)
SetRegisterValue 3, 2, DatePart("n", d)
SetRegisterValue 3, 3, DatePart("h", d)
SetRegisterValue 3, 4, DatePart("w", d)
SetRegisterValue 3, 5, DatePart("d", d)
SetRegisterValue 3, 6, DatePart("m", d)
SetRegisterValue 3, 7, DatePart("yyyy", d)
This is exactly what I need. It's a great tool, and way easier to use than the other one I tried. Thanks for supporting it.
Don
From: wiki@modrssim2.p.re.sourceforge.net wiki@modrssim2.p.re.sourceforge.net On Behalf Of Doug Lyons
Sent: Wednesday, March 20, 2024 5:31 PM
To: [modrssim2:wiki] Home@wiki.modrssim2.p.re.sourceforge.net
Subject: [modrssim2:wiki] Discussion for Home page
You don't often get email from douglyons@users.sourceforge.netdouglyons@users.sourceforge.net. Learn why this is importanthttps://aka.ms/LearnAboutSenderIdentification
Don, Please see if you don't have "clock.vbs" in your sources download folder. It shows how you can use the "timer" variable that is part of Visual Basic Script to get the time.
Since it is small I will include it here:
dim x
dim n
dim hr
dim min
dim sec
n = int(timer/100)
x = timer - n*100
h = timer
SetRegisterValue 3, 0, n
SetRegisterValue 3, 1, x
if ((int(x/10)*10 - x) >= -1) then
SetRegisterValue 3, 2, x
' Or your code here
end if
hr = int(timer/60/60)
min = int((timer - hr * 3600)/60)
sec = timer - hr * 3600 - min * 60
SetRegisterValue 3, 10, hr
SetRegisterValue 3, 11, min
SetRegisterValue 3, 12, sec
For information on how to enable scripts use the "F1" help key from the main screen and search for "script".
This does not handle the date. If you need more help, please respond back to me here.
Thanks, Doug Lyons
Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/modrssim2/wiki/Home/
To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/
Hi Doug,
My customer is saying they want the time in UTC. I've seen some posts showing how to read the registry time offset, but I can't get them to work.
Here's what one says to do:
Dim var_offset
Dim WshShell
set WshShell = WScript.CreateObject("WScript.Shell")
var_offset = WshShell.RegRead("HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
d = DateAdd("n", var_offset, Now())
But as soon as I add the 'set' line it stops working. I guess you aren't running wscript interpreter? Any suggestions on how to do this?
TIA
Oops! I should have read your post more carefully. The stack overflow link shows how to do it. Thanks!
Or maybe not. When I try to run this it doesn't update. If I comment out the for loop it updates, but it doesn't have the UTC offset. I'm also not sure I see how to get the bias for the local time zone.
dim d
dim offset
offset = 0
Dim wmi : Set wmi = GetObject("winmgmts:root\cimv2")
Set timeZones = wmi.ExecQuery("SELECT Bias, Caption FROM Win32_TimeZone")
For Each tz In timeZones
tz.Bias = -300
tz.Caption = (UTC-05:00) Eastern Time (US & Canada)
Next
d = DateAdd("n", offset, Now())
'd = Now()
SetRegisterValue 3, 1, DatePart("s", d)
SetRegisterValue 3, 2, DatePart("n", d)
SetRegisterValue 3, 3, DatePart("h", d)
SetRegisterValue 3, 4, DatePart("w", d)
SetRegisterValue 3, 5, DatePart("d", d)
SetRegisterValue 3, 6, DatePart("m", d)
SetRegisterValue 3, 7, DatePart("yyyy", d)
Don,
It seems to me you should be able to just look up this key's value in the machine manually:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\Bias.
Then just take this value (300 for Eastern Time) and plug it into the script as shown below.
dim d
d = DateAdd("n", 300, Now())
SetRegisterValue 3, 1, DatePart("s", d)
SetRegisterValue 3, 2, DatePart("n", d)
SetRegisterValue 3, 3, DatePart("h", d)
SetRegisterValue 3, 4, DatePart("w", d)
SetRegisterValue 3, 5, DatePart("d", d)
SetRegisterValue 3, 6, DatePart("m", d)
SetRegisterValue 3, 7, DatePart("yyyy", d)
Because "Now()" will be automatically updated for Daylight Time by default, this should work.
Note that you do not want the "ActiveTimeBias" because this changes for Standard Time and Daylight Time, so you would be double compensating if you used this dynamic value.
You should not need to even read the registry, just use the offset based on their Time Zone.
Doug Lyons
My task is to set the machine's clock to UTC using a PC connected by modbus. Hundreds of these will be deployed across the country and beyond. Requiring manual intervention by the end user is not an option.
So, not at all knowing what I'm doing, I've been slogging around the swamp for a while, and I think I stumbled on the answer. I ended up here:
https://learn.microsoft.com/en-us/windows/win32/wmisdk/swbemdatetime
Based on that, I came up with this, which appears to work:
Set dateTime = CreateObject("WbemScripting.SWbemDateTime") 'create a date/time object
dateTime.SetVarDate(Now()) 'put the current time into the object
d = dateTime.GetVarDate (false) 'the false value retreives UTC time
SetRegisterValue 3, 1, DatePart("s", d) 'load seconds into modbus holding register at address 1
SetRegisterValue 3, 2, DatePart("n", d) 'minutes
SetRegisterValue 3, 3, DatePart("h", d) 'hours
SetRegisterValue 3, 4, DatePart("w", d) 'day of the week
SetRegisterValue 3, 5, DatePart("d", d) 'date (day of month)
SetRegisterValue 3, 6, DatePart("m", d) 'month
SetRegisterValue 3, 7, DatePart("yyyy", d) 'full year
Hi. Is it possible to run 2 instances of ModRSsim2 with to different IP?. I need to simulate 2 diferent IP both with the same ID.
Hello, Kali. The ModRSSim2 server takes its IP address from the computer that it is running on.
Therefore, it is possible by doing something similar to the following.
Install a Virtual Machine server such as Virtual Box or VMWare. Now install an operating system in two seperate instances. You can find a free version of ReactOS that is capable of running this at
https://sourceforge.net/projects/reactos/files/ReactOS/0.4.15-ReleaseCandidates/.
Set these two machines to have dedicated IP addresses that correspond to the two IP address that you want to simulate. Install ModRSSim2 in each of these machines. Good Luck. Doug Lyons
Last edit: Doug Lyons 2024-10-01
Hello Mr. Doug,
I am new to ModRSim2, and I have been trying to update IEEE32 floats using the scripts, with no luck so far.
Using the SetRegisterValue and GetRegisterValue I can only manipulate one register at a time, and the float32 gets truncated.
All the VBS solutions I have found for converting IEEE32 to two words or to four bytes, and vice-versa, seem to use VB functions that are not accepted by the script compiler.
Do you have any workaround for handling float32 in ModRSim2 ?
Thanks in advance
Mr. Duarte,
If you look at the 2nd row of selections near the top of the display, there is one that shows "Fmt:".
You can use the pull-down selection and set this to "float 32". This will allow you some options.
Because a 32-bit float takes two 16-bit registers, they can begin on either an even or odd address.
Since the system does not know which is intended, the display attempts to show both values.
So you have to decide whether to read/write to the even or odd address.
I see that you reference "SetRegisterValue" and "GetRegisterValue".
These functions do not support setting floating point registers at this time.
But since the source code is provided, it would be possible to extend it fairly easily to do this.
You could use REG_TYPE of 5 (which is not used) to indicate a 32-bit float number.
Now the programming would have to be extended to handle the details, but it could be done.
Otherwise, you would have to enter the 32-bit float as two Set/Get Register Values.
I hope that this helps. Good Luck. Doug Lyons
Mr. Doug,
Thank you very much for the feedback.
I have explored a little bit more of the software and, following up on your sugestion, I was able to implement the Set/Get float32 in VBS.
Mr. Duarte,
Would you be willing to share your VBS code here so that it might benefit others? Thanks.
Doug Lyons