evranch
Hi, I'm just getting started experimenting with OpenPLC, it looks like it has some real potential. I work with PLCs and Modbus in industry and this looks like a fun and economical setup to use around my farm for a homebrew DCS and monitoring setup, especially with the dirt cheap and simple ESP8266 nodes. I am even imagining an ESP8266 on each of my tractors and vehicles to monitor if the battery is getting weak!

First minor issue, I love that the ESP8266 has that analog input, but in initial testing when the input is tied to 3.3v and reporting 1024, the line

mb_input_regs[i] = (analogRead(pinMask_AIN[i]) * 64);


overflows to 65536 and returns 0 rather than 0xFFFF.

Since this is a single case, my simple workaround was to test for max value and reset it in the case of overflow:

uint16_t ana_in = analogRead(pinMask_AIN[i]);
if (ana_in == 1024)
   mb_input_regs[i] = 0xFFFF;
else
   mb_input_regs[i] = (ana_in * 64);


Often an analog input doesn't run up against the high limit in normal operation, but assuming something like a thermistor goes shorted, it needs to return max rather than 0!


A potentially bigger issue is that in my test setup I have tried to hook up an Arduino Nano on the Raspberry Pi's serial bus, with a goal of ultimately using RS485, and connected an ESP8266 as the second slave. The Nano is assigned %IW100-%IW105, and the 8266 %IW106.

However, the value from A0 on the ESP8266 ends up in %IW107 instead, which is not even supposed to be allocated. %IW106 contains a null value.

When I swap the 8266 with the Nano, the value from the 8266 ends up in %IW100 and the values from the Nano end up in %IW102-107 with %IW101 containing a null value. The Nano was supposed to be allocated %IW101-106.

Having a gap between the address spaces is not a bad thing if intentional, but the fact that the allocations don't match up with the displayed memory map is not so good.

While testing this I noticed another big potential issue with the slave devices: They are allocated in order of creation. If one has to be deleted, all of the rest must also be deleted and recreated in the right order, or the addressing gets messed up. In an industrial device, each slave device is allocated a starting address and that allocation persists. Maybe one more field on the "create/edit slave" page to set offsets, since you are already using an offset of 100 for the first slave?

I can take a look at the code and help out in the future, but this time of year I'm busy with work as well as haying and other time-critical tasks, so I'm just throwing this in as a bug report/feature request.

Thanks for all your work on this system and the editor and simulator - the whole thing is very professional for what appears to mostly be a one man project!
Quote 0 0
thiagoralves
evranch, thank you for reporting those bugs. Another user had reported problems working with analog inputs on slave devices and I never had the time to check what the problem was. Turns out you nailed it. There was an extra int_input_index++; instruction counting one extra space between the devices. I fixed it now. Can you confirm that it works? You will have to reinstall OpenPLC to get the most recent code from the repositories.
Quote 0 0
evranch
Thank for the quick fix! I tested it and it works perfectly.

I had a quick skim of the code and it looks simple enough to add fixed addressing by adding a start_address field to MB_device and then setting bool_input_index, int_input_index and such to that start_address before you poll the device. Then each device would also start its discretes and registers at the same index i.e. %IX200.0 %QX200.0 %IW200. Much simpler to remember while writing the PLC logic.

This would also avoid having to increment the pointers past any unresponsive devices, which I see you are doing while checking if devices are connected. The only issue I see is potentially wasting some RAM on the gaps in the array, but with the class of devices OpenPLC runs on I don't see a couple extra KB of RAM being an issue.

Finally, if each device had its own address space they could then be polled asynchronously... I noticed while integrating the ESP8266 with the hardwired devices that if the ESP8266 is not reachable, the entire polling loop blocks on the timeout, slowing the RTU to a crawl.
Quote 0 0