Sahil
Hi, I am trying to configure so that I have 8 digital outs on my Arduino Uno Slave (Address: %QX100.7). However for some reason I can not use the 8th Digital out no matter if its physical pin 12 or physical pin 13 on the arduino uno. In the Hardware monitor page the LED turns on when a condition is met, but not on the actual hardware if the address (%QX100.7) I am targeting is the 8th pin i.e. pin 12 or 13.

My understanding is that if i have 8 coils (discrete outputs) then the addressing would start from %QX100.0 and finish at %QX100.7 (8 bits of information starting from 0 ending at 7). If I redo the ladder logic and point to %QX100.6 the physical LED light turns on as well as the virtual in the "Hardware Monitoring" page of the OpenPLC runtime.

What am I not doing correctly? 

The edited Arduino Uno Firmware below ( i have only modified the top part). 

Quote:
#include <Arduino.h>
#include "Modbus.h"
#include "ModbusSerial.h"

//ModBus Port information
#define BAUD 115200
#define ID 0
#define TXPIN -1

//Define the number of registers, inputs and coils to be created
#define NUM_DISCRETE_INPUT 3
#define NUM_INPUT_REGISTERS 2
#define NUM_COILS 8
#define NUM_HOLDING_REGISTERS 2

//Create the I/O pin masks
uint8_t pinMask_DIN[] = {2, 3, 4};
uint8_t pinMask_AIN[] = {A2, A3};
uint8_t pinMask_DOUT[] = {5, 6, 7, 8, 9, 10, 11, 12};
uint8_t pinMask_AOUT[] = {A0, A1};

//Modbus Object
ModbusSerial modbus;

void configurePins()
{
for (int i = 0; i < NUM_DISCRETE_INPUT; i++)
{
pinMode(pinMask_DIN[i], INPUT);
}

for (int i = 0; i < NUM_INPUT_REGISTERS; i++)
{
pinMode(pinMask_AIN[i], INPUT);
}

for (int i = 0; i < NUM_COILS; i++)
{
pinMode(pinMask_DOUT[i], OUTPUT);
}

for (int i = 0; i < NUM_HOLDING_REGISTERS; i++)
{
pinMode(pinMask_AOUT[i], OUTPUT);
}
}

void setup()
{
//Setup board I/O
configurePins();

//Config Modbus Serial (port, speed, rs485 tx pin)
modbus.config(&Serial, BAUD, TXPIN);

//Set the Slave ID
modbus.setSlaveId(ID);

//Add all modbus registers
for (int i = 0; i < NUM_DISCRETE_INPUT; ++i)
{
modbus.addIsts(i);
}
for (int i = 0; i < NUM_INPUT_REGISTERS; ++i)
{
modbus.addIreg(i);
}
for (int i = 0; i < NUM_COILS; ++i)
{
modbus.addCoil(i);
}
for (int i = 0; i < NUM_HOLDING_REGISTERS; ++i)
{
modbus.addHreg(i);
}
}

void loop()
{
//Run the main modbus task
modbus.task();

//Update modbus registers
for (int i = 0; i < NUM_DISCRETE_INPUT; ++i)
{
modbus.Ists(i, digitalRead(pinMask_DIN[i]));
}
for (int i = 0; i < NUM_INPUT_REGISTERS; ++i)
{
modbus.Ireg(i, (analogRead(pinMask_AIN[i]) * 64));
}
for (int i = 0; i < NUM_COILS; ++i)
{
digitalWrite(pinMask_DOUT[i], modbus.Coil(i));
}
for (int i = 0; i < NUM_HOLDING_REGISTERS; ++i)
{
analogWrite(pinMask_AOUT[i], (modbus.Hreg(i) / 256));
}
}
Quote 0 0
Sahil
I did some more investigating today, and in the Arduino firmware I set my pin configuration as in the quote below, i set the number of coils to 9 in the OpenPLC runtime Slave Device configuration (keeping everything else the same). and I modified my OpenPLC ladder programe to address pin %QX100.8 and the pin turns on as it is supposed to do. Pin on %QX100.7 still doesnt.   On the OpenPLC run time I noticed that the Coil address range shifts from %QX100.0 - %QX100.7 to %QX100 - %QX101, however my codes still works. So I am reaching the limits in the address when i call for %QX100.7 but dont understand how/why.

I dont know how/why I can reference %QX100.8 in ladder logic and the program works.  I have looked online here searching for similar post about extending the number of pins but haven't found anything yet. 

Quote:
//Define the number of registers, inputs and coils to be created
#define NUM_DISCRETE_INPUT 3
#define NUM_INPUT_REGISTERS 2
#define NUM_COILS 9
#define NUM_HOLDING_REGISTERS 2

//Create the I/O pin masks
uint8_t pinMask_DIN[] = {2, 3, 4};
uint8_t pinMask_AIN[] = {A2, A3};
uint8_t pinMask_DOUT[] = {5, 6, 7, 8, 9, 10, 11, 12, 13};
uint8_t pinMask_AOUT[] = {A0, A1};
Quote 0 0
thiagoralves
%QX100.8 is an invalid address. You can only use it because the memory model is flat which makes %QX100.8 point to %QX101.0. But using invalid addresses can get you in trouble. The correct address to use is %QX101.0, and it should work the same.

Since the 9th coil is working, I imagine the 8th pin problem is not related to Modbus communication. Are you sure that this pin is working on your board? Try using a different pin as your 8th coil to make sure it is not the pin
Quote 0 0
Sahil
Good afternoon Thiago, thank you for your response. 

I have just re-tested with the ladder logic pointing to address %QX101.0 for pin 9 as I had seen another one of your posts suggesting to be careful about addressing. 

I have tried to point %QX100.7 (the 8th digital output) to another pin, please see extract below in quotes.

This time %QX100.7 points to Arduino Physical Pin 6 and I rerun the code and the physical light does not turn on when the pre-set value is reached.

I then changed the ladder logic program so that the coil is on %QX100.0 (Physical pin 13) and I upload and run the code and I have a light on address %QX100.0 (physical pin 13).

Quote:

//Define the number of registers, inputs and coils to be created
#define NUM_DISCRETE_INPUT 3
#define NUM_INPUT_REGISTERS 2
#define NUM_COILS 9
#define NUM_HOLDING_REGISTERS 2

//Create the I/O pin masks
uint8_t pinMask_DIN[] = {2, 3, 4};
uint8_t pinMask_AIN[] = {A2, A3};
uint8_t pinMask_DOUT[] = {13, 12, 11, 10, 9, 8, 7, 6, 5};
uint8_t pinMask_AOUT[] = {A0, A1}; 
Quote 0 0
thiagoralves
Sahil, did you figure this out? I find it very odd that the 8th pin is not working. One thing you can try doing is to duplicate the pin on the vector and declare the number of coils as 9 instead of 8. Then at least you will be able to access the pin at %QX101.0.

But still, this is very strange.
Quote 0 0
Sahil
Hi Thiago, 

I haven't understood why I am seeing this issue, I have had a look at the source code for OpenPLC runtime and the header files in the Arduino firmware and I don't understand it yet.

What you suggest is a good work around which I had not considered. I will try to compare the firmware for the Arduino Mega with what I have for the Arduino Uno next week, maybe there are people with Arduino Mega's and for them there is no issue with the address?  

I also keep wondering that since the OpenPLC run time automatically shifts to %QX101.0 on the 9th address is it possible that there is a combination of things in the Runtime software someplace that allows address %QX100.7 to fall through.

It (%QX100.7) is there on the hardware monitor and the hardware monitor indicates that %QX100.7 should work normally but the instructions do not get passed to the actual hardware side? 

I might have to make do with your propose work around and not be able to debug this issue. 
Quote 0 0
thiagoralves
It is possible that there could be errors somewhere in the OpenPLC code, but after so many people using it, it would be pretty obvious if %QX100.7 wasn't working for everyone. So my bet is that there is something either on your modified Arduino code or something on the modbus_master.cpp driver that makes the communication with slave devices. Try getting an Arduino Mega board and check if %QX100.7 works with the default configuration (default firmware from OpenPLCProject.com and default configuration on slave devices - Arduino Mega).
Quote 0 0
thiagoralves
It is possible that there could be errors in OpenPLC code, but with so many people using it, it would be pretty obvious if %QX100.7 wasn't working for everyone. My best bet is that there might be something wrong on your modified Arduino code or perhaps on the modbus_master.cpp file that is responsible for communicating with slave devices. Try getting an Arduino Mega board and check if %QX100.7 works on it with the default configuration (default firmware from OpenPLCProject.com using the default Arduino Mega configuration on Slave Devices).
Quote 0 0
Sahil
Hi Thiago, 

The code for the Arduino is on my first post. I will check against a Arduino Mega might need to move to that in the future anyway, but that may take upto 4 months, I will come back and post my findings to close this topic then or sooner if I find out what is going on. 
Quote 0 0
thiagoralves
You can use the firmware of the Arduino Mega on the Uno, just put a condition to stop the digitalwrite, digitalread, etc commands if they fall out of range of the uno pins (but keep the size of modbus registers the same, so that you can still use the default Arduino Mega configuration)
Quote 0 0