How to set SoftwareSerial 8E1---HELP!!!

hello!

i want to use the SofwareSerial port to communicate with a device via a RS232.

I found how I can set the start/stop/parity etc. for the normal hardware Serialport (Serial.begin(38400, SERIAL_8E1)).

But how I can change my setting for the SoftwareSerial port.

Seetings I need are:

baudrate 38400
1 start bit
8 bit of data, lsb first
1 parity bit
even parity
1 stop bit

Thanks a lot for helping!!!

To get a SoftwareSerial variant, that does 8E1, you need to change the class' recv and write methods:

// The receive routine called by the interrupt handler
//
void SoftwareSerial8e1::recv()
{

#if GCC_VERSION < 40302
// Work-around for avr-gcc 4.3.0 OSX version bug
// Preserve the registers that the compiler misses
// (courtesy of Arduino forum user *etracer*)
  asm volatile(
    "push r18 \n\t"
    "push r19 \n\t"
    "push r20 \n\t"
    "push r21 \n\t"
    "push r22 \n\t"
    "push r23 \n\t"
    "push r26 \n\t"
    "push r27 \n\t"
    ::);
#endif  

  uint8_t d = 0;

  // If RX line is high, then we don't see any start bit
  // so interrupt is probably not for us
  if (_inverse_logic ? rx_pin_read() : !rx_pin_read())
  {
    // Wait approximately 1/2 of a bit width to "center" the sample
    tunedDelay(_rx_delay_centering);
    DebugPulse(_DEBUG_PIN2, 1);

    // Read each of the 8 bits
    for (uint8_t i=0x1; i; i <<= 1)
    {
      tunedDelay(_rx_delay_intrabit);
      DebugPulse(_DEBUG_PIN2, 1);
      uint8_t noti = ~i;
      if (rx_pin_read())
        d |= i;
      else // else clause added to ensure function timing is ~balanced
        d &= noti;
    }
    // skip the parity bit
    tunedDelay(_rx_delay_stopbit);
    DebugPulse(_DEBUG_PIN2, 1);

    // skip the stop bit
    tunedDelay(_rx_delay_stopbit);
    DebugPulse(_DEBUG_PIN2, 1);

    if (_inverse_logic)
      d = ~d;

    // if buffer full, set the overflow flag and return
    if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) 
    {
      // save new data in buffer: tail points to where byte goes
      _receive_buffer[_receive_buffer_tail] = d; // save new byte
      _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
    } 
    else 
    {
#if _DEBUG // for scope: pulse pin as overflow indictator
      DebugPulse(_DEBUG_PIN1, 1);
#endif
      _buffer_overflow = true;
    }
  }

#if GCC_VERSION < 40302
// Work-around for avr-gcc 4.3.0 OSX version bug
// Restore the registers that the compiler misses
  asm volatile(
    "pop r27 \n\t"
    "pop r26 \n\t"
    "pop r23 \n\t"
    "pop r22 \n\t"
    "pop r21 \n\t"
    "pop r20 \n\t"
    "pop r19 \n\t"
    "pop r18 \n\t"
    ::);
#endif
}

size_t SoftwareSerial8e1::write(uint8_t b)
{
  if (_tx_delay == 0) {
    setWriteError();
    return 0;
  }

  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);
  uint8_t p = 0;
  uint8_t t;
  for (t = 0x80; t; t >>= 1)
    if (b & t) p++;
  

  // 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);
    }
    // parity
    if (!(p & 0x01))
      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);
    }
    // parity
    if (!(p & 0x01))
      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;
}

baudrate 38400
1 start bit
8 bit of data, lsb first
1 parity bit
even parity
1 stop bit

38400 is probably too fast for the SoftwareSerial class but if you have a very tolerant device on the other side you might have success. I would change to the hardware serial in any case.

thanks!!!

38400 is probably too fast for the SoftwareSerial class but if you have a very tolerant device on the other side you might have success. I would change to the hardware serial in any case.

but if i'm using the hardware seril, how can I still see what's going on at my monitor?

but if i'm using the hardware seril, how can I still see what's going on at my monitor?

Use a Leonardo (USB serial is separate) or Mega2560 (3 additional hardware serial interfaces). Or use SoftwareSerial for debugging, although this might give you problems, depending on your application. In some cases you can use LEDs to show some states, an LCD to show debugging messages, there are a lot of possibilities. As you haven't told us what your project is about, it's almost impossible to give you more detailed advise.

I want to communicate with an Inverter (Xtender) via a RS232 interface... I'm using a Serial Adapter with a MAX232 on it....

just tried to use the hardware Serial port and LED's for debugging....

but after uploading this code:

//try to receive data via hardware serial  port
int led_xtender_available = 13;
int led_xtender_not_available = 7;
//Request line 26bytes, Hexadecimal
byte Request[] = {0xAA,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x0A,0x00,0x6F,0x71,0x00,0x01,0x01,0x00,0xB8,0x0B,0x00,0x00,0x01,0x00,0xC5,0x90};
int incomingByte = 0;  

void setup()  
{

  // Open serial communications and wait for port to open:
  // Set USART_Configurations: 38400bps, 1start bit, 8bit of data
  // 1 parity bit, even parity, 1 stop bit
  Serial.begin(38400,SERIAL_8E1);
  
  pinMode (led_xtender_available, OUTPUT);
  pinMode (led_xtender_not_available, OUTPUT);
}

void loop(){
  
  //sending the Request to the xtender
  for (int i=0; i<sizeof(Request); i++)
  {
  Serial.write(Request[i]);
  //Serial.println(Request[i]);
  //delay(500);
  
  //proof via LED Blinking, if Xtender is available
  }
  if(Serial.available()>0){
    digitalWrite(led_xtender_available, HIGH);
    incomingByte = Serial.read();
  }else{
    digitalWrite(led_xtender_not_available, HIGH);
    
  }
  
}

I got this Error: avrdude: stk500_getsync(): not in sync: resp=0x00
any idea what the reason for this error is?

I got this Error: avrdude: stk500_getsync(): not in sync: resp=0x00
any idea what the reason for this error is?

Disconnect the RS232 hardware while uploading because the upload uses the same hardware (the serial interface).

THANKS, now the error doesn't uccurence anymore!

But I still have a problem receiving any data from my device:

I want to send a Request with 26 Bytes to the Xtender, and then I should get a Response (number of Bytes 30) in HEX like this:
Request: AA 00 01 00 00 00 65 00 00 00 0A 00 6F 71 00 01 00 B8 0B 00 00 01 00 C5 90
Response: AA 23 65 00 00 00 01 00 00 00 0E 00 96 8A 02 01 01 00 B8 0B 00 00 01 00 00 00 3B 42 44 78

How can I store all the Bytes from my Response in an array?
And the moment I'm still getting an error (invalid conversion byte to char). But I want to get the Response in hex.

The code I'm using is:

//try to receive data via hardware serial  port
int led_xtender_available = 4;
int led_xtender_not_available = 13;
//Request line 26bytes, Hexadecimal
byte Request[] = {0xAA,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x0A,0x00,0x6F,0x71,0x00,0x01,0x01,0x00,0xB8,0x0B,0x00,0x00,0x01,0x00,0xC5,0x90};
//Response should have 30bytes
byte Response [30];  

void setup()  
{

  // Open serial communications
  // Set USART_Configurations: 38400bps, 1start bit, 8bit of data
  // 1 parity bit, even parity, 1 stop bit
  Serial.begin(38400,SERIAL_8E1);
  
  pinMode (led_xtender_available, OUTPUT);
  pinMode (led_xtender_not_available, OUTPUT);
}

void loop(){
  
  //sending the Request to the xtender
  for (int i=0; i<sizeof(Request); i++)
  {
  Serial.write(Request[i]);
  //Serial.println(Request[i]);
  //delay(500);
  
  //proof via LED Blinking, if Xtender is available
  }
  if(Serial.available()>=30){
    digitalWrite(led_xtender_available, HIGH);
    Serial.read(Response, 30);
  }else{
    digitalWrite(led_xtender_not_available, HIGH);
    
  }
  
}

But also If I don't try storing all bytes of the response in one Array, I'm not getting an Response... Does anybody knows why?

The encoding of the Arduino is in little endian, right?

I want to send a Request with 26 Bytes to the Xtender, and then I should get a Response (number of Bytes 30) in HEX like this:
Request: AA 00 01 00 00 00 65 00 00 00 0A 00 6F 71 00 01 00 B8 0B 00 00 01 00 C5 90
Response: AA 23 65 00 00 00 01 00 00 00 0E 00 96 8A 02 01 01 00 B8 0B 00 00 01 00 00 00 3B 42 44 78

Do you have a link to that device? I have some doubts that you really have to send this in hex.

How can I store all the Bytes from my Response in an array?

Sure you can.

byte resp[30];
if (Serial.available() >= 30) {
  uint8_t i;
  for (i = 0; i < 30; i++) {
    resp[i] = Serial.read();
  }

And the moment I'm still getting an error (invalid conversion byte to char). But I want to get the Response in hex.

And you think we are not interested in seeing this error? Don't you think that keeping this error message secret doesn't help you much?

But also If I don't try storing all bytes of the response in one Array, I'm not getting an Response... Does anybody knows why?

What does that mean? Post both sketches, the one where you get a response and the one where you don't.

The encoding of the Arduino is in little endian, right?

That's absolutely irrelevant here but as far as I remember it is.

the device I want to communicate with is an xtender via a Xcom-232i:
http://studer-innotec.com/?n_ulang=en&cat=sine_wave_inverter-chargers&id=432
http://www.studer-innotec.com/?n_ulang=en&cat=sine_wave_inverter-chargers&id=432&aId=1418&tab=4

I attached the serial protocol of the xtender to that post

The encoding of the Arduino is in little endian, right?

That's absolutely irrelevant here but as far as I remember it is.

I thought maybe the device get's the byte-order of the request wrong.... that's why I was asking. Or maybe I can't receive any data, because of the USART configuration: 8bit of data- LSB first?

my actual code is now:

//try to receive data via hardware serial  port
int led_xtender_available = 4;
int led_xtender_not_available = 13;
//Request line 26bytes, Hexadecimal
byte Request[26] = {0xAA,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x0A,0x00,0x6F,0x71,0x00,0x01,0x01,0x00,0xB8,0x0B,0x00,0x00,0x01,0x00,0xC5,0x90};
//Response should have 30bytes
byte Response [30];  

void setup()  
{

  // Open serial communications
  // Set USART_Configurations: 38400bps, 1start bit, 8bit of data
  // 1 parity bit, even parity, 1 stop bit
  Serial.begin(38400,SERIAL_8E1);
  
  pinMode (led_xtender_available, OUTPUT);
  pinMode (led_xtender_not_available, OUTPUT);
}

void loop(){
  
  //sending the Request to the xtender
  for (int i=0; i<sizeof(Request); i++)
  {
  Serial.write(Request[i]);
  //Serial.println(Request[i]);
  }
  delay(2000);
  //proof via LED Blinking, if Xtender is available
  if(Serial.available()>=30){
    digitalWrite(led_xtender_available, HIGH);
  //write response in an array  
  for (int n=0; n<30; n++){
       Response [n] = Serial.read();
  }  
  
  }else{
    
  digitalWrite(led_xtender_not_available, HIGH);
    
  }
  
}

I checked with an oszilloskop: I'm sending data to the device, but I'm not getting any response....

Technical specification - Xtender serial protocol - V1.5.16.pdf (1.5 MB)

I thought maybe the device get's the byte-order of the request wrong.... that's why I was asking. Or maybe I can't receive any data, because of the USART configuration: 8bit of data- LSB first?

Little endian is the byte order not the bit order. Asynchronous serial communication is in almost any case LSB, I doubt that this device is different in this regard. BTW, section 3.1 of the manual specifies that it uses LSB.

That device uses a real RS232, what hardware do you use to physically translate the signals (Arduino: 0/5V, RS232: -(3-15)V/+(3-15)V)?
What's your wiring?

I'm using this Serial Adapter with a MAX232 on it:
http://www.exp-tech.de/Shields/Schnittstelle/Serial-Adapter-RS232-TTL-3-5-5V.html?XTCsid=c94fcabf9a652b7813983b111e22a5bd

My wiring is:
(left Serial Adapter, right Arduino UNO)
TX --> RX
RX--->TX
GND ---> GND
VCC ---> 5V

As this device is made to connect your PC to some peripheral, RX/TX might be labeled wrongly. Can you check with a multimeter (on the disconnected adapter) to which pin of the MAX232 chip the TTL-side TX pin is connected? Don't swap the connections for the moment, just check that with a multimeter.

Can you check with a multimeter (on the disconnected adapter) to which pin of the MAX232 chip the TTL-side TX pin is connected?

I'm not sure how to do this... what do I have to messure?

I am also using a mini gender changer, cause my device and the serial adapter both have male connectors:
http://www.conrad.de/ce/de/product/986369/Seriell-Adapter-1x-D-SUB-Stecker-9pol-1x-D-SUB-Stecker-9pol-0-m-Gelb?ref=searchDetail

I'm not sure how to do this... what do I have to messure?

Every multimeter I know has a circuit tester function, the beeper, I don't know what you call it. If you hold both testers against each other a sound is played. Check all pins of the chip on the module if it has a connection to the TX pin.

I am also using a mini gender changer, cause my device and the serial adapter both have male connectors:
http://www.conrad.de/ce/de/product/986369/Seriell-Adapter-1x-D-SUB-Stecker-9pol-1x-D-SUB-Stecker-9pol-0-m-Gelb?ref=searchDetail

In this case do the same for sub-D connector (after the gender changer). Although I would expect that the gender changer just changes the gender, that's not clearly defined and the link doesn't offer a datasheet where this could have been stated.

We have the pinout for all the other components so you have to find out the missing one.

ok thanks!!

I just messured the the gender changer. all pins are connected to each other, means 1--->1, 2--->2 etc.

By messuring TX, I just got one "piep" at the left side 4th top pin, by messuring RX, I got the "piep" at the left side 3th top pin of the MAX3232 (with left side I mean the left side of the MAX3232 if I can read the letters at the Adapter, means the sub- D connector is on the left side). At all other pins I didn't get a piep.

then I messured the MAX and the sub- D connector:
Pin 7 Connector ---> 1st top Pin right side MAX
pin 8 Connector ----> 2nd top Pin right side MAX
pin 3 Connector ----> 4th down Pin left side MAX
pin 2 Connector ----> 3th down Pin left side MAX
pin 5Connector ----> 2nd down Pin left side MAX

I made a handwritten note of it:

the adapter uses a max3232C from Texas Instruments, so if I'm looking at the datasheet(http://www.ti.com/lit/ds/symlink/max3232.pdf), it seems to me, as if the serial adapater is not the problem, why I can't receive any data...right?

If I got everything correctly, you need a null-modem cable on the RS232 side (DB-9 to DB-9). The adapter you use is thought to be connected to a PC as a device (like a modem) and the Xtender has exactly the same connector scheme.

that's why I'm using the gender changer

No, you need a null-modem cable that swaps the RX/TX lines.

thought I have to swap the lines between adapter and microcontroller? Or do I also have to do this?