Bachelorthesis/Modbus-CAPL/include/CAPL/include/DeviceInformation.cin
Jonny007-MKD 2279ff04b0 DeviceInformation.cin
Added default value of 1 to gDevReceiveWindow because gtRobin would do anything in MakeConfig
2014-06-17 14:28:29 +00:00

285 lines
7.6 KiB
Plaintext

/*@!Encoding:1252*/
variables
{
word gDevOutputBitAddr, gDevOutputRegAddr;
word gDevInputBitAddr, gDevInputRegAddr;
word gDevBitMaxCount, gDevRegMaxCount;
word gDevReceiveWindow = 1;
enum Vendor
{
Wago = 23,
BuR = 2
};
struct deviceIOs
{
byte InputRegisters;
word InputBits;
byte OutputRegisters;
word OutputBits;
char Modules[1024];
};
struct device // A structure that contains information about an Modbus device
{
char Ip[16]; // String: The IP address
char IpLsb[4]; // String: The last byte of the IP address. Used as index of node name
char IpNet[4]; // String: The second last byte of the IP. Used as index of net
enum Vendor Vendor; // The Vendor (Wago / B&R)
word SerialCode; // Serial Code
word DeviceCode; // Device Code
struct deviceIOs DeviceIOs; // A structure with more information about IOs
};
}
// This is for the normal client and for making the sysvars
/// <ModbusClient>
void DeviceInit(byte vendor)
{
switch ((enum Vendor) vendor)
{
case Wago:
gDevInputBitAddr = 0x0000; // Wago inputs start at 0x000
gDevInputRegAddr = 0x0000;
gDevOutputBitAddr = 0x0200; // Wago outputs start at 0x200
gDevOutputRegAddr = 0x0200;
gDevBitMaxCount = 0x0100; // Wago allows up to 256 inputs
gDevRegMaxCount = 0x0100;
gDevReceiveWindow = 5; // Wago can handle 5 requests simultaneously
break;
case BuR:
gDevInputBitAddr = 0x0000; // B&R inputs start at 0x000
gDevInputRegAddr = 0x0000;
gDevOutputBitAddr = 0x0000; // B&R digital outputs start at 0x000
gDevOutputRegAddr = 0x0800; // B&R analog outputs start at 0x800
gDevBitMaxCount = 0x4000; // B&R allows up to 16348 digital inputs
gDevRegMaxCount = 0x0800; // B&R allows up to 2048 analog inputs
gDevReceiveWindow = 1; // B&R can only handle 1 request at a time
break;
}
}
// This is for making the sysvars (MakeConfig)
/// <MakeConfig>
void DeviceParseCode(word dev, enum Vendor vendor, struct deviceIOs dios)
{
byte input;
byte numChannels;
char module[10];
switch(vendor)
{
case Wago: // if this is a Wago device
if (dev & 0x8000) // Digital Module
{
numChannels = (dev >> 8) & 0x007F;
if (dev & 0x0001) // Input Module
{
input = 1;
strncpy(module, "DI%d,", elCount(module));
}
else if (dev & 0x0002) // Output Module
{
input = 0;
strncpy(module, "DO%d,", elCount(module));
}
else // mhm. What is it?
{
writeDbg(AlgoError, "ParseDeviceCode: Device code 0x%X cannot be decoded", dev);
OnModbusClientPanics(DeviceCodeUnknown);
}
}
else
{
// http://www.wago.com/wagoweb/documentation/navigate/nm0dx__d.htm
// http://www.wago.com/wagoweb/documentation/navigate/nm0dy__d.htm
switch (dev)
{
case 881: // devices that have no inputs/outputs
return;
case 491: // devices that have 1 inputs
input = 1;
numChannels = 1;
break;
case 452: // devices that have 2 inputs
case 465:
case 470:
case 472:
case 480:
case 454:
case 473:
case 474:
case 466:
case 484:
case 485:
case 492:
case 482:
case 475:
case 467:
case 477:
case 478:
case 456:
case 479:
case 476:
case 483:
case 461:
case 481:
case 462:
case 469:
case 487:
input = 1;
numChannels = 2;
break;
case 493: // devices that have 3 inputs
case 494:
case 495:
input = 1;
numChannels = 3;
break;
case 459: // devices that have 4 inputs
case 453:
case 455:
case 468:
case 457:
case 464:
case 460:
case 463:
input = 1;
numChannels = 4;
break;
case 552: // devices that have 2 inputs
case 585:
case 563:
case 554:
case 550:
case 560:
case 562:
case 556:
input = 0;
numChannels = 2;
case 555: // devices that have 4 inputs
case 553:
case 557:
case 559:
input = 0;
numChannels = 4;
default: // unknown device. Ouch!
writeDbg(AlgoInfo, "Connected device: 750-%d", dev);
return;
}
if (input)
strncpy(module, "AI%d,", elCount(module));
else
strncpy(module, "AO%d,", elCount(module));
}
break; // switch(vendor)
default:
writeDbg(AlgoError, "ParseDeviceCode: Unknown vendor id: %d", vendor);
OnModbusClientPanics(VendorIdUnknown);
return;
}
snprintf(module, elCount(module), module, numChannels);
strncat(dios.Modules, module, elCount(dios.Modules));
}
// This function requests more information from the device and return the number of expected results
/// <MakeConfig>
byte DeviceGetInformation(enum Vendor vendor)
{
switch (vendor)
{
case Wago:
ModbusReadRegisters(0x2011, 1); // Serial Code
ModbusReadRegisters(0x2012, 1); // Device Code
ModbusReadRegisters(0x1022, 1); // Number of AOs (= size in bits)
ModbusReadRegisters(0x1023, 1); // Number of AIs (= size in bits)
ModbusReadRegisters(0x1024, 1); // Number of DOs
ModbusReadRegisters(0x1025, 1); // Number of DIs
ModbusReadRegisters(0x2030, 65); // Connected IO 1
ModbusReadRegisters(0x2031, 64); // Connected IO 2
ModbusReadRegisters(0x2032, 64); // Connected IO 3
ModbusReadRegisters(0x2033, 63); // Connected IO 4
return 10;
case BuR:
ModbusReadRegisters(0x1083, 1); // Product Code
ModbusReadRegisters(0x1101, 1); // Number of AIs
ModbusReadRegisters(0x1103, 1); // Number of AOs
ModbusReadRegisters(0x1105, 1); // Number of DIs
ModbusReadRegisters(0x1107, 1); // Number of DOs
return 5;
}
return 0;
}
// This function parses the received registers
/// <MakeConfig>
void DeviceParseRegister(struct device device, word address, word data[], word count)
{
byte i;
switch (device.Vendor)
{
case Wago:
// Parse the received data
switch (address)
{
case 0x2011:
device.serialCode = data[0];
break;
case 0x2012:
device.deviceCode = data[0];
break;
case 0x1022:
device.DeviceIOs.OutputRegisters = data[0] / 16; // Wago returns the size in bits allocated by the module
break;
case 0x1023:
device.DeviceIOs.InputRegisters = data[0] / 16;
break;
case 0x1024:
device.DeviceIOs.OutputBits = data[0];
break;
case 0x1025:
device.DeviceIOs.InputBits = data[0];
break;
case 0x2030:
case 0x2031:
case 0x2032:
case 0x2033:
for (i = 0; i < count; i++)
{
if (data[i] == 0x0000) // No more devices --> end
break;
DeviceParseCode(data[i], device.Vendor, device.DeviceIOs);
}
break;
}
break;
case BuR:
// Parse the received data
switch (address)
{
case 0x1083:
device.serialCode = data[0];
break;
case 0x1101:
device.DeviceIOs.InputRegisters = data[0];
break;
case 0x1103:
device.DeviceIOs.OutputRegisters = data[0];
break;
case 0x1105:
device.DeviceIOs.InputBits = data[0] * 8; // Unfortunately this is quite imprecise:
// in the process image one module will always fill a whole number of bytes.
// So 4 12DI modules not allocate not 4*12 bit = 6 byte, but 4*16 bit = 64 bit = 8 byte
// See Modbus X20BC0087 documentation v1.11 p. 22
break;
case 0x1107:
device.DeviceIOs.OutputBits = data[0] * 8;
break;
}
break;
}
}