Sending/Receiving Data via RS232

I'm trying to connect a chiller to an arduino nano via tx/rx RS232 pins and poll the temperature.
The datasheet of the chiller specifies that the commands must be sent in hex (eg: CA 00 01 20 00 DE) before the chiller will respond with a similarly formatted answer.

Hardware wise, I have the nano hooked up to an MAX232 Transceiver which connects to the chiller via a spliced RS232 Cable

Coding wise i'm not really sure the best way to send these commands (rather new to serial communications)

what i've got so far is something along these lines:

int x=0;
const char command1[] = {0xCA, 0x00, 0x01, 0x20, 0x00, 0xDE};
static char inChar=-1;
static int pos=0;
char answer[20];

void setup()
{
      Serial.begin(9600);
}

void sendCommand(const char *cmd)
{

     for(int i = 0; i <sizeof(cmd); i++)
     {
     Serial.write(cmd[i]);
     }

}

void loop()
{
    sendCommand(command1);
    while(Serial.available()){

            inChar=Serial.read();
            answer[pos]=inChar;
            pos++;
            answer[pos]=0;
     }
     for(int x=0;x!='\0';x++){
            Serial.print(answer[x],HEX);
            
     }
     Serial.print('\n');
     delay(1000);
}

Any advice on tutorials or examples would be much appreciated

for(int x=0;x!='\0';x++)

That's a very short loop.

for(int x=0; answer[x] ;x++)

Ah seems I missed that one,

However i'm still not able to get any sort of response from the machine once the command is sent

Do I need to specify the tx/rx pins? and how does one differentiate between usb serial and tx/rx serial?

Post a diagram of how things are connected - a photo of a pencil sketch will be find.

Does the Nano have a USART as well as the USB serial (like a Leonardo) ? On the Leonardo the USB is Serial and the USART is Serial1

You can use Serial.write(buffer, numBytes) to send all the bytes with one instruction.

const char command1[] = {0xCA, 0x00, 0x01, 0x20, 0x00, 0xDE};

does NOT send HEX. It just sends bytes which could just as well have been specfied as {202, 0, 1 etc}

That may indeed be what is required. But it's just possible that it wants the characters CA 00 01 etc.. Can you post a link to the datasheet.

...R

Stuff to consider:
Grounds connected?
Correct serial configuration? 9600,8,N,1 is what you now have.
Need "Null Modem" connection, Rx-Tx, Tx-Rx ?
RTS/CTS Handshake?
Does command string need lineend(s), \n and/or \r, in correct order ?

See here for more possibilities:

There is only one set of Rx, Tx pins.

This is the circuit i've got currently set up

From what i've read about the nano it's not like the leonardo (i.e. no Serial1, just serial).

Here's the datasheet for the chiller i'm using

The RS232 pinout is explained on page 16 and the communication protocols are explained on pages 27-30 (mostly on 28 though)

Thanks for the help

I just checked the Nano and, as you say, it only has one hardware serial port.

That means you will have to use the SoftwareSerial library to communicate with the chiller. You can't communicate with two devices on the same serial connection. SoftwarSerial allows you to use a couple of other pins for Rx and Tx for talking to the chiller.

From a quick look at the datasheet it does indeed just need bytes of data so the style you already have

const char command1[] = {0xCA, 0x00, 0x01, 0x20, 0x00, 0xDE};

is nearly correct. It needs to be const byte command[] to allow for values above 127 (0x7F).

...R

is using SoftwareSerial really easy as adding

#include <SoftwareSerial.h>

#define rxPin 10
#define txPin 11

SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

void setup()
{
      pinMode(rxPin, INPUT);
      pinMode(txPin, OUTPUT);
      mySerial.begin(9600);
}

and then changing every instance of Serial.something to mySerial.something?

daflippymaster:
is using SoftwareSerial really easy as adding

YES - fingers crossed :slight_smile:

...R

Well it almost works :disappointed_relieved:

The output of the MAX232 shows the correct data on the scope, however i'm still getting no response from the chiller.

I'm thinking it because the output of the MAX232 is only +/- 1V which I think might be too low a signal for the chiller.


EDIT: Found the source of the problem! The probes we were using for the scope had something funky goin on, now the output shows about +/- 10V.

Still no response from the machine -___- I suspect the cable at this point.

The probes we were using for the scope had something funky goin on,

10:1 scope probes.
Second time this week.

Finally figured out the problem
Turns out the datasheet i've been trying to use is not the right one (exact same make and model of chiller, different control panel >_<)

This is the correct one.

These commands are specified in ASCII, however am I able to convert them to hex and send them that way still?

EDIT:

Finally got it to work!! Thanks to everyone for all of the help, this a great community here

I'm communicating with a chiller using softwareSerial on an arduino nano

After a command is received by the chiller, it sends a confirmation. The trouble I have is reading in this confirmation after the command is sent because the time between the arrival of the confirmation varies.

adding delay(1500) works most of the time for most commands, but its hit-or-miss

here's the code i'm using

#include <SoftwareSerial.h>

byte turnOn[]={0x53,0x4F,0x31,0x0D};
byte turnOff[]={0x53,0x4F,0x30,0x0D};
byte SetPoint[]={'R','S',13};
byte MainT[]={'R','T',13};
byte RemoteT[]={'R','R',13};
int tempNum=0;
char tempChar;
#define rxPin 10
#define txPin 11
String answer;

SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

void setup()
{
      pinMode(rxPin, INPUT);
      pinMode(txPin, OUTPUT);
      mySerial.begin(9600);
      Serial.begin(9600);     
}

void loop()
{
      mySerial.write(RemoteT,3);
      delay(1500);
      
      while(tempNum!=13)
      {
      tempNum=mySerial.read();  
      tempChar=tempNum;
      answer+=tempChar;
      }
      Serial.print(answer);
      Serial.write('\n');
     
}

any suggestions?

Why the delay?
Why not wait for the expected response?

@daflippymaster,
Let's keep the topic on track please.
You're comm's are pretty slow.
Could you connect Rx in parallel to an interrupt pin, and capture micros() in the ISR and then process the data?

Or rather, is there an equivalent of

if (mySerial.Available() >0){
// read the next byte that came in
}

Sorry about that

Do you mean use the interrupt to find how long the confirmation took to arrive? Or do you mean use the interrupt to actually display the data once it comes in?


EDIT: Got it working, I was forgetting the 'my' in front of while(!Serial.available());

Thanks for the help!

For some reason when this function is called, it causes the serial monitor to freeze up and it won't respond until i've uploaded a completely different sketch a couple times to the arduino

The bug seems to be occurring somewhere around the "while(!mySerial.available());" and I can't for the life of me figure out whats wrong. No errors when compiling.

void SetSetpoint(){

  String SetPoint;
  byte command[10];
  char temp[8];
  char Start[]={'S','S'};
  char End[]={'\r'};
  char answer[8];
  Serial.println("Enter a temperature between -30.00 and +150.00C");
  
  while(!Serial.available());
  Serial.readBytesUntil('\r',temp,6);
  SetPoint+=Start;
  SetPoint+=temp;
  //SetPoint+=End;
  SetPoint.getBytes(command,8);

  mySerial.write(command,8);
 
  while(!mySerial.available());
  mySerial.readBytesUntil('\r',answer,6);
  
  Serial.println(answer);
  
  Serial.println(SetPoint);
  
}
while(!Serial.available());

This is like a delay() of unknown length. Try to rewrite your code so that it is not needed - unless you really want the Arduino to be completely inactive until some data is received.

Serial.readBytesUntil('\r',temp,6);

And this is not much better because the Arduino can do nothing useful until all the data has arrived.

If you look at the Arduino code here (Reply #4) you will see how the Serial data can be collected byte by byte without holding up other stuff.

...R

Its not too incredibly critical that the arduino not be tied up waiting for data, and this is one instance where it needs to wait for input from the user.
After a little more debugging it looks like the arduino freezes right after the "mySerial.write"

Using a logic analyzer, the correct data is being sent expect for at the very end. The last byte is a null character instead of a carriage return, which I think might be the problem