This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Mapping SOG to Speed Thru Water
#1
Can somebody point me in the right direction for trying to map SOG (GPS speed) to VHW (speed thru water/paddlewheel)?  I'd like to get my instruments to display an estimated true wind.  I know it won't be perfect if there's a current running.  Would that be a node-red thing, a signalk thing, or something else?

Thanks,
Jason
Reply
#2
Bringing this old, unanswered, thread back to life.

I have a new-to-me boat, and I've determined that the paddlewheel wiring is broken, and maybe the paddlewheel sensor itself is broken.  For my Raymarine ST60+ instruments, the broken wire is turning the Tridata display into a repeater, and the Wind display doesn't show True Wind, only Apparent (as it needs STW).

I have recently networked all of my NMEA2000 instruments to/from SeaTalk, as well as WiFi to Openplotter.  Because my Garmin chartplotter has sea temp in the depth transducer, the ST60+ Tridata is now showing ("repeating") sea temperature from the Garmin device.  But Water Speed and True Wind isn't working because Raymarine needs STW and it doesn't care about SOG.

Until I get new wiring and/or paddlewheel, I'd like to "copy" my SOG/VTG into a VHW Speed Through Water.  In doing so, I hope that the now-repeater-display will at least show SOG instead of 0.00, and that the Wind display will show True Wind, even if not completely accurate due to SOG vs. STW.  It looks like VTG and VHW have identical structure, other than SOG vs. STW.  It is also key that I be able to send this out on the TCP connection on WLAN1/192.168.1.2 which is connected to my WiFi NMEA multiplexer, and not just WLAN9 which is the openplotter.local (10.10.10.1).  In doing so, it will be put onto the SeaTalk network.

I don't know how to do this.  I'm guessing I'll need Node-Red to accomplish this.  But I'm Node Red illiterate.  I wouldn't know how to even start.  Can anyone help?
Reply
#3
I was able to not very gracefully generate navigation.seppedThroughWater in Signal K with the plugin "mulitple-sow-sources" and setting both sources to Navigation.speedOverGround. Now, how do I convert that to a VHW and put that out on port 1456 on wlan1/192.168.1.2?
Reply
#4
Activate VHW in signalk to nmea0183 plugin and the data will be available over tcp on your server’s port 10110.

You’ll have to be more specific than ”put that out…”. Tcp? Udp? Is the address the source or the target?
Reply
#5
(2023-02-27, 10:12 PM)tkurki Wrote: Activate VHW in signalk to nmea0183 plugin and the data will be available over tcp on your server’s port 10110.
That's fine for OpenCPN running on the Pi (localhost:10110), but it doesn't put the VHW back out onto the boat's NMEA network/multiplexer.

(2023-02-27, 10:12 PM)tkurki Wrote: You’ll have to be more specific than ”put that out…”. Tcp? Udp? Is the address the source or the target?
I have two WiFi connections on the Pi.  There's the wlan9 (10.10.10.1 or localhost) which is an access point.  The network in question is on wlan1 (192.168.1.x), where the Pi is a CLIENT, connecting to my YachtDevices YDNR-02 NMEA multiplexer which is the access point.  This is the source of all of my NMEA2000/NMEA0183/SeaTalk1 data.  That data is available on port 1456, a TCP connection.  The YachtDevices server is 192.168.1.1, and the Pi has a DHCP assigned address, usually 192.168.1.2.  I want to send the VHW sentence out on the wlan1 connection, on port 1456, so that the other devices on the NMEA/ST1 network can receive it.

I see in the data connection for my YachtDevices, there's a Output Events section, which is currently blank.  I changed that to nmea0183out, and everything that is checked in the Plugin Config > Convert Signal K to NMEA0183 section is now going out on that connect.  Yay, my Raymarine instruments are now reporting a speed on the TriData (although it's SOG, not STW), and the wind instrument display is now showing a TWS/TWD, although based on SOG.

Thanks for the nudge in the right direction.
Reply
#6
That solution was not working well / repeatable.  Also, the mulitple-sow-sources plugin would send out a ton of deltas.

Instead, I was able to cobble together my first Node-Red flow and thought I would share in case it may be of use to others.  Maybe not for the exact same purpose, but this example shows how to combine several Signal K messages into one new NMEA0183 sentence.  In this case, I combined magneticVariation (from GPS), headingMagnetic (from autopilot), and speedOverGround (from GPS) and form the VHW sentence (headingTrue, headingMagnetic, speedThroughWater).  I did not make a new Signal K delta for this, but instead just send the NMEA0183 formatted sentence, along with the nmea0183out event.  This would make this sentence available both to OpenCPN (via the local port 10110 connection) as well as my data connection to the multiplexer, which in turn sent it on the Raymarine SeaTalk1 network, such that my Tridata now reads SOG and Wind display can calculate TWS/TWA.

Code:
[{"id":"01c84fd2a95aa7a6","type":"tab","label":"SOG -> STW","disabled":false,"info":"This flow copies SOG into STW with the VHW sentence.\n\nMy paddlewheel that measures Speed through\nwater is currently broken, leaving the\nRaymarine Tridata display without Speed and\nthe Wind display without True Wind.\nAn (incorrect) approximation of using GPS\nSOG as STW has now brought life back into those\ndisplays, at least until I can get the paddlewheel\nfixed.\n\nThis flow uses headingMagnetic (from autopilot),\nalong with magneticVariation and speedOverGround\nfrom the GPS, and forms a full VHW NMEA0183\nsentence (headingTrue, headingMagnetic, speedThroughWater)\nand then sends this NMEA0183 sentence.  It does\nnot populate the Signal K key with speedThroughWater,\nalthough it could be added.  I just needed STW\ninto OpenCPN (local, port 10110) and also sent\nout my NMEA data connection to the multilexer\nsuch that the SeaTalk instruments could see \nthe data.","env":[]},{"id":"ad2b0fe6d3916011","type":"signalk-subscribe","z":"01c84fd2a95aa7a6","name":"navigation.speedOverGround","mode":"sendAll","flatten":true,"context":"vessels.self","path":"navigation.speedOverGround","source":"","period":"500","x":140,"y":160,"wires":[["9b78262d4f212efc"]]},{"id":"7a08028bb1ba9354","type":"signalk-subscribe","z":"01c84fd2a95aa7a6","name":"navigation.headingMagnetic","mode":"sendAll","flatten":true,"context":"vessels.self","path":"navigation.headingMagnetic","source":"WLN10.YD","period":"500","x":140,"y":100,"wires":[["9b78262d4f212efc"]]},{"id":"12ea71b9c4081683","type":"function","z":"01c84fd2a95aa7a6","name":"VHW","func":"var maghead,truehead,sent;\nvar sog,sogn,sogk;\nvar checksum = 0;\nmaghead = msg.payload[\"navigation.headingMagnetic\"]\ntruehead = (maghead + msg.payload[\"navigation.magneticVariation\"]) * (180.0 / 3.141592653589793238463);\nmaghead = maghead * (180.0 / 3.141592653589793238463);\nsog = msg.payload[\"navigation.speedOverGround\"];\nsogn = sog * 1.94384449;    // to knots\nsogk = sog * 3.6;           // to km/hr\nsent = \"IIVHW,\"+truehead.toFixed(1)+\",T,\" + maghead.toFixed(1) + \",M,\" + sogn.toFixed(2) + \",N,\" + sogk.toFixed(2) +\",K\";\n\nfor (var i=0;i<sent.length;i++){\n    checksum = checksum ^ sent.charCodeAt(i);\n}\nchecksum = Number(checksum).toString(16).toUpperCase();\nmsg.payload = \"$\" + sent + \"*\" + checksum;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":210,"y":280,"wires":[["2bca9df90dcad788","e481a40b7cc184ea","9cf369789481f61e","ad7c5f35bc01f6c9"]]},{"id":"9b78262d4f212efc","type":"join","z":"01c84fd2a95aa7a6","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":350,"y":100,"wires":[["12ea71b9c4081683"]]},{"id":"917934523f2b0340","type":"signalk-subscribe","z":"01c84fd2a95aa7a6","name":"navigation.magneticVariation","mode":"sendAll","flatten":true,"context":"vessels.self","path":"navigation.magneticVariation","source":"","period":"500","x":140,"y":40,"wires":[["9b78262d4f212efc"]]},{"id":"b20c985349adeffb","type":"signalk-send-nmea0183","z":"01c84fd2a95aa7a6","name":"","nmea0183Event":"nmea0183out","x":570,"y":360,"wires":[]},{"id":"2bca9df90dcad788","type":"delay","z":"01c84fd2a95aa7a6","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"2","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":370,"y":360,"wires":[["b20c985349adeffb"]]},{"id":"e481a40b7cc184ea","type":"debug","z":"01c84fd2a95aa7a6","d":true,"name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":180,"wires":[]},{"id":"9cf369789481f61e","type":"tcp out","z":"01c84fd2a95aa7a6","d":true,"name":"","host":"","port":"1456","beserver":"server","base64":false,"end":false,"tls":"","x":560,"y":240,"wires":[]},{"id":"ad7c5f35bc01f6c9","type":"tcp out","z":"01c84fd2a95aa7a6","d":true,"name":"","host":"","port":"10110","beserver":"server","base64":false,"end":false,"tls":"","x":580,"y":300,"wires":[]}]
Reply
#7
(2023-03-01, 11:11 PM)we9v Wrote: That solution was not working well / repeatable.  Also, the mulitple-sow-sources plugin would send out a ton of deltas.

Instead, I was able to cobble together my first Node-Red flow and thought I would share in case it may be of use to others.  Maybe not for the exact same purpose, but this example shows how to combine several Signal K messages into one new NMEA0183 sentence.  In this case, I combined magneticVariation (from GPS), headingMagnetic (from autopilot), and speedOverGround (from GPS) and form the VHW sentence (headingTrue, headingMagnetic, speedThroughWater).  I did not make a new Signal K delta for this, but instead just send the NMEA0183 formatted sentence, along with the nmea0183out event.  This would make this sentence available both to OpenCPN (via the local port 10110 connection) as well as my data connection to the multiplexer, which in turn sent it on the Raymarine SeaTalk1 network, such that my Tridata now reads SOG and Wind display can calculate TWS/TWA.

Code:
[{"id":"01c84fd2a95aa7a6","type":"tab","label":"SOG -> STW","disabled":false,"info":"This flow copies SOG into STW with the VHW sentence.\n\nMy paddlewheel that measures Speed through\nwater is currently broken, leaving the\nRaymarine Tridata display without Speed and\nthe Wind display without True Wind.\nAn (incorrect) approximation of using GPS\nSOG as STW has now brought life back into those\ndisplays, at least until I can get the paddlewheel\nfixed.\n\nThis flow uses headingMagnetic (from autopilot),\nalong with magneticVariation and speedOverGround\nfrom the GPS, and forms a full VHW NMEA0183\nsentence (headingTrue, headingMagnetic, speedThroughWater)\nand then sends this NMEA0183 sentence.  It does\nnot populate the Signal K key with speedThroughWater,\nalthough it could be added.  I just needed STW\ninto OpenCPN (local, port 10110) and also sent\nout my NMEA data connection to the multilexer\nsuch that the SeaTalk instruments could see \nthe data.","env":[]},{"id":"ad2b0fe6d3916011","type":"signalk-subscribe","z":"01c84fd2a95aa7a6","name":"navigation.speedOverGround","mode":"sendAll","flatten":true,"context":"vessels.self","path":"navigation.speedOverGround","source":"","period":"500","x":140,"y":160,"wires":[["9b78262d4f212efc"]]},{"id":"7a08028bb1ba9354","type":"signalk-subscribe","z":"01c84fd2a95aa7a6","name":"navigation.headingMagnetic","mode":"sendAll","flatten":true,"context":"vessels.self","path":"navigation.headingMagnetic","source":"WLN10.YD","period":"500","x":140,"y":100,"wires":[["9b78262d4f212efc"]]},{"id":"12ea71b9c4081683","type":"function","z":"01c84fd2a95aa7a6","name":"VHW","func":"var maghead,truehead,sent;\nvar sog,sogn,sogk;\nvar checksum = 0;\nmaghead = msg.payload[\"navigation.headingMagnetic\"]\ntruehead = (maghead + msg.payload[\"navigation.magneticVariation\"]) * (180.0 / 3.141592653589793238463);\nmaghead = maghead * (180.0 / 3.141592653589793238463);\nsog = msg.payload[\"navigation.speedOverGround\"];\nsogn = sog * 1.94384449;    // to knots\nsogk = sog * 3.6;           // to km/hr\nsent = \"IIVHW,\"+truehead.toFixed(1)+\",T,\" + maghead.toFixed(1) + \",M,\" + sogn.toFixed(2) + \",N,\" + sogk.toFixed(2) +\",K\";\n\nfor (var i=0;i<sent.length;i++){\n    checksum = checksum ^ sent.charCodeAt(i);\n}\nchecksum = Number(checksum).toString(16).toUpperCase();\nmsg.payload = \"$\" + sent + \"*\" + checksum;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":210,"y":280,"wires":[["2bca9df90dcad788","e481a40b7cc184ea","9cf369789481f61e","ad7c5f35bc01f6c9"]]},{"id":"9b78262d4f212efc","type":"join","z":"01c84fd2a95aa7a6","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":350,"y":100,"wires":[["12ea71b9c4081683"]]},{"id":"917934523f2b0340","type":"signalk-subscribe","z":"01c84fd2a95aa7a6","name":"navigation.magneticVariation","mode":"sendAll","flatten":true,"context":"vessels.self","path":"navigation.magneticVariation","source":"","period":"500","x":140,"y":40,"wires":[["9b78262d4f212efc"]]},{"id":"b20c985349adeffb","type":"signalk-send-nmea0183","z":"01c84fd2a95aa7a6","name":"","nmea0183Event":"nmea0183out","x":570,"y":360,"wires":[]},{"id":"2bca9df90dcad788","type":"delay","z":"01c84fd2a95aa7a6","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"2","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":370,"y":360,"wires":[["b20c985349adeffb"]]},{"id":"e481a40b7cc184ea","type":"debug","z":"01c84fd2a95aa7a6","d":true,"name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":180,"wires":[]},{"id":"9cf369789481f61e","type":"tcp out","z":"01c84fd2a95aa7a6","d":true,"name":"","host":"","port":"1456","beserver":"server","base64":false,"end":false,"tls":"","x":560,"y":240,"wires":[]},{"id":"ad7c5f35bc01f6c9","type":"tcp out","z":"01c84fd2a95aa7a6","d":true,"name":"","host":"","port":"10110","beserver":"server","base64":false,"end":false,"tls":"","x":580,"y":300,"wires":[]}]

Chad,

Another solution is to add the derived data plugin and then add a custom calculation.  you basically can make a text file that takes the SOG and outputs a STW.  The code is very simple and there is already a TWS, TWA calculator that you could just copy, rename and then remap the 'navigation.speedThroughWater' to 'navigation.speedOverGround' or just use the same format and just map  'navigation.speedOverGround' to 'navigation.speedThroughWater'.  Once you have the new file, put it in the calc directory and the plugin comes with a config screen in SignalK to turn on what ever calc you want to enable.  Here is the TWS, TWA calc code:

Code:
module.exports = function (app) {
  return {
    group: 'wind',
    optionKey: 'trueWind',
    title:
      'True Wind Angle, Direction and Speed (based on speed through water, AWA, AWS, headingTrue)',
    derivedFrom: [
      'navigation.headingTrue',
      'navigation.speedThroughWater',
      'environment.wind.speedApparent',
      'environment.wind.angleApparent'
    ],
    calculator: function (headTrue, speed, aws, awa) {
      var apparentX = Math.cos(awa) * aws
      var apparentY = Math.sin(awa) * aws
      var angle = Math.atan2(apparentY, -speed + apparentX)
      var speed = Math.sqrt(
        Math.pow(apparentY, 2) + Math.pow(-speed + apparentX, 2)
      )

      var dir = headTrue + angle

      if (dir > Math.PI * 2) {
        dir = dir - Math.PI * 2
      } else if (dir < 0) {
        dir = dir + Math.PI * 2
      }

      return [
        { path: 'environment.wind.directionTrue', value: dir },
        { path: 'environment.wind.angleTrueWater', value: angle },
        { path: 'environment.wind.speedTrue', value: speed }
      ]
    }
  }
}
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)