charlesbaynham / simple-modbus

Automatically exported from code.google.com/p/simple-modbus
3 stars 4 forks source link

simulating a slave device #17

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Hello,

i want to simulate a modbus slave device (a rather big AHU) witch has some 
config data, sensor data and status data on varoius adresses.

10001-10018 config
15000-15024 sensors
...
40000-40004 status

How can i create the same register structure with a simpleModbus slave?
Using arduino IDE 1.0.5 and nano328 boards + max 485

thanks!

Original issue reported on code.google.com by kraftair...@gmail.com on 16 Aug 2013 at 9:13

GoogleCodeExporter commented 8 years ago
sorry, its not a defect of course

Original comment by kraftair...@gmail.com on 16 Aug 2013 at 9:15

GoogleCodeExporter commented 8 years ago
Hi,

SimpleModbusSlave only supports function 3 and 16. These functions both share 
the same address space i.e. 4XXXX.

Original comment by bester.j...@gmail.com on 19 Aug 2013 at 7:02

GoogleCodeExporter commented 8 years ago
Hi, thanks for the answer, and what about modbusMaster? 
I wrote this code for reading the slave device's registers,
but cant tell if its correct or not. Could this be working?

#define baud 9600
#define timeout 1000
#define polling 200 
#define retry_count 5
#define TxEnablePin 2 

enum
{
  CONFIG1, //10001-10018
  CONFIG2, //40000-40004
  INFO,    //15000-15024
  STATUS,  //20000-20003
  COMMAND, //20004-20013
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];

packetPointer config_1 = &packets[CONFIG1];
packetPointer config_2 = &packets[CONFIG2];
packetPointer info_1 = &packets[INFO];
packetPointer status_1 = &packets[STATUS];
packetPointer command_1 = &packets[COMMAND];

unsigned int readRegs1[1];
unsigned int readRegs2[1];
unsigned int readRegs3[1];
unsigned int readRegs4[1];
unsigned int readRegs5[1];

unsigned int writeRegs[1];

void setup()
{
 Serial.begin(9600); 
  modbus_construct(config_1, 1, READ_HOLDING_REGISTERS, 10001, 11, readRegs1); 
  modbus_construct(config_2, 1, READ_HOLDING_REGISTERS, 40000, 2, readRegs2);
  modbus_construct(info_1, 1, READ_HOLDING_REGISTERS, 15000, 25, readRegs3);
  modbus_construct(status_1, 1, READ_HOLDING_REGISTERS, 20000, 4, readRegs4);
  modbus_construct(command_1, 1, READ_HOLDING_REGISTERS, 20004, 10, readRegs5);

  modbus_configure(baud, SERIAL_8O1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

void loop()
{
  modbus_update();
  for (int i = 1; i <= 18 ; i++){ 
   Serial.println(readRegs1[i]);   
  }
  for (int i = 0; i <= 4 ; i++){ 
   Serial.println(readRegs2[i]);   
  }
  for (int i = 0; i <= 24 ; i++){ 
   Serial.println(readRegs3[i]);   
  }
  for (int i = 0; i <= 3 ; i++){ 
   Serial.println(readRegs4[i]);   
  }
    for (int i = 4; i <= 13 ; i++){ 
   Serial.println(readRegs5[i]);   
  }
  delay(5000);
}

Original comment by kraftair...@gmail.com on 19 Aug 2013 at 9:32

GoogleCodeExporter commented 8 years ago
Yes, SimpleModbusMaster supports function 1, 2, 3, 4 15 and 16.

But:
20000-20003 and 20004-20013 are not valid modbus addresses. Function 1 covers 
addresses with 0X reference and function 2 covers 1X references (maybe that's 
what you meant ;))

The function implicitly specifies the address so you do not use 40000 but 0000 
using READ_HOLDING_REGISTERS.

Using function 1 (READ_COIL_STATUS) and 2 (READ_INPUT_STATUS) you must specify 
the amount of points to read. The library will shift them into the unsigned int 
register array in 16 bits from MSbit to LSbit. So reading 25 points you must 
make sure the array (readRegs3[] in this case) can handle all the points, which 
is of course 2 unsigned int registers.

Also try not to use delay() longer than a few (<100ms). Rather use millis().

Test code:
enum
{
  CONFIG1, //00001-00018
  CONFIG2, //40000-40004
  INFO,    //15000-15024
  STATUS,  //10000-10003
  COMMAND, //10004-10013
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];

packetPointer config_1 = &packets[CONFIG1];
packetPointer config_2 = &packets[CONFIG2];
packetPointer info_1 = &packets[INFO];
packetPointer status_1 = &packets[STATUS];
packetPointer command_1 = &packets[COMMAND];

unsigned int config1_regs[1];
unsigned int config2_regs[1];
unsigned int info1_regs[2];
unsigned int status1_regs[1];
unsigned int command1_regs[1];

void setup()
{
 Serial.begin(9600); 
  modbus_construct(config_1, 1, READ_COIL_STATUS, 1, 11, config1_regs); 
  modbus_construct(config_2, 1, READ_HOLDING_REGISTERS, 0, 2, config2_regs);
  modbus_construct(info_1, 1, READ_INPUT_STATUS, 5000, 25, info1_regs);
  modbus_construct(status_1, 1, READ_INPUT_STATUS, 0, 4, status1_regs);
  modbus_construct(command_1, 1, READ_INPUT_STATUS, 4, 10, command1_regs);

  modbus_configure(baud, SERIAL_8O1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

Original comment by bester.j...@gmail.com on 19 Aug 2013 at 9:33

GoogleCodeExporter commented 8 years ago
Thanks! According to the factory doc, they using the 20000 address space for 
the most important things. I attached the protokol spec.(it german, but easy to 
understand), i you have a couple of minutes please have a quick look.

Original comment by kraftair...@gmail.com on 20 Aug 2013 at 2:06

Attachments:

GoogleCodeExporter commented 8 years ago
Ah!

They are using the full 16 bit address space. So you were correct. They only 
implement function 3, 4, 6 and 16. You will have to extract the bits your self 
from address 15000 and 20000, see page 3, Table 3 where they are using 15012 as 
an example.

The registers array that you assign to the packet must be the larger or the 
same size as what you are requesting.

unsigned int readRegs1[11];
unsigned int readRegs2[2];
unsigned int readRegs3[25];
unsigned int readRegs4[4];
unsigned int readRegs5[10];

void setup()
{
 Serial.begin(9600); 
  modbus_construct(config_1, 1, READ_HOLDING_REGISTERS, 10001, 11, readRegs1); 
  modbus_construct(config_2, 1, READ_HOLDING_REGISTERS, 40000, 2, readRegs2);
  modbus_construct(info_1, 1, READ_INPUT_REGISTERS, 15000, 25, readRegs3);
  modbus_construct(status_1, 1, READ_HOLDING_REGISTERS, 20000, 4, readRegs4);
  modbus_construct(command_1, 1, READ_HOLDING_REGISTERS, 20004, 10, readRegs5);
  modbus_configure(baud, SERIAL_8O1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

First try reading one register to verify communication...

Original comment by bester.j...@gmail.com on 21 Aug 2013 at 6:27

GoogleCodeExporter commented 8 years ago
Ok, i will try. There is some time till the unit arrives tough...
So thanks! I will report my progress.

Original comment by kraftair...@gmail.com on 21 Aug 2013 at 7:06

GoogleCodeExporter commented 8 years ago
I had a chance finally to test my code against the real Unit, but i get no 
response. Do you have any ideas what could be wrong? 
I'm using this basic code

//**************************
#define baud 9600
#define timeout 1000
#define polling 200 
#define retry_count 5
#define TxEnablePin 2 

enum
{
  CONFIG2, //40000-40004
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];

packetPointer config_2 = &packets[CONFIG2];

unsigned int readRegs2[2];

void setup()
{
 Serial.begin(9600); 

  modbus_construct(config_2, 1, READ_HOLDING_REGISTERS, 40000, 2, readRegs2);

  modbus_configure(baud, SERIAL_8O1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}

void loop()
{
  modbus_update();

  for (int i = 0; i <= 4 ; i++){ 
   lcd.println(readRegs2[i]);   
  }
delay(300);
}
//****************************

Original comment by kraftair...@gmail.com on 18 Oct 2013 at 6:12