Struggling with Syringe Pump Communication

Hi,

I don't mean to bother anyone if I'm missing a previous post, but the ones relating to syringe pump control are missing code or haven't really aided me in solving my issue.

I am trying to control an old Harvard Apparatus pump 11, the manual is here: https://cdn2.hubspot.net/hubfs/3909336/InstechLabsSeptember2017/pdf/HA11_Plus_manual.pdf

I have managed to control it by using the terminal from a computer following contact from the manufacturer on how to, but am struggling with the programming on an arduino, it just won't register my messages, but the RS232 TX Shifter lights up.

I've tried switching the RX and TX lines to see in I need to use it as a null modem type connection or if standard straight would be better, but neither have worked.

I've attached it and reprogrammed to use Rx and Tx pins for Serial to change to be Serial.begin(9600, Serial_8N2), but that didn't read either.

I have also added in an extra endmarker to send as the manufacturer said it required 2 stopbits, but softwareserial won't allow any deviation form 8N1 default. Here's the manufacturer's email f it helps:

Do you have a copy of the manual? I have attached a copy to this email

the first step is to put the pump into remote communications mode (see page 12)
make sure the address of the first pump is set to 00

Then try running the pump from a PC, using Pump Terminal
https://drive.google.com/open?id=0B1rm6OCy9gZEUFI0UUpQZDhQV2M

You will need to set the baud rate to match what is on the pump, and change the stop bits to 2 (and make sure word size is 8 and Parity is none)
this has to be done in both the device manager and the Pump Terminal software itself

Then try sending some commands.

If that works, then try it on your Arduino

Also, did you make the serial cable yourself? did you make sure to use a straight through cable (otherwise you have to change the pinout at the other end to match your cable's properties)

Here's the code I'm using:

#include <SoftwareSerial.h>                           //we have to include the SoftwareSerial library, or else we can't use it
#define rx 4                                          //define what pin rx is going to be
#define tx 5                                          //define what pin tx is going to be

SoftwareSerial myserial(rx, tx);                      //define how the soft serial port is going to work

const byte numChars = 16;
char receivedpcChars[numChars];                       // Array to store the input.
char receivedRS232Chars[numChars];                      // Array to store ezo data
boolean pcdata = false;                               // Check for incoming new data.
boolean RS232data = false;                               // Incoming ezo response check

String pc_message;
String RS232_message;                                


void setup() {
Serial.begin(9600);                                   // Setup the arduino you've connected to
myserial.begin(9600);
delay(5);
}

void loop(){

pc_input();
pc_to_RS232();
RS232_input();
RS232_to_pc();
Serial.print(pc_message);                             // Troubleshoot the message I'm Sending
}
  
  
void pc_input() {
  static byte ndx = 0;
  char endMarker = '\r';
  char rc;

  if (Serial.available() > 0) {
    rc = Serial.read();
    if (rc != endMarker) {
      receivedpcChars[ndx] = rc;
      ndx++;
      if(ndx >= numChars){
        ndx = numChars - 1;
      }
    }
    else {
      receivedpcChars[ndx] = '\0';
      ndx = 0;
      pcdata = true;
    }
  } 
}




void pc_to_RS232() {
  pc_message = receivedpcChars;
  if (pcdata == true){
    myserial.print(pc_message);
    myserial.print('\r');
    myserial.print('\r');
  }
  else {
    delay(1);
  }
  pcdata = false;
}



void RS232_input() {
  static byte ndx = 0;
  char startmarker = '\n';
  char endMarker = '\r';
  char rc;

  if (myserial.available() > 0) {
    rc = myserial.read();
    if (rc != endMarker) {
      receivedRS232Chars[ndx] = rc;
      ndx++;
      if(ndx >= numChars){
        ndx = numChars - 1;
      }
    }
    else {
      receivedRS232Chars[ndx] = '\0';
      ndx = 0;
      RS232data = true;
    }
  } 
}


void RS232_to_pc() {
  RS232_message = receivedRS232Chars;
  if (RS232data == true){
    Serial.print(RS232_message);
    Serial.print(". ");
    Serial.println('\r');
  }
  else {
    delay(1);
  }
  RS232data = false;
}

I'm using an arduino Uno, a sparkfun RS232 shifter module and a Harvard Apparatus Pump 11 with an RS232 DB9 port. Apologies if my programming is bad as I'm only at this 2 months or if I'm taking on a bit too much this early, just need to get this working.

Thanks in advance for the feedback.

LukePower:
I have also added in an extra endmarker to send as the manufacturer said it required 2 stopbits, but softwareserial won't allow any deviation form 8N1 default.

That will not help. If the pump really insists on 2 stop bits, you may be able to fool it into thinking it got them by sending characters one at a time with a small delay between them.

I'd suggest that you start with a much simpler program too. Just send one hard coded command to the pump and echo back what was received until you establish that you can communicate.

You appear to have no choice but to use the hardware serial for this one, as that can be set to 8N2, as required by this device.

Easiest is to have an Arduino with multiple hardware Serial, such as the Mega, so you still have the regular Serial with USB connection for debugging.

From SoftwareSerial.cpp line 613

	  uint8_t oldSREG = SREG;
  cli();  // turn off interrupts for a clean txmit

  // Write the start bit
  tx_pin_write(_inverse_logic ? HIGH : LOW);
  tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);

  // Write each of the 8 bits
  if (_inverse_logic)
  {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
      if (b & mask) // choose bit
        tx_pin_write(LOW); // send 1
      else
        tx_pin_write(HIGH); // send 0
    
      tunedDelay(_tx_delay);
    }

    tx_pin_write(LOW); // restore pin to natural state
  }
  else
  {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
      if (b & mask) // choose bit
        tx_pin_write(HIGH); // send 1
      else
        tx_pin_write(LOW); // send 0
    
      tunedDelay(_tx_delay);
    }

    tx_pin_write(HIGH); // restore pin to natural state
  }

  SREG = oldSREG; // turn interrupts back on
  tunedDelay(_tx_delay);
  
  return 1;
}

Maybe you could simply add an additional tx_pin_write(HIGH/LOW) and tunedDelay after the “8” bits.

Basically tricking the code to send :
start bit
9 data bits always ending with value of the stop bit
stop bit.

For a single use project as your describing maybe that workaround will get you commanding the syringe.

wildbill:
you may be able to fool it into thinking it got them by sending characters one at a time with a small delay between them.

Looking at the manual, the longest command looks to be about 8-10 characters, including the CR termination. The commands are not rapid-fire real-time anyway. I think inserting a character time between each one sent would work okay.