Advanced Serial Communications Problem

Hi all.

I've been playing around with some digital servos. The problem I'm having arises because they dont use a standard serial configuration. Best I can find, they use 19200 baud, with 8 bit packets, 2 stop bits and the line voltages inverted. Also, for return data it pulls down on a 'blank' byte (=0x00), to return data.

I have written a program which currently at least sends correctly formatted commands to the servo over serial and an inverting circuit. The servo also responds correctly to these commands. The returns however are garbled. Also, if I connect pin 0 to pin 1 the serial read data is also garbled. The problem therefore appears to be in the initilisation of the Serial connection.

First off, can anyone see what I've done wrong and how to fix it? Secondly, does anyone know how to invert the output from the serial port on a software side?

The current code :-

    /* DEFINITIONS */
#define FOSC 16777216                           // Clock Speed
#define BAUD 19200                              // Serial Communication Speed
#define MYUBRR FOSC/16/BAUD-1                   // Time per Bit

    /* PROTOTYPES */
void CustomSerial(long ubrr);                    // Initialises the Serial Protocals on TX and RX with 2 stop, 8 bits
void dataSet(byte data1,byte data2,byte data3); // Sets Serial data to be written
void dataWrite(void);                           // Writes current data to the Servo via serial

void setup()
{
  CustomSerial(MYUBRR);
}

 byte data[7];

void loop()
{
  // Servo ID set to 0x01
dataSet(0xE9,0x01,0x01);    //Sets Speed to min
dataWrite();

dataSet(0x01,0x03,0x03);    // Moves Servo to position 1
dataWrite();

delay(20000);            // Waits for servo to reposition, V.slow on min speed

dataSet(0xE9,0x01,0xFF);  // Sets Servo to max speed
dataWrite();
dataSet(0x01,0x06,0x06);  // Moves servo to position 2
dataWrite();
delay(1000);

}

void CustomSerial(long ubrr)
{
  UBRR0H = (unsigned char) (ubrr>>8);
  UBRR0L = (unsigned char)(ubrr);
  //UCSR0B = (1<<RXEN0) | (1<<TXEN0);
  UCSR0B = 0x98; // Value to allow both RX and TX with servo
  UCSR0C = (1<<USBS0) | (3<<UCSZ00);
}


void dataSet(byte data1,byte data2,byte data3)
{
  data[0]=0x80; // Command
  data[1]=data1; // Command type
  data[2]=data2; // Data 1
  data[3]=data3; // Data 2
  data[4]=256-((data[0]+data[1]+data[2]+data[3])%256); // Checksum
  data[5]=0x00; // Return 1
  data[6]=0x00; // Return 2
}

void dataWrite(void)
{
  Serial.write(data[0]);
  Serial.write(data[1]);
  Serial.write(data[2]);
  Serial.write(data[3]);
  Serial.write(data[4]);
  Serial.flush();
  Serial.write(data[5]);
  data[5]=Serial.read();
  Serial.flush();
  Serial.write(data[6]);
  data[6]=Serial.read();
}

A shameless bump, but this has trned into a real sticking point in my program. Any ideas/advice would be greatfully received.

Thanks,
Cynar

Hi

When you say that you connect pin 0 to pin 1 I presume that you mean you are connecting the RxD and TxD pins together. This will only work if you can correctly run in half-duplex. i.e. only one side transmits, then stops and listens whilst the other side transmits - otherwise you are both trying to transmit down the same wire at the same time, so it will get garbled.

As far as I know, there is no way to configure the on chip UART to invert the polarity of the signal. Your only options therefore are (1) use an external hardware inverter, or (2) bit bash the serial data by turning the pin on and off with the correct timings. This can be done, but is not straightforward, and may only be viable at relatively low baud rates.

I hope this is of some help.

I had a feeling it couldnt invert the data. Looks like hardware option is the best one for that. transmission speed needs to be 19200, with built in reading as well. A bit to high for bit bashing.

Annoyingly, the servo I'm using pulls down the TX signal, rather than making it's own, so i need to transmit a byte to receive the return. This means I've no option other than use full duplex.

So all I need to do now is persuade the board to talk to it's self. It seems to do this fine in normal serial mode, just not in my customised mode :-S.

Thanks for the assistance so far though.

Cynar

P.S
Just to clarify, I'm only using 1 arduino chipset, i need to get it so that what does out on the TX pin goes through a resistor is read on the RX pin. The servo pulls down on the RX pin to transmit (hence the resistor.

+-----------Transistor---RX (pin 0)
Servo ----|
+----3.3K--Transistor---TX (pin 1)

The transistors invert the voltage passing through them.