rs232 newbie question

I have a relay board that accepts hex rs232 data to change 16 relays, but the device I want to control it with only sends ascii data... How difficult would it be for me to accomplish this with arduino? I basically want to send 1 ascii number or letter to send to arduino then have arduino reply back either on the same 232 port or even a different port with hex data to activate or deactivate a relay. How and what board would an expert use to do this...?

Thanks!

a professional would buy some premade device to avoid any troubleshooting issues costing several hundered dollars, least I would

as far as ASCII, well ascii represents charters based on their hex value, so it should be easy enough to convert from ascii to hex, as far as what board you need, not many directly support RS232 anymore. Though you can can connect the RX and TX pins of an arduino though a converter (like a max232, the TI version costs less than a dollar)

hex rs232 data

Meaning raw binary?

the device I want to control it with only sends ascii data

Meaning 2 characters or 1? If there are only 16 devices 1 is enough.

rs232 data

Meaning genuine RS-232 voltage levels or is this just the common misuse of the term and you really mean async serial?

If it's genuine RS-232 then as Osgeld said you need a chip to convert the voltages.

Whatever the answers are it's a pretty easy task for an Arduino.


Rob

Please excuse my faulty terms when typing my original post... The home automation panel is genuine 232 voltages as well as the relay board I have. The home automation panel lets me type ascii messages up to 15 characters long, but doesn't seem robust enough to send anything else than ascii characters. The program that comes with the relay board is called comm operator which sends bytes of data in hex or decimal. The manufacturer of the device is saying that I need to be sending ascii character codes instead of what my panel sends [which is ascii characters].

But an ASCII character is Hex data.
An ASCII character is composed of a byte (8 bits), 0x00 - 0xff.
Some terminal programmes cannot (do not) send all of the ASCII control codes ( 0x00 - 0x1f )
An Arduino is fully capable of rattling off any combination of bytes in "8N1" fashion.
So you just need to come up with a TTL to RS232 interface (MAX232, et al)

Your device/s may accept the Arduino output inverted (via npn transistor, common collector config.)
A MAX233 will effect "RS-232 compliant" signalling.

ASCII-std.bmp (295 KB)

Do you have links to the products? The below has some info on rs232 to TTL conversion info

http://www.scienceprog.com/alternatives-of-max232-in-low-budget-projects/

Can you provide links to technical information for the Home Automation board and the Relay Board.
Of particular use would be a description of the protocol the Relay Board uses.

-radman
http://www.relaycontrollers.com/Relay/Device/A0010 The actual model number for it is ZADSR165PROXR_ZRS <<<<< relay board
http://www.homeauto.com/Downloads/Products/AutomationControllers/OmniProII/OmniPro2.pdf <<<<automation panel

I'm probably not right in assuming its genuine 232 on my automation board or the relay board and also I'm not opposed to just ditching the relay board and using a custom relay board that will accept my ascii characters. It would actually help me if i did have a different relay board because this automation panel has 5 separate 232 ports and i could use some existing ascii messages to trigger them without using up my 127 message limit on the board. Essentially i would need to send 32 different commands for my relays 1-16 for relays on 17 thru 32 for relays off. If i needed the relays timed from 1 second all the way up to 18 hours i can easily do that by starting a timer on my automation panel and then sending a command 17 thru 32 to turn it off later.

An idea possibly would be something like this?? :astonished:

and

Jon,

While translations of electrical signals and encodings and protocol messages are definitely possible
and often not difficult to do,
from your current description, it isn't possible to tell what you need.

There are two distinct things that you have to address:

  • The physical layer
    This is the electrical connections and how the data flows over those connections.
    It is things like voltage levels and how the data bits are encoded and sent.
    For asynchronous serial communication,
    this also includes things like baud rate, data bits, stop bits, parity, etc...

  • The message protocol
    This is how the higher layers communicate.
    It is things like message and data format of
    requests and responses.
    i.e. what are the data bytes of messages and responses?
    what are the expected responses to requests?

If there is a mismatch at either layer, you have to provide some kind of translation.
What may help is drawing a picture that shows the components and how they
communicate.

The term "rs-232" refers to a very specific standard that includes data encoding, electrical levels
and handshakes. Next to no one implements the full standard since it is so many pins.
Most "rs-232" implementations cheat and limit it to a the serial data connections and a few handshake lines,
and many even cheat on the voltage levels they send or expect.
The key for your needs is to know what "rs-232" pins are being used and what
voltages are used/expected.

The Arduino implements TTL asynchronous serial. While the data bit encoding is compatible with rs-232,
the voltages are not. So if you device really uses rs-232 voltage levels, you will have to map
the 5v TTL levels to the 12v rs-232 levels.
You will also have to know the async encoding parameters, i.e. baud rate, data bits, parity, stop bits, etc
to see if there are any mismatches there.

As for protocol messages, you will need to know the exact messages and responses involved
in order to do any needed translations.
In terms of data on the serial line, data is well, data. The serial line does not know
the difference between, hex, binary, ascii, etc... It is all just data bits.
Think of the data as just bits rather than ASCII, HEX, etc....
An ASCII '0' (zero) is the 8 data bits 00110000 or 0x30
A zero value is the 8 data bits 00000000 or 0x00

If one device is sending a 0x30 and the other device is expecting 0x00
then some sort of translation is needed.

Once you know what is being sent vs what is being received
the translations are not very difficult.
But the key is knowing what is being sent and expected
at both at the physical layer and protocol layer of all your
components.

--- bill

Energise 1st relay [coil], bank 1:

Serial.print (0xfe,BYTE);
Serial.print (0x6c,BYTE);
Serial.print (0x01,BYTE);

BYTE is Not "Arduino 1" supported keyword.
De-energise previously selected relay [coil] in current bank:

Serial.print (0xfe,BYTE);
Serial.print (0x00,BYTE);

BYTE is Not "Arduino 1" supported keyword.

Know anything about what baudrate (bps) it's supposed to run?

Maybe it's 9600? See "what is baud rate?" ----
http://www.relaycontrollers.com/Relay/Device/A0002

I do know its 9600 8,1,none,1

jonspeedr:
An idea possibly would be something like this?? :astonished:
http://www.radioshack.com/product/index.jsp?productId=12665270

They work...
http://forum.arduino.cc/index.php?topic=165923.msg1239161#msg1239161
...but they're definitely NOT for 120vac circuits (w/o modification & finger-crossing.)

jonspeedr:
and
Error, Electronic & Electronics Components Depot United States

Given any thought to one of the circuits in zoomkat's link (Reply#5) - if not the first one then the second?
You definitely need to do something about that.
[Does it matter if you get the Reply back from the relay board?]

Ive got an arduino uno board now... Ill just wait til the rs232 shield comes in to convert the ttl to 232. I could make what zoomkat is refering to but i dont have the parts/know how quite yet.. Meanwhile ill try to figure out what code i need to program into the uno to translate what i need.

Thanks much for yall's advice so far!

displayorder:
From the tons of comments on your articles, I guess I am not the only one having all the leisure here! [/quote

Spammers have the nicest "generic" comments!

http://forum.arduino.cc/index.php?action=profile;u=199484;sa=showPosts

Yeah they do, already reported.


Rob

I have created the code below that I thought would work to energize and de-energize my relays but i cant figure out how to make it work exactly as i want... I was wondering if someone could help me make it work right? As mentioned, I want to send values 01 thru 32 to my arduino uno board and it send hex bytes out to my relay device. The current code that i have written seems to send duplicates bytes out and does not know to combine the two characters as one. For example 01 sends þl which i believe is correct... 11 sends þl twice. Ive looked online a bit at example code and saw how i might be able to create a while loop to do this task, but i cant figure that out. :astonished:

Thanks in advance!

int val = 0;

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

void loop()
{
 val = Serial.read();
  if (-1 != val) {
  if ('1' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6c)); //108 Relay 1
     Serial.write(byte(0x01)); //01 Bank 1
   }
  if (-1 != val) {
   if ('2' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6d)); //109 Relay 2
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
    if (-1 != val) {
   if ('3' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6e)); //110 Relay 3
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('4' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6f)); //111 Relay 4
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('5' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x70)); //112 Relay 5
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('6' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x71)); //113 Relay 6
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('7' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x72)); //114 Relay 7
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('8' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x73)); //115 Relay 8
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('9' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6c)); //108 Relay 1
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('10' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6d)); //109 Relay 2
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('11' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6e)); //110 Relay 3
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('12' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6f)); //111 Relay 4
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('13' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x70)); //112 Relay 5
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('14' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x71)); //113 Relay 6
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('15' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x72)); //114 Relay 7
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('16' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x73)); //115 Relay 8
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('17' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x64)); //100 Relay 1
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('18' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x65)); //101 Relay 2
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('19' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x66)); //102 Relay 3
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('20' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x67)); //103 Relay 4
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('21' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x68)); //104 Relay 5
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('22' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x69)); //105 Relay 6
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('23' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6a)); //106 Relay 7
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('24' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6b)); //107 Relay 8
     Serial.write(byte(0x01)); //01 Bank 1
   }
  }
      if (-1 != val) {
   if ('25' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x64)); //100 Relay 1
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('26' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x65)); //101 Relay 2
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('27' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x66)); //102 Relay 3
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('28' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x67)); //103 Relay 4
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('29' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x68)); //104 Relay 5
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('30' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x69)); //105 Relay 6
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('31' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6a)); //106 Relay 7
     Serial.write(byte(0x02)); //02 Bank 2
   }
  }
      if (-1 != val) {
   if ('32' == val) {
     Serial.write(byte(0xfe)); //254
     Serial.write(byte(0x6b)); //107 Relay 8
     Serial.write(byte(0x02)); //02 Bank 2
   }
  } 
 }
}

you dont really need the byte(0xfe) with serial write just Serial.write(0xFE);

serial read only reads 1 byte at a time, and you really should use Serial.available

Firstly, use Serial.available() to tell if there is anything to read. Don't do 32 compares of the same character with -1.

Next, you can't compare two characters

if ('12' == val) {

this will not work.

Then what is the relevance of these "magic" numbers

Serial.write(byte(0x67)); //103 Relay 4

How about some #defines to make the code readable, there is no obvious relationship between 0x67, 103 and Relay 4

And what is the point of this

Serial.write(byte(0xfe)); //254

Just do

Serial.write(254);

No need to complicate things with HEX numbers and a comment.

But it seems we are at least slowly getting to the guts of what needs to be done.

There should be no need for 32 if blocks, if you can describe the relationship between the number received and the number sent all you need to do is receive the ASCII chars, convert to a number, and transmit that number.

So as I said above, what's the relationship between 0x67, 103 and Relay 4 for example. I assume there's a constant with a 4-bit field which holds the relay number, if we look at the first couple

0x6C is relay 1
0x6D is relay 2

no obvious 4-bit field for the relay number so maybe there's a magic reason that the numbers start with 108 (or maybe 107 as there is no relay 0)

So you can define something like this

#define RELAY_OFFSET 107

then use

Serial.write(byte(RELAY_OFFSET + 1)); //Relay 1

We still don't know what the offset is for but at least there's some readability to the code.

Do you always get 2 chars, or only one for values < 10? That makes a big difference to how the code would be written. Is there something that tells you the characters have been received, say a CR/LF pair or whatever. If the number of chars varies from 1 to 2 and there's no delimiting character you are in trouble.


Rob

A very simple setup showing how to send a multi character command string to turn the arduino board LED on and off.

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

int ledPin = 13;
String readString;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  Serial.println("serial on/off test 0021"); // so I can keep track
}

void loop() {

  while (Serial.available()) {
    delay(3);  
    char c = Serial.read();
    readString += c; 
  }

  if (readString.length() >0) {
    Serial.println(readString);

    if (readString == "on")     
    {
      digitalWrite(ledPin, HIGH);
    }
    if (readString == "off")
    {
      digitalWrite(ledPin, LOW);
    }

    readString="";
  } 
}