thiagoralves
Hi folks!

I just updated the OpenPLC code on github adding some nice new features:

Modbus Slave Rewrite
The main thing on this update is a major modbus slave code rewrite. I was tired of the problems libmodbus was causing, so I dropped it entirely and wrote my own modbus implementation. It was based on the previous modbus code I wrote for the OpenPLC v1, but with many bugfixes and a new modbus memory map (see below).

Added support for memory located vars
Now OpenPLC supports located memory vars and they are mapped to the modbus requests. This means that you can locate your vars at %MW0, %MW1, %MW2... and they will be accessible through modbus read holding registers request.

Added support for 32bit and 64bit variables
With the addition of the memory located vars, OpenPLC now supports longer variables as well. You can now declare double (DINT), long (LINT), REAL and LREAL variables and locate them at %MD0, %MD1... or %ML0, %ML1... and they are all accessible through modbus read holding registers request.

These modifications required the entire modbus memory map to be changed, mostly because variables bigger than 16bit requires more registers to be stored. So, the entire modbus holding registers address space was divided into normal analog output, 16bit memory holding registers, 32bit memory holding registers and 64bit memory holding registers. Please refer to the modbus memory map below:

Modbus_memory_map.PNG 

I will soon update the website with more detailed information. If you have any questions, please ask here.

I hope you'll all enjoy the update! [wink]



Thiago Alves

Quote 5 0
nmambre
I just did a quick test with HelloWorld.
The registers appear to be starting at 2050. Screenshot_2016-07-11_22-21-40.png 
Quote 0 0
thiagoralves
Modbus protocol address starts on 0, while PLCs address usually starts on 1. This leads to some confusion on modbus master softwares. Check the configuration of your software to see if it is using Modbus addressing or PLC addressing. I believe that your software is using PLC addressing, so the double value stored in register 2048 and 2049 seems to be showing on ModScan at registers 2049 and 2050.
Quote 0 0
nmambre
That is right, tested also with LREAL (double float) and the correct addressing starts with 1.

BTW, I tested the Modbus RTU Master with a slave IO (8DI and 8DO) without problems. OpenPLC running on Laptop with WinXP and USB to RS-485 converter.
Quote 0 0
thiagoralves
nmambre wrote:
BTW, I tested the Modbus RTU Master with a slave IO (8DI and 8DO) without problems. OpenPLC running on Laptop with WinXP and USB to RS-485 converter.

That's very good news! Thanks
Quote 0 0
mendesgeo

Hello, i'am running a tomcat webserver that connects to the modbus tcp on a raspberry pi via localhost and i'm getting this in openPlc log window:

threads.png 

The communication work fine at first but then, it seems that its created so much threads that rapsberry pi gets very slow and freezes until a i have to rebootit by pulling its power off.

I can't understand this. Tcp request are configured to refresh datapoint in each 1000ms. And everityme OpenPlc creates a new thread as it don't recognize its the same client over again.  This only occurs when i tested with raspberryPi, but not in windows with cygwin. 

Quote 0 0
mendesgeo
I really think that it must be the client application i'm using, but I can't say as i don't know how sockets work yet. But I made a quick workaround for my case (I'm using ScadaBR as client, but it seems very awkward its changind socket id behavior on raspberry) in the code below, I just put the thread's code directly in the server start instead of opening a new thread each time a new client arrives. This works well for my specific case but I don't recommend as any client could "steal" the messages from each other if more than one is connected in port 502.  



void startServer(int port)
{
  int socket_fd, client_fd;
  int arguments[1];
      pthread_t thread;
      unsigned char buffer[1024];
    int messageSize;
  
  socket_fd = createSocket(port);
  mapUnusedIO();
  while(1)
  {
    client_fd = waitForClient(socket_fd); //block until a client connects
    
    
    if (client_fd < 0)
    {
      printf("Server: Error accepting client!\n");
    }
    else
    {
      //printf("Response ID: %d...\n", client_fd);
      arguments[0] = client_fd;
      messageSize = listenToClient(client_fd, buffer);
        if (messageSize <= 0 || messageSize > 1024)
        {
      break;
        }
         processMessage(buffer, messageSize, client_fd);      
    }
  }
}
Quote 0 0
thiagoralves
mendesgeo, I never worked with tomcat before, so I don't know how it handles TCP connections. The OpenPLC Modbus server tries to keep the connection alive, unless the client kills it, which I think is what it's happening. Once the connection is killed, another attempt to read data will be made on another thread, as a new connection will have to be established. Probably the overhead of building and destroying threads all the time is overwhelming the Pi.

The code change you made actually works because you disabled the possibility to have more than one client connected at the same time. This way, if somebody is connected and reading/writing data, another client will be denied and timeout. I don't think it is the best approach.

If you try to use a Modbus/TCP master simulator software, such as Modbus Poll or Radzio Modbus, you will see that only one connection is active on the OpenPLC log.
Quote 2 0
mendesgeo
Thank you. ScadaBr in Linux had an issue that makes it open a request different for each reading.
Quote 0 0
AP2016
mendesgeo wrote:
Thank you. ScadaBr in Linux had an issue that makes it open a request different for each reading.


Is ScadaBr available in English? Thank you.
Quote 1 0
thiagoralves
AP2016 wrote:
Is ScadaBr available in English? Thank you.

I installed ScadaBR according to this manual:  https://www.dropbox.com/s/bipcpeylpg7f20c/Como%20instalar%20o%20scadaBR%20no%20windows.pdf?dl=0

Unfortunately the manual is in portuguese, but the pictures are pretty much self-explanatory. I will try to sum it up here:

1) Download and install JDK (the x86 version, even if you have a x64 computer):  http://www.oracle.com/technetwork/pt/java/javase/downloads/jdk8-downloads-2133151.html

2) Download and install Tomcat v7 (download the windows installer version)
Direct link:  http://apache.cs.utah.edu/tomcat/tomcat-7/v7.0.82/bin/apache-tomcat-7.0.82.exe
During the installation process, change the HTTP/1.1 Connector Port to 8085 (as shown in the manual). At the end of the instalation, unmark the checkbox to run Tomcat.

3) Download ScadaBR from here: https://docs.google.com/uc?export=download&confirm=no_antivirus&id=0BwyThwktWLAlZmNhVmEtdFdkUVk
Extract the contents and then move the ScadaBR folder to Tomcat at C:\Program Files (x86)\Apache Software Foundation\Tomcat 7.0\webapps\

4) Start Tomcat: C:\Program Files (x86)\Apache Software Foundation\Tomcat 7.0\bin\Tomcat7w.exe
Change the Startup Type to automatic and click on the start button.

5) Launch ScadaBR by opening your browser and typing: localhost:8085/ScadaBR
login: admin
pass: admin

After installing, the system was entirely in English. You will be fine by then.

mendesgeo wrote:
Thank you. ScadaBr in Linux had an issue that makes it open a request different for each reading.

I installed ScadaBR and after playing with it a bit, I figured out that it was not a bug or issue. Actually, you can configure it to open a new connection at each request or to keep the connection alive. Open you Data Source configuration and select this option:
Capture.PNG 

After that, only one connection will be opened and the system will work fine!
Quote 3 0
mendesgeo

Wow, thank you a lot, maybe when I installed ScadaBr in linux i didn't notice the default configuration of transport type had changed. I've got to fix this issue by cutting some code in the server.cpp but now I'm happy that it was just a configuration in ScadaBR [smile]

I'm working in a project with rasp and i managed to create a hardware layer that uses hardware SPI instead of serial, so communication speed could lift off. I just have to polish some details and comment everthing out before share with you guys.

I mounted a linux drive in my smartphone and i'm also testing OpenPLC in it. I'm looking forward to also post a generic mobile hardware layer, and instructions of how to install it.

Once again, thank you a lot for your project, it makes IoT unbelivible easier because of its flexibility in any hardware layer implementation.

Quote 0 0
felipe

First of all, I'm an absolute beginner, so my questions are very basic. I followed the instructions on the SCADA supervisory software post to assign addresses to holding registers. The code is up and running on my Raspberry Pi. Now, I'd like to use SCADABR (already installed) to monitor those registers from a computer on the same network (the same computer I used to upload the st file through the web server).

I've never used Modbus so I'm lost here. How do I configure the Raspberry Pi to work as a slave and my computer to work as a master? and where do I go from that point?

Quote 0 0
thiagoralves
You don't need to configure anything. If you're running OpenPLC on your Raspberry Pi, it's already a modbus slave device. If you want to know more about modbus, it would be nice to check this website: http://www.simplymodbus.ca/FAQ.htm

Basically, modbus is just a protocol to read and write to the PLC memory. It has mainly 4 types of call: one to read digital inputs, another to read/write digital outputs, other for reading analog inputs and the last one for reading/writing analog outputs. The simpler way to start is to download Radzio Modbus (it's like a windows explorer for modbus, where you can see the value of any address instantly) and start playing with it. To connect to the Raspberry Pi, just click on Connection->Settings, choose Modbus TCP and insert the IP address of your Pi. The port for modbus is always 502 (leave it as is). Then click on Connection->Connect and you'll be online!

To read/write the values, click on File->new, and you will see a spreadsheet-like window where you can define if you want to see digital inputs (input status), digital outputs (coils), analog inputs (input registers) or analog outputs (holding registers). Provide the address range you want and then you'll be able to see the values.

A good thing to do is to set up for reading digital inputs and then wire one of the Pi's inputs to true. You'll immediately see the value changing to 1 on the Radzio modbus software. Play with this software first for a little bit until you get familiarized with modbus. Then you can move to ScadaBR.
Quote 0 0
felipe
Thanks! I was able to access it from Radzio. I'll play with it for some time before moving to ScadaBR.
Quote 0 0