Go Down

Topic: Asynchronous SeaTalk (Read 39628 times) previous topic - next topic


Thanks Nick, I did see what you wrote and I am intrigued.  I will build the seatalk to rs232 level shifter hardware as soon as I get a moment and start playing around but... let me see if I have this right...  On the UNO you would be talking about pins 1 and 2 labelled rx/tx which also serve as  hardware serial ports.  You describe how to turn on and off the ninth bite (where  did those commands come from?) .... but how do (and here I fearlessly reveal my profound ignorance) the nine bits turn into an acsi character?   



Actually labelled 0 (Rx) and 1 (Tx).

How do you turn 9 bits into ASCII? Well ASCII is normally 8 bits, so I suppose you mean "how do I get or send the 9th bit?".

The datasheet has examples (I've adapted them a bit):


Code: [Select]
void USART_Transmit (unsigned int data)
  /* Wait for empty transmit buffer */
  while ( !(UCSR0A & _BV (UDRE0)))
     { }
  UCSR0B &= ~_BV (TXB80);  // clear 9th bit
  if (data & 0x0100)     // if 9th bit in "data" set, set 9th bit
    UCSR0B |= _BV (TXB80); 

  UDR0 = data;  // put remaining 8 bits in, and send it


Code: [Select]
unsigned int USART_Receive ()
  byte status, resh, resl;
  /* Wait for data to be received */
  while ( !(UCSR0A & _BV (RXC0)) )
    { }
  /* Get status and 9th bit, then data */
  /* from buffer */
  status = UCSR0A;
  resh = UCSR0B;
  resl = UDR0;
  /* If error, return -1 */
  if ( status & _BV(FE0) | _BV (DOR0) | _BV (UPE0) )
    return -1;
  /* Filter the 9th bit, then return */ 
  resh = (resh >> 1) & 0x01;
  return (resh << 8) | resl;

Now in both cases the 9th bit is in the 9th bit of the unsigned int that you are sending/receiving.

For the receiving part at least you might need to get into the HardwareSerial library to achieve this. But this is fairly simple.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


I 've ordered an arduino mega 2560 --  $38.50 +/- at Mouser.  My plan is to migrate  Wallenwein's code to it and work directly with the port.  mega 2560 has more designated ports and I think I can do it without involving SoftwareSerial.  I really don't know what I'm doing but i didn't the last time i got into something like this and eventually prevailed.  When I get it running I'll try to back it down to an UNO.  I don't know that it can't be done with an UNO, but the Mega seems to my ignorant view to be a closer sister to the atmega32.  

idea of building an autopilot is a good one.  I'm running our marine trader 36 sedan on a Cetrek with which I'm delighted, but it's an orphan and I need a back up plan.  

best regards.  john


A quick browse of HardwareSerial indicates you probably need to make a custom version for 9 bits. For one thing the internal buffer is only 8-bit characters so there is no room for the 9th bit in the incoming data stream.

So you probably need to increase the buffer to unsigned int (from unsigned char) and then build in the above code to get that 9th bit, if indeed 9 bits are being used.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


this is what we're trying to contend with:

SeaTalk Seria:

11 bits are transmitted for each character:
1  Start bit (0V)
8  Data Bits (least significant bit transmitted first)
1  Command bit, set on the first character of each datagram. Reflected in the parity bit of most UARTs. Not compatible with NMEA0183 but well suited for the multiprocessor communications mode of 8051-family microcontrollers (bit SM2 in SCON set).
1  Stop bit (+12V)
Composition of Messages

Each datagram contains between 3 and 18 characters:
Type of command (the only byte with the command-bit set)
Attribute Character, specifying the total length of the datagram in the least significant nibble:

      Most  significant 4 bits: 0 or part of a data value
      Least significant 4 bits: Number of additional data bytes = n  =>
      Total length of datagram = 3 + n  characters
First, mandatory data byte
- 18.  optional, additional data bytes "

Directly quoted from Thomas Knauth's informative blog on this problem. Read here: http://www.thomasknauf.de/rap/seatalk1.htm#Ser


Do you only want to send command bits, or receive them as well?

If you only want to send them, what I suggested on the first page should work:

Set up:

Code: [Select]
UCSR0B = 0;  // turn off
UCSR0B = 0b10011100;  // turn on again in 9-bit mode

This converts the UART to work in 9 bit mode.

Then if you want to send something with the command bit set you can do this:

Code: [Select]
  UCSR0B = 0b10011101;  // turn 9th bit on
  Serial.print ("a");
  UCSR0B = 0b10011100;  // turn 9th bit off again

Be warned that this simple approach will only work with pre 1.0 Arduino, because the version 1.0 onwards buffers output.

I've been working on adapting the library to work more generally with 9 bits, if you need to use 1.0 of the IDE.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


I've modified the HardwareSerial code to handle 9 bits:


This is for the 1.0 version of the IDE only. Also it hasn't been through any "peer review" yet, so I can't guarantee it is really stable. If you are going to try it I suggest saving the old versions of HardwareSerial, just in case.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


It is very good of you to contribute this fix.  I am interested only in receiving seatalk and converting it short to sentences to display on an LCD .  There is a hardware interface to be added as well as running the product of the hardware mod through a max232 to reduce levels to ttl suitable to the arduino.

Sometimes it is surprising to find that there are people around the world with similar pursuits. I've found no-one among the boat people I know with any interest in this sort of thing so I'm delighted at your's.

It will take me some time to work my way through some of the ancillary issues with this conversion before I can get to your code, but be assured that I will and thank you.

best regards,  john


Nick,  wow!   That is amazing, I can hardly wait to try it (I have to purchase some parts to make the level shifter so it will take a while).   One question .... Will the hardware serial still be able to read 8 bits?   I am running ver 1.0 on a rev 3 UNO but won't the 9 bit mod screw up communication via the USB which also uses the hardware serial?   In any case, your efforts are greatly appreciated.


It's an optional flag (at this stage). I tested by outputting in the "usual way" via USB to my computer. So yes, you only have to use 9 bits if you want to. In my case I did not use 9 bits for Serial, but only Serial1 and Serial2.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


Feb 12, 2012, 02:28 pm Last Edit: Feb 12, 2012, 05:22 pm by jferg Reason: 1
My take on Nick's excellent code is that it will require a mega, which has three serial ports.  It might be possible to read incoming SeaTalk and send output on same port - I do that with my PolarView navigation notebook setup where the nmea stuff comes in on the RX pin on Com1, is read by the navigation software, and the direction to the autopilot goes out on the TX pin on com1. This has worked for me for many years.

My grasp of Wallenwein's code was that it, too, requires more than one hardware serial port and so i ordered a Mega 2560, which  should show up on thursday.  I've now built the hardware board which contains a gps module, a compass w/tilt compensation (yet to be calibrated), the incoming signal modification for the SeaTalk signals, and the max232 to convert the SeaTalk signal levels to ttl for connection to the Arduino.

so I think we can make this work on Unos but with the inconvenience of having to fool with the progrsamming via the USB port, then disconnecting the USB connection and running with the connection to the serial port.

I know I don't know much, so don't hesitate to straighten this out if i've misconstrued something.


i should add to above that i have no need to write SeaTalk, and that I have assumed that i will use SoftwareSerial to read the GPS module.  the compass operates on the U2C bus.  likely, i will concoct my code on the Mega and then when it does what i want, move it to an Uno and read Seatalk on pin 0 and write everything out on pin 1.  obviously no handshaking, but at 4800 bps, do you need it?

and come to think about it, since I'm going to be writing to an LCD, i don't need the serial output at all except while I'm concocting code.


I modified Nick's sketch on the other thread to run on a UNO sending and receiving on same port and it works fine. see below:

Code: [Select]
  //modified Nick's code to run on a single UNO serial
//port, ferguson 2/12/12

void setup ()
  Serial.begin (4800, true);  // debugging prints
//  Serial1.begin (115200, true);  // 9 bit mode
//  Serial2.begin (115200, true);  // 9 bit mode
  Serial.println ("--- starting ---");
}  // end of setup

int i;

void loop ()

  Serial.write9bit (i++);  // send another byte
  // display incoming on Serial2 -changed to Serial jasf
  if (Serial.available ())
    Serial.println ((int) Serial.read (), HEX);
  // check if we have sent all possible characters noter:changed
  // to Serial jaf
  if (i >= 0x200)
    delay (100);
    while (Serial.available ())
      Serial.println ((int) Serial.read (), HEX);
    delay (5000);
    i = 0;
    }  // end of sent 512 bytes
}  // end of loop

now on to make it work with actual SeaTalk.


Feb 12, 2012, 03:50 pm Last Edit: Feb 12, 2012, 04:42 pm by jferg Reason: 1
Add a delay(10000) ; at the beginning of setup otherwise it will be hard to reprogram Uno on Linux - Windows ok.


Feb 12, 2012, 06:23 pm Last Edit: Feb 12, 2012, 06:26 pm by DavidFoe Reason: 1

This whole interaction is amazing.  Thanks for checking that Nick's mods work on the single UNO serial port -- it gives me great hope for my system-upgrade.  I am seriously thinking about going to a mega because I am using nearly every digital pin on the UNO to monitor buttons, to talk to/listen to serial LCD, Serial NMEA compass, and to talk to the motor controller for my actuator.    I read somewhere that there are difficulties when using the interupt pins on UNO while softwareserial is running (something about turning off interupts to preserve timing) and so I have avoided using interupts.    Whether or not this is true, having the extra hardware serial pins would be good for my application.   Right now my autopilot is working (actuator responds to heading changes and I can set the course with a button) but the human interface (buttons) and the IR remote, while they work, are clunky and need to be tarted-up.  Once this is done, I'll be working on the wind direction and boat speed mods (reading ST) and writing to a ST monitor (writing ST) so  I look forward to hearing about your success in reading Seatalk using Nick's hardware serial mods.



Go Up