Jonny007-MKD
2279ff04b0
Added default value of 1 to gDevReceiveWindow because gtRobin would do anything in MakeConfig
285 lines
7.6 KiB
Plaintext
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;
|
|
}
|
|
} |