Arduino NMEA0183 GPS to Paddle wheel converter for sailboat 2022

Why an Arduino NMEA0183 GPS to Paddle wheel converter?

arduino NMEA0183 GPS to Paddlewheel converter
NOT a Gemini , but a Catamaran

This project uses an Arduino and a GPS module and a TTL to RS232 converter to read data from the GPS and parse it into a VHW sentence to feed into my existing Garmin GPSMap, so it will feed into my Axiom chart plotter via MNEA2000 where it will be available to my Raymarine wind instrument. All this is simply to get true-wind because Raymarine will not accept GPS speed to calculate true wind. Well, that is not totally true because part of it is just for the sake of “doing it” and learning in the process.

Arduino NMEA0183 GPS to Paddle wheel converter. The code is somewhat convoluted as I am not a coder, but IT WORKS, GPS IN AND “WATER SPEED” OUT on the Garmin. I have determined that the Raymarine side of things will do what I expect, HOORAY IT ALL WORKS!! but Garmin and the NMEA0183 gods are satisfied. So it is up to Garmin to change it to the proper NMEA2000, N2K, signal to get it to Raymarine and for Raymarine to do it’s magic to calculate “true” wind direction. I will find out this week.

  • While it is all in the code, the kind of pseudocode is:
  • Read GPS output at 9600 baud (that is the GPS default)
  • Get rid of everything except $GNVTG sentence
  • Convert $GNVTG sentences into valid $SDVHW,0.0,T,0.0,M,0.95,N,0.0,K*7E sentence (the SD seems to be something Garmin MAY want)
  • create and add a checksum in after the conversion
  • add the carriage return and line feed (yeah, totally weird eh)
  • send it out of the Arduino as TTL (0 to +5v) at 4800 baud (4800 is what Garmin wants)
  • convert the TTL signal to RS232 (invert and change the voltage level) became NMEA0183 is not TTL, but RS232.
  • read “water speed” on Garmin.

Hardware-wise, I am using a buck regulator to take the 12 volt (nominal) boat power down to +5 volts for the cards. This can be as high as 14.7 while being charged

I currently have it running on a Nano but it was prototyped on a Uno, using a Beitian BN-220 Dual GPS Module TTL Level 9600bps + GPS Passive Antenna and a MAX3232 RS232 to TTL Serial Port Converter Module DB9 Connector.

I got the .MAX3232 RS232 to TTL Serial Port Converter Module DB9 Connector. from a Canadian guy on ebay https://www.ebay.ca/usr/phillipjfry78?_trksid=p2047675.l2559 . I didn[t need the DB9 connector but after getting a bunch of bad Max3232 chips on Amazon, I did not want to wait a month for my order from China.

I got the Nano on Amazon.ca (pack of 5 for $20 ) The UNO came from Alibaba years ago. And misc. Parts came from AliExpress.

softwareserrial.H is needed to get a separate “input” port (from the GPS) and a separate “output” (to the chart plotter). This also allows me to have a different baud rate going in and a different one going out. kind of miraculus in itself.

our Gemini Let’s look at the code for a Arduino NMEA0183 GPS to Paddle wheel converter.

crappy code by me
*good code, concepts, inspiration and ideas by:
*http://www.holdentechnology.com/2017/09/02/nmea-0183-speedometer/, https://www.sparkfun.com/tutorial/BeginningEmbedded/ATmega8-RS232.pdf
*http://picprojects.org.uk/projects/simpleSIO/SimpleRS232.pdf , https://create.arduino.cc/projecthub/hwhardsoft/how-to-use-nmea-0183-with-arduino-6e3988
*groundFungus, and a few others who deserve credit but I did not capture there names in time.

This worked on an Uno card, I will likely move it to a pro-mini (as I have some). You can copy the code just as it is but omit the [code language=”cpp”] and the [/code] at the end. I will update this as the project progresses.

Overall the idea is to see if I can replace the through hull paddle wheel with a GPS speed over ground single. And I also hope this gets my “true wind” to work on the RayMarine Axiom and wind guage. Arduino NMEA0183 GPS to Paddle wheel converter

[code language="cpp"]
/*
  parse nmea sentences from GPS and output to MNEA RS232 device. updated 5:48
  What it does. 
  reads nmea signel from a gps then strips out everythng but the VHW sentence then strips everything from that except the speed in knots, then it adds a checksum. 
  as of now I do not have it actually feeding the onboard electronics, but I have checked the sentences here >> http://freenmea.net/decoder  and the checksums all check out.
	 RX is digital pin 9 (connect to TX of other device)
   TX is digital pin 8 (connect to RX of other device)
   reads serial data to com port at 9600 and software serial port is also set at 9600
   *crappy code by me
   *good code, concepts, inspiration and ideas by:
   *http://www.holdentechnology.com/2017/09/02/nmea-0183-speedometer/,  https://www.sparkfun.com/tutorial/BeginningEmbedded/ATmega8-RS232.pdf
   *http://picprojects.org.uk/projects/simpleSIO/SimpleRS232.pdf , https://create.arduino.cc/projecthub/hwhardsoft/how-to-use-nmea-0183-with-arduino-6e3988
   *groundFungus,  and a few others who deserve credit but I did not capture there names in time. 
   *
   */
#include <SoftwareSerial.h>
String ReadString;
SoftwareSerial Serial1(9, 8); // RX, TX
char* nmeaData = "$--VHW,0.0,T,0.0,M,20.36,N,0.0,K";
int nmea0183_checksum(char* nmea_data)
{
	int crc = 0;
	int i;
	for (i = 1; i < strlen(nmea_data); i++)
	{
		crc ^= nmea_data[i];
	}
	return crc;
}                                        // =============== End nmea0183_checksum routine   
  
void setup()
{
	
	// Open HARDWARE (usb and pins 1 and 2) serial communications and wait for port to open:
	//set speed of hardware port below
	Serial.begin(4800);  // speed of HARDWARE port
	while (!Serial)
	{
		; // wait for serial port to connect. Needed for native USB port only
	}
		Serial.println("Goodnight moon!");
			// set the data rate for the SoftwareSerial port
	Serial1.begin(9600);  //dw THIS IS SOFTWARE SERIAL, pins 8tx and 9Rx 

}
void loop()
{
	
	ReadString = Serial1.readStringUntil(13);   //NMEA data ends with 'return' character, which is ascii(13)
	ReadString.trim();        // they say NMEA data starts with "$", but the Arduino doesn't think so.
	
	if (ReadString.startsWith("$GNVTG"))
	{ 
     //This section gets repeated for each delimeted bit of data by looking for the commas
	 //DW   begin routine to find next comma and remove all charactors before it. 
		int Pos = ReadString.indexOf(',');   //look for comma delimetrer
		ReadString.remove(0, Pos + 1); // Remove Pos+1 characters starting at index=0, 
	 	Pos = ReadString.indexOf(','); //looks for next comma delimetrer, which is now the first comma 
		 //DW   begin routine to find next comma and remove all charactors before it. 
		int Pos2 = ReadString.indexOf(',');   //look for comma delimetrer
		ReadString.remove(0, Pos2 + 1); // Remove Pos+1 characters starting at index=0, 
		Pos2 = ReadString.indexOf(','); //looks for next comma delimetrer, 
     	 //DW   begin routine to find next comma and remove all charactors before it. 
		int Pos3 = ReadString.indexOf(',');   //look for comma delimetrer
		ReadString.remove(0, Pos3 + 1); // Remove Pos+1 characters starting at index=0, 
		Pos3 = ReadString.indexOf(','); //looks for next comma delimetrer, which is now the first comma 
	 	 //DW   begin routine to find next comma and remove all charactors before it. 
		int Pos4 = ReadString.indexOf(',');   //look for comma delimetrer
		ReadString.remove(0, Pos4 + 1); // Remove Pos+1 characters starting at index=0, 
		Pos4 = ReadString.indexOf(','); //looks for next comma delimetrer, which is now the first comma 
	 	 //DW   begin routine to find next comma and remove all charactors before it. 
		int Pos5 = ReadString.indexOf(',');   //look for comma delimetrer
		ReadString.remove(0, Pos5 + 1); // Remove Pos+1 characters starting at index=0, 
	 	Pos5 = ReadString.indexOf(','); //looks for next comma delimetrer, which is now the first comma 

		 //DW   END routine to find next comma and remove all charactors before it.
		 // 
		// DW remove charctors after the ground speed or isolate the ground speed as a variable.
		String grdSpd;
		grdSpd = ReadString;
			int DecPos = grdSpd.indexOf('.');   //  look for the decimal point
		grdSpd.remove(4);
		
		// DW insert the GPS speed into a VHW sentence
		String VHW;
		String Stringone = "";
			//String VHW1 = "$--VHW,0.0,T,0.0,M,";
     // String VHW1 = "$VWVHW,0.0,T,0.0,M,";
     String VHW1 = "$SDVHW,0.0,T,0.0,M,";
			String VHW2 = ",N,0.0,K";
			String VHW3 = "0D 0A";  // Add carrage return and line feed in HEX)
			VHW = String(VHW1 + grdSpd + VHW2);
	// dw it is good till here,  I now have to add the checksum to the end of this
		//	Serial.print(" the String variable VHW           >");
		//	Serial.println(VHW);
		//	 Serial.println("dw it is good till here,  I now have to add the checksum to the end of this");
	// dw add the checksum in HEX  to the end of the string. first add "*" then HEX	
			  // change data type so it will work in the function.
		char vhwArray[50];  // make a char array so create array name 
		VHW.toCharArray(vhwArray, 50);
		/*
		Serial.print(" print VHW  after the array was made   >");
			Serial.println(VHW);
		// finished creating array 

	
			Serial.print("print the array  vhwArray          >");
		Serial.println(vhwArray);
		Serial.print(" print VHW  after the array was made   >");
		Serial.println(VHW);
		Serial.print("print the checksum from the fuction    >");
		Serial.println(nmea0183_checksum(vhwArray), HEX);
		*/
								
		String hexVar = String(nmea0183_checksum(vhwArray), HEX); 
		hexVar.toUpperCase();
	//	Serial.print("Create a variable for the HEX checksum and print it here     >");
	//	Serial.println(hexVar);


		//  Now combeine the string and the hex number with a "*" between them.
		String withHex = "";
	//	VHW.concat(hexVar);
	//	withHex = VHW + '*' + hexVar + " " + VHW3;  // ALSO added the carrage retrun and line feed 
	//	withHex = VHW + '*' + hexVar + '\r'+'\n';  // ALSO added the carrage retrun and line feed  '\r' '\n'
		withHex = VHW + '*' + hexVar + "<CR><LF>";  //  <CR><LF>
	//	Serial.print(" the variable one more    >");
		Serial.println(withHex);

		

		
		//---------------DW see if we can add a CRC checksum
		
							
	}  // exists before checksum routine 
}  // exists before checksum routine 

[/code]

Loading

Please share it. Thanks!