Hi Kate,
Thanks for the protocol document. Luckily, the RTS/DTR (hardware control/handshake) lines do not seem to be required. That is good to know since the shield you are using does not support those.
Serial.write() would be the proper command to use, but Serial.print/println can work too, depending on how you setup your string/buffer for sending the command.
Assuming that your DB25<->DB9 converter cable redirects the TX/RX line around properly (you may want to check that quickly with a multimeter, continuity test), there seems to be no obvious electrical/hardware/interface issues.
As for your code, here is a few notes:
The serial code used to send a command to the dispenser seems valid at first glance. Did you check to confirm the “if(counter < rows){” block is executed? You could add extra debug code there, such as blinking a LED or something similar for a second so you know it is executing. You mentioned previously there is no effect on the instrument when writing to its serial interface, but is there any motor action? Are the timings (calculated delays) OK?
The line “else if (counter == rows) {” may very well never execute, depending on if counter and rows match up properly. If counter is ever changed in a way where it skips the value of rows, it would continue until overflow. A good way to prevent this is using something like “if (counter >= rows) {”.
Since there are only two options in this case, you could simply use “else {” at the end instead of a “else if (…) {”, since if it is not “< rows”, then it has to do that other code instead.
Also, it seems you have code to increment your counter value by +1 or +2, but no code to reset it to 0. Is that on purpose?
Another important point, your lines “if (platesize = 96) {” and “else if (platesize = 384) {” are using “=” (assignment) instead of “==” (equality test). Because of this, the first “if” would assign a value of 96 to platesize, which would the evaluate to true (0 = false, anything else = true).
On a general note, you may want to either define your “rowTime” variable as a float (so it can store non-integer values, right now it is defined as a int), or you could keep it as an int (probably a long instead) and instead calculate everything in ms to begin with. ex:
rowTime = 0.016*(volume) + 2.400;
would become
rowTime = 16*(volume) + 2400;
This would allow for fast and easy use of the numbers and also prevent losing precision due to conversion from float/integers and from representation in RAM (pure integer math is exact, whereas float may not be in most cases). We strongly recommend using the integer (long) solution since it would make using delay() more straightforward, too, since that function only accepts unsigned long values and therefore another conversion is made there when you pass the value if it is not of the right time (ex: a float).
We recommend that you verify your code against all the comments above and see if that helps. It may be best to make a smaller example/test code where you only send one command once (ex: in setup()) to the device instead of in a loop, just as a test to see if it responds properly. Once you have working code to control that instrument, then integrate it into your loop.
Sincerely,