Can not read string array
Closed this issue · 6 comments
Trying to read string array and only get first 2 elements. Writes work perfectly. Can always read array of 2. Code below produces following:
Values read: { STRARRAY: [ 'String 00', 'String 01', '', '' ] }
[50475,547282909 10.0.0.101] Preparing to WRITE STR0,STR1,STR2,STR3,STR4
[50475,559641594] NST9:0 write completed with quality OK
[50475,559721341] NST9:1 write completed with quality OK
[50475,559756823] NST9:2 write completed with quality OK
[50475,559794130] NST9:3 write completed with quality OK
[50475,559815871] NST9:4 write completed with quality OK
Done writing.
function connected(err) {
if (typeof(err) !== "undefined") {
// We have an error. Maybe the PLC is not reachable.
console.log(err);
// process.exit();
}
conn.setTranslationCB(tagLookup);
conn.addItems('STRARRAY');
// conn.addItems(['INT0','INT1','INT2', 'INT2']);
async.forever(
function(next) {
//conn.readAllItems(valuesReady);
if (doneReading && doneWriting) {
doneReading = false;
conn.readAllItems(function (err, values) {
if (err) {
console.log("SOMETHING WENT WRONG READING VALUES!!!!");
plc_error = true;
} else {
console.log('Values read: ',values)
plc_error = false;
++sheet_length;
conn.writeItems(['STR0', 'STR1', 'STR2', 'STR3', 'STR4'],
['String 00', 'String 01', 'String 02', 'String 03', 'String 04'], valuesWritten);
// conn.writeItems(['INT0', 'INT1', 'INT2'],
// [2, sheet_length, 500500], valuesWritten);
doneWriting = false;
}
doneReading = true;
setTimeout(function () {
next();
}, 1000);
// if (doneWriting) { process.exit(); }
});
}
},
function(err) {
console.log('READ LOOP ERROR: ' + err);
}
);
}
function valuesWritten(anythingBad) {
if (anythingBad) { console.log("SOMETHING WENT WRONG WRITING VALUES!!!!"); }
console.log("Done writing.");
doneWriting = true;
}
// This is a very simple "tag lookup" callback function that would eventually be replaced with either a database findOne(), or a large array in memory.
// Note that the return value is a controller absolute address and datatype specifier.
// If you want to use absolute addresses only, you can do that too.
function tagLookup(tag) {
switch (tag) {
case 'TEST1':
return 'Test_Int'; // Integer
case 'TEST2':
return 'B3:0/0'; // Bit
case 'TEST3':
return 'B3/17'; // Same as B3:1/1
case 'TEST4':
return 'F8:0,20'; // Yes this is an array... 20 real numbers.
case 'TEST5':
return 'F8:1'; // Single real.
case 'TEST6':
return 'F8:2'; // Another single real.
case 'TEST7':
return 'N7:1,2'; // A couple of integers in an array
case 'TEST8':
return 'NST9:2,4'; // Direct output
case 'TEST9':
return 'N7:0'; // Direct output
case 'STRARRAY':
return 'NST9:0,4'; // setup number
case 'STR0':
return 'NST9:0'; // setup number
case 'STR1':
return 'NST9:1'; // customer name
case 'STR2':
return 'NST9:2'; // order number
case 'STR3':
return 'NST9:3'; // next operation
case 'STR4':
return 'NST9:4'; // generic comment
case 'INT0':
return 'L7:0'; // discharge direction (flags?)
case 'INT1':
return 'L7:1'; // sheet width
case 'INT2':
return 'L7:2'; // sheet length
case 'INT3':
return 'L7:3'; // sheets in discharge
case 'INT4':
return 'L7:4'; // sheets in discharge
case 'INT5':
return 'L7:5'; // stacks to batch
default:
return undefined;
}
}
Did you verify the write in Studio 5000?
Because it's an N file, it needs 44 integers for a string, STR1 should be NST9:44, then 88 and so on.
I've never been able to get it work writing with single dimension array. Always writes over first location offset by one.
But writing to a 2 dimensional array works great! N9 INT[100,44] (100 strings). STR0 = N9[0,0] STR1 = N9[1,0], STR2 = N9[2,0]...
Then this instruction copies to a true STRING array: COP N9[0,0] PC_STRING[0] 100
Can only read back the first two though.
That is why it works for me and not for you - I think it will be really difficult to support two-dimensional arrays with nodePCCC because the PCCC protocol is meant for simple data tables.
Reason: When we read an array of NSTRING values, we need to read 88x4 = 352 bytes. The maximum amount of PCCC data we can request varies, but the latest nodePCCC figures it's about 200 in my case, but then shortens this to 176 to keep from "splitting a string" over multiple read requests. So it comes up with two chunks of data - one starting at N9:0, and another one starting at - it calculates N9:88, because this is 176 bytes later, and the "88" number is part of the request for the second half of the data. But in the case of a two dimensional array, how the ControlLogix/CompactLogix maps a two dimensional array to a SLC file internally probably doesn't agree with that calculation. You could fill the array with a bunch of characters to see what you're getting, but then we would need additional syntax in the item definition to support this properly, and that could get complicated when extended to other data types as well. Time would be better spent supporting CIP to get the tag in its native format.
When I tested this on the weekend, I set up a CompactLogix with the following variables:
N9 created as INT[484]
ST41 created as STRING[5]
And a single instruction in the program:
COP ST41[0] N9[0] 484
I typed in values in Logix for the strings and wanted to read them as NSTRINGS.
I then was able to read strings using either of the following methods:
TEST8 - NST9:0,4 to read or write ALL strings as an array.
STR0 - NST9:0
STR1 - NST9:44
STR2 - NST9:88
STR3 - NST9:132
Writing the array works too, I tested this as well, with the COP instruction disabled.
I would suggest you try the single-dimension arrays again with the COP done the way I suggest, it works much better with 0.1.11.
Alternatively, edit the code for theItem.plcnpratio = 44; on line 2412 and try different values to find what works for a two-dimensional array.
Ok, I see what I was doing wrong when writing to the single array. All works as advertised now.
I might continue using the two dimensional array for writing though. Works so nice.
Thanks!
Good to hear it's working better now. When I get a chance I will see if I can figure out what the PLC is doing with the 2D array and the PCCC request.
I did play around a bit with 2D arrays and at least I understand a little better how that works. If you set the plcnpratio to 1 instead of 44 as in the latest code, it works reading and writing large arrays of strings. If you want to have this as an option that you specify when connecting, I will add it, but I don't want to force it to be that way as I don't want to break any existing applications. Either way I will close the issue, it works now with single-dimension arrays and we can support the 2D ones easily if anyone asks for the option.