[SOLVED] Serial Data Coming Through Garbled

*Edit - I've found the problem. Doing logic level analysis it turns out the baud rate of the prolific converter was about 9259, not 9600. The signals from the FTDI were reversed from that of the prolific and the ZigBee. (FTDI High Logic Level was 0, while Prolific High Logic Level was 1).

I've searched the internet for the cause of this problem and the best I've been able to find is "check the baud rate". I've already tried that, always using 8N1, but just can't find the source of this problem.

I'm using an Arduino board, programmed as a Modbus slave device, and a ZigBee to rs232 converter from SHJ electronics. I was attempting to connect the Arduino Modbus slave to the ZigBee to rs232 converter. They failed to communicate, and I found the following results by doing further testing.

The Arduino board functions perfectly as a modbus slave when connected to the pc via an ftdi board, however for some reason cannot be programmed by the ftdi board, producing errors. I had to resort to isp programming.

The arduino board produces garbled data when connected to the pc with a prolific usb to serial converter

The Zigbee to serial converter produces garbled data with both prolific and ftdi usb to serial converters, except when in configuration mode.

When the prolific and ftdi usb to serial converters are connected to each other, converting from usb - serial - usb, with 2 com ports open on my maching, the data between them is garbled.

I've checked the baud rate, it changes how the data is garbled, but doesn't fix the problem.

What could be causing this?

techn1cian:
What could be causing this?

Who would ever know? One reason why they probably won't is that your code is apparently a State Secret.

A couple of guesses are that

there is a mismatch of baud rate in the system somewhere
you are using software serial on hardware serial pins.
you are using software serial at a speed beyond its abilities 38400
wrong bluetooth protocol

Nick_Pyner:

you are using software serial at a speed beyond its abilities 38400

I'm using baud 9600

Nick_Pyner:
Who would ever know? One reason why they probably won't is that your code is apparently a State Secret.

A couple of guesses are that

there is a mismatch of baud rate in the system somewhere
you are using software serial on hardware serial pins.
you are using software serial at a speed beyond its abilities 38400
wrong bluetooth protocol

There must be a mismatch in the baud rate somewhere right?

I'm using baud 9600, so surely that won't exceed any limitations?

I'll look further into software serial on hardware serial pins, I don't know much about that so there might be something there.

I'll do some research

#include "crc.h"


void dbug(String db_msg)
{
  Serial.println(db_msg);
}

void dbug(byte db_byte)
{
  Serial.println(db_byte, DEC);
}

void dbug(unsigned db_value)
{
  Serial.println(db_value, DEC);
}

int convert_string_unsigned(String input)
{
  int output = 0;
  int index = 0;
  if(input[index]) output += input[index++] - 48;
  while(input[index])
  {
    output = output * 10;
    output += input[index] - 48;
    index++;
  }
  return output;
}

int csv_parse_unsigned(String input, int& index)
{
    String value = "";

    while(input[index])
    {
        if(input[index] < 48 || input[index] > 57)
        {
            index++;
            break;
        }
        value += input[index];
        index++;
    }

  return convert_string_unsigned(value);
}



const byte modbus_func_read = 3;
const byte modbus_func_write = 6;

const unsigned rx_buffer_len = 8;
const unsigned tx_buffer_len = 250;


unsigned long rx_time;
char rx_char;
String rx_ascii = "";         // a String to hold incoming data
unsigned rx_buffer_idx = 0;
byte rx_buffer[rx_buffer_len];

unsigned tx_buffer_idx = 0;
byte tx_buffer[tx_buffer_len];


byte modbus_mode = 0; // 0 for rtu, 1 for ascii
byte modbus_address = 254;
bool relay_output = 0;
unsigned io_analog[8];


void modbus_read_addr(unsigned addr, unsigned count, byte target[], const unsigned &target_len, unsigned &target_idx)
{
  if(!count) return; // if 0 addresses
  count--;



  // address 0, modbus mode
  if(addr == 0)
  {
    target[target_idx++] = 0;
    target[target_idx++] = modbus_mode;
    if(!count) return;
    count--, addr++;
  }

  // address 1, modbus address
  if(addr == 1)
  {
    target[target_idx++] = 0;
    target[target_idx++] = modbus_address;
    if(!count) return;
    count--, addr++;
  }

  if(addr == 2)
  {
    target[target_idx++] = 0;
    target[target_idx++] = relay_output;
    if(!count) return;
    count--, addr++;
  }



  // reserved addresses
  while(addr < 100)
  {
    target[target_idx++] = 0;
    target[target_idx++] = 0;
    if(!count) return;
    count--, addr++;
  }
  


  if(addr == 100)
  {
    io_analog[0] = analogRead(A0);
    target[target_idx++] = io_analog[0] >> 8;
    target[target_idx++] = io_analog[0] & 0xff;
    if(!count) return;
    count--, addr++;
  }
  if(addr == 101)
  {
    io_analog[1] = analogRead(A1);
    target[target_idx++] = io_analog[1] >> 8;
    target[target_idx++] = io_analog[1] & 0xff;
    if(!count) return;
    count--, addr++;
  }
  if(addr == 102)
  {
    io_analog[2] = analogRead(A2);
    target[target_idx++] = io_analog[2] >> 8;
    target[target_idx++] = io_analog[2] & 0xff;
    if(!count) return;
    count--, addr++;
  }
  if(addr == 103)
  {
    io_analog[3] = analogRead(A3);
    target[target_idx++] = io_analog[3] >> 8;
    target[target_idx++] = io_analog[3] & 0xff;
    if(!count) return;
    count--, addr++;
  }
  if(addr == 104)
  {
    io_analog[4] = analogRead(A4);
    target[target_idx++] = io_analog[4] >> 8;
    target[target_idx++] = io_analog[4] & 0xff;
    if(!count) return;
    count--, addr++;
  }
  if(addr == 105)
  {
    io_analog[5] = analogRead(A5);
    target[target_idx++] = io_analog[5] >> 8;
    target[target_idx++] = io_analog[5] & 0xff;
    if(!count) return;
    count--, addr++;
  }


  

  // write null addresses
  for(;;)
  {
    target[target_idx++] = 0;
    target[target_idx++] = 0;
    if(!count) return;
    count--;
  }
}


void modbus_read()
{
  unsigned start_address = rx_buffer[3] + (rx_buffer[2] << 8);
  unsigned reg_to_read = rx_buffer[5] + (rx_buffer[4] << 8);

  
  tx_buffer[tx_buffer_idx++] = modbus_address;
  tx_buffer[tx_buffer_idx++] = modbus_func_read;
  tx_buffer[tx_buffer_idx++] = reg_to_read * 2;

  modbus_read_addr(start_address, reg_to_read, tx_buffer, tx_buffer_len, tx_buffer_idx);

  unsigned crc = CRC16(tx_buffer, tx_buffer_idx);
  tx_buffer[tx_buffer_idx++] = crc >> 8;
  tx_buffer[tx_buffer_idx++] = crc & 0xff;



  //
  // binary response
  //
  Serial.write(tx_buffer, tx_buffer_idx);

  // wait for transmission to complete then clean up
  Serial.flush();
  tx_buffer_idx = 0;
}


void modbus_write()
{
  unsigned write_address = rx_buffer[3] + (rx_buffer[2] << 8);
  unsigned data_to_write = rx_buffer[5] + (rx_buffer[4] << 8);

  switch(write_address)
  {
    case 0:
    modbus_mode = data_to_write;
    break;

    case 1:
    modbus_address = data_to_write;
    break;

    case 2:
    relay_output = data_to_write;
    digitalWrite(6, relay_output);
    break;

    default:
    return;
  }

  for(int i=0; i<rx_buffer_idx; i++)
  {
    tx_buffer[tx_buffer_idx++] = rx_buffer[i];
  }

  //
  // binary response
  //
  Serial.write(tx_buffer, tx_buffer_idx);

  // wait for transmission to complete then clean up
  Serial.flush();
  tx_buffer_idx = 0;
}


void modbus_request()
{
  if(rx_buffer[0] != modbus_address) return;
  if(rx_buffer[1] == modbus_func_read) return modbus_read();
  if(rx_buffer[1] == modbus_func_write) return modbus_write();
}

void setup()
{
  // put your setup code here, to run once:
  // initialize serial:
  Serial.begin(9600);

  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);
  pinMode(A5, INPUT);

  pinMode(6, OUTPUT);

  // reserve 200 bytes for the rx_ascii:
  rx_ascii.reserve(200);
}


void loop()
{

  // if receiving serial data, check to see if the transmission has ended by means of idle rx channel
  if(rx_buffer_idx)
  {
    if(millis() - rx_time >= 20) onSerialRxEnd();
  }
}

inline void onSerialRxEnd()
{
  if(rx_buffer_idx >= 8) modbus_request();

  // clear the string:
  rx_ascii = "";
  rx_buffer_idx = 0;
}

void serialEvent()
{
  while (Serial.available())
  {
    rx_char = Serial.read();
    
    if(rx_buffer_idx < rx_buffer_len) rx_buffer[rx_buffer_idx] = rx_char;
    rx_ascii += rx_char;

    rx_buffer_idx++;
  }

  rx_time = millis();
}

What is sending the data? Where is your PROOF that the data is garbled? Why do you have so freaking much code that has nothing to do with serial data reception when you have a basic problem with serial data reception?

Serial Input Basics - simple reliable ways to receive data.

...R

PaulS:
What is sending the data? Where is your PROOF that the data is garbled? Why do you have so freaking much code that has nothing to do with serial data reception when you have a basic problem with serial data reception?

The zigbee unit sends modbus data to my Arduino, which then sends a reply back to the zigbee unit.

However they failed to work together, and in testing I connected a ftdi USB to serial converter to a prolific one, sent data between them, and what came out wasn't what I put in. I suspect that's where my problem starts.