2020-04-13, 11:36 AM
In response to requests on the How Do I Thread about Seatalk1 to NMEA0183. Here's a few details of what I've done with an Arduino Mega.
My implementation is to be an interface between an ONWA plotter using NMEA V3 and a B&G autohelm using NMEA V1.5.
I will write it up more thoroughly when I've finished it.
The Onwa has an environmental screen which displays wind vector, temperature, humidity etc., So, I am providing that data too. My wind instrument is a Raymarine I60 outputting Seatalk1.
Using snippets of code from the Seatalk display code on http://berreizeta.blogspot.com/2017/02/s...nitor.html It's a relatively simple task to extract the wind speed and angle. then build NMEA sentences.
I'm currently using a rather rough and ready seatalk interface of a 4k7 resistor and a couple of diodes to clamp the input voltage to 0.6v of the arduino supply rails. The I60 output is 5 to 6 volts anyway, but, I intend improving the spike protection before using this in anger. The input feeds directly into the receive pin of Serial port1.
I'm using Nick Gammon's 9 bit serial library. NB: you do need to use no newer than V1.6.9 of the Arduino IDE for this library. And, if you already have a newer version installed, it can be a hunt to find the right location to place Nicks library!
Output to the ONWA is via Serial port2 and a MAX485 adaptor.
Output to Openplotter is via the USB Serial Port.
Code Below:
/*Seatalk 1 Input to NMEA MWV sentence output
* Requires 9 bit serial support, which only compiles correctly on Arduino IDE V1.6.9 or earlier
*/
char SeaTalkData[256] , index;
int z, inbyte , windangle;
float windspeed;
String NMEA = " ";
byte CRC=0;
void setup ()
{
Serial.begin (4800); // debugging prints
Serial1.begin (4800, SERIAL_8N1,true); // 9 bit mode. Serial port1 input connected to seatalk data out from Raymarine I60 via 4k7 resistor.
Serial2.begin(4800); //Output to NMEA Plotter via MAX485 convertor. TX/RX held High
Serial.println ("--- starting ---");
} // end of setup
void loop()
{
if (Serial1.available ()) {
inbyte = (Serial1.read());
if (inbyte & 0x100){
datagram();
index = 0 ;
}
if (index == 0) {
//Serial.println() ;
} // end 0x100
SeaTalkData[index++] = inbyte ;
} // end serial
} // end loop
void datagram(){
//-----------------------------------------------------------------
// Apparent Wind Angle (AWA): 10 01 XX YY
if (SeaTalkData[0] == 0x10){
windangle = (makeWord(SeaTalkData[2] , SeaTalkData[3]))/2;
if (windangle > 360){ windangle = 360;}
} // end 0x10
//-----------------------------------------------------------------
// Apparent Wind Speed (AWS): 11 01 XX 0Y
// (XX & 0x7F) + YY/10 = speed
// XX&0x80=0 = knots (default)
// XX&0x80=0x80 = meters/second
if (SeaTalkData[0] == 0x11){
windspeed = ((SeaTalkData[2] & 0x7F) + (float(SeaTalkData[3]) / 0x0A));
if (windspeed > 99){ windspeed = 99;}
if (windspeed < 0){ windspeed = 0;}
//-------------------------------------------------------------------
//Generate wind sentence
NMEA="XXMWV,"; //Wind angle & speed
NMEA=NMEA+ String(windangle); //wind angle 0 to 359
NMEA=NMEA+",R,"; //Relative or True
NMEA=NMEA+String(windspeed); // Wind Speed
NMEA=NMEA+",N,A"; //Units Km/Metre/kNots and Valid indicator
CalcCRC();
Serial2.println(NMEA);
Serial.println(NMEA);
} // end 0x11
}
void CalcCRC(){
//Using the NMEA string without Dollar sign and asterix
//Create a CRC by doing bitwise XOR with each character in the string.
CRC=0;
for(z=0;z<NMEA.length();z++){
CRC=CRC ^ NMEA[z];
}
NMEA="$"+NMEA; //Place Dollar at the start of string
NMEA=NMEA+"*"; //Place asterix at the end of string
if(CRC<16)NMEA=NMEA+"0"; //If CRC is less than 16 then the Hex output would be 1 charcter - Pad the 1st character with zero
NMEA=NMEA+String(CRC,HEX); //Append the CRC
}
My implementation is to be an interface between an ONWA plotter using NMEA V3 and a B&G autohelm using NMEA V1.5.
I will write it up more thoroughly when I've finished it.
The Onwa has an environmental screen which displays wind vector, temperature, humidity etc., So, I am providing that data too. My wind instrument is a Raymarine I60 outputting Seatalk1.
Using snippets of code from the Seatalk display code on http://berreizeta.blogspot.com/2017/02/s...nitor.html It's a relatively simple task to extract the wind speed and angle. then build NMEA sentences.
I'm currently using a rather rough and ready seatalk interface of a 4k7 resistor and a couple of diodes to clamp the input voltage to 0.6v of the arduino supply rails. The I60 output is 5 to 6 volts anyway, but, I intend improving the spike protection before using this in anger. The input feeds directly into the receive pin of Serial port1.
I'm using Nick Gammon's 9 bit serial library. NB: you do need to use no newer than V1.6.9 of the Arduino IDE for this library. And, if you already have a newer version installed, it can be a hunt to find the right location to place Nicks library!
Output to the ONWA is via Serial port2 and a MAX485 adaptor.
Output to Openplotter is via the USB Serial Port.
Code Below:
/*Seatalk 1 Input to NMEA MWV sentence output
* Requires 9 bit serial support, which only compiles correctly on Arduino IDE V1.6.9 or earlier
*/
char SeaTalkData[256] , index;
int z, inbyte , windangle;
float windspeed;
String NMEA = " ";
byte CRC=0;
void setup ()
{
Serial.begin (4800); // debugging prints
Serial1.begin (4800, SERIAL_8N1,true); // 9 bit mode. Serial port1 input connected to seatalk data out from Raymarine I60 via 4k7 resistor.
Serial2.begin(4800); //Output to NMEA Plotter via MAX485 convertor. TX/RX held High
Serial.println ("--- starting ---");
} // end of setup
void loop()
{
if (Serial1.available ()) {
inbyte = (Serial1.read());
if (inbyte & 0x100){
datagram();
index = 0 ;
}
if (index == 0) {
//Serial.println() ;
} // end 0x100
SeaTalkData[index++] = inbyte ;
} // end serial
} // end loop
void datagram(){
//-----------------------------------------------------------------
// Apparent Wind Angle (AWA): 10 01 XX YY
if (SeaTalkData[0] == 0x10){
windangle = (makeWord(SeaTalkData[2] , SeaTalkData[3]))/2;
if (windangle > 360){ windangle = 360;}
} // end 0x10
//-----------------------------------------------------------------
// Apparent Wind Speed (AWS): 11 01 XX 0Y
// (XX & 0x7F) + YY/10 = speed
// XX&0x80=0 = knots (default)
// XX&0x80=0x80 = meters/second
if (SeaTalkData[0] == 0x11){
windspeed = ((SeaTalkData[2] & 0x7F) + (float(SeaTalkData[3]) / 0x0A));
if (windspeed > 99){ windspeed = 99;}
if (windspeed < 0){ windspeed = 0;}
//-------------------------------------------------------------------
//Generate wind sentence
NMEA="XXMWV,"; //Wind angle & speed
NMEA=NMEA+ String(windangle); //wind angle 0 to 359
NMEA=NMEA+",R,"; //Relative or True
NMEA=NMEA+String(windspeed); // Wind Speed
NMEA=NMEA+",N,A"; //Units Km/Metre/kNots and Valid indicator
CalcCRC();
Serial2.println(NMEA);
Serial.println(NMEA);
} // end 0x11
}
void CalcCRC(){
//Using the NMEA string without Dollar sign and asterix
//Create a CRC by doing bitwise XOR with each character in the string.
CRC=0;
for(z=0;z<NMEA.length();z++){
CRC=CRC ^ NMEA[z];
}
NMEA="$"+NMEA; //Place Dollar at the start of string
NMEA=NMEA+"*"; //Place asterix at the end of string
if(CRC<16)NMEA=NMEA+"0"; //If CRC is less than 16 then the Hex output would be 1 charcter - Pad the 1st character with zero
NMEA=NMEA+String(CRC,HEX); //Append the CRC
}