OpenMarine

Full Version: Speed-Data directly from Sensor
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi there,

I'm a total newbie to this whole think. But now - after some weeks of learning - I've made myself a OP Sailcomputer.
The whole thing sits in a watertight case, having a step up/step down converter for power and a USB-Hub for internal
connections.

Photos here:

https://drive.google.com/open?id=1_aU9Ev...0wGgJ51YPA

https://drive.google.com/open?id=1hwZKbc...vcTAaL8unw



There is a USB-Plug, a Ethernet plug and a HDMI plug at the side of the case.
Here I have Internet conection over the Ethernet, coming from a Ubiquiti Bullet M2 and a Antenne which connects to harbor wifi.
The HDMI plugs in my monitor on board and the USB-plug is used to connect via another hub the GPS, AIS and the AP.
Cirrently I'm waiting for Jean's weather sensor and his AP-controller for steering my Simrad TP22.

Besides Monitor and Keybord at the chart table, I have a 10" tablet in the cockpit under the sprayhood with a VNC-Viewer.
Also I have a small mobile in a arm pouch, on which I have the polar data, the ideal course to the appearent wind and all tactical data.
I use sailinstruments and the nke app.

One of my problems was, how to get the data from my old speed sensor into the system. The old Bidata ST30 is working with seatalk and my first idea was to use a seatalk to nmea converter. I found some code on the internet I had to alter a bit and programmed my arduino, but it was not working out.
Then, instead of buying a converter cable for 100 bucks, I thought of getting one step deeper into the system.
The speed sensor is a hall sensor.Three wires. You put voltage and ground in and recieve a signal in the same voltage on the third line whenever the little wheel in the water spins.
Luckily I found a ready to use C-scetch for the arduino that reads this signal and makes a nmea string from it:

http://www.holdentechnology.com/2017/09/...eedometer/

Easy to install on the arduino. Only thing left was the issue of the ST30 using 12V and the arduino only working with 3,3V-5,5V. So I used a selfmade voltage devider, that gets everything from 11v to 14V and devides it down by 3.

Now I have a simple Y-split in the signal cable and the data is still on the display of the Bidata ST30 and additionaly as nmea data in the OP.
Works fine when my wife is simulating the water current and spins the wheel under the boat. ;-)) Can't wait to use it in the water and calibrate it. 

Its not my invention. All credits go to Mr Mike Holden and its code. But maybe it will help anybody here with the same problem.
The problem with Seatalk is that it uses 9-bit sentences. The UART uses 8 Bits by default. I'm not an Arduino expert, but I think you can read 9-bit sentences with Arduino.
Another possibility is to use a SeaTalk to NMEA converter like this one https://www.ebay.com/itm/SEAYAK-Seatalk1...:rk:5:pf:0
or this more complete one: https://ocenav.com/en/base-stations-atm105a/, with which you can integrate all marine communication standards.

More complicated, you can read the pulses from the speed sensor directly with a GPIO from the Raspberry Pi. As the hall sensor produces, as you said, 12 Volt pulses. This voltage must first be reduced to the 3V input of the Raspberry GPIO, for example by using a voltage divider mounted as a pull down system,
[Image: pull-down-abierto.png]

although the best system is by optoisolation, for example with the 4n25 or better with the LTV817

[Image: Raspberry-Optocoupler.jpg]

That if, it will be necessary to write a program in Python to read the pulses and to turn them into speed
Hi gypsylon,

Yes, you can read seatalk 9-bit with the arduino mega. That works, but than you have to write a sketch to transform it to nmea. I have none, so you have to write your own.

You idea of reading the pulses of the speed sensor directly with the raspberry pi might work. But as you noticed, you will need optoisolation and - again - some piece of script that translates it into nmea. Here too, I have no such script and you have to develop you own.

So - the easiest way is to rrad the pulses of the speed sensor with an arduino and use the sketch of Mike Holden (see link above) to translate them to nmea.
No hassle with optoisolation and a ready to use piece of software.
For reducing the 12V of the sensor to readable 3.3-5.2V your pull down resistor should work.

If you run into any probs, just send me a pm. Should be easy to copy my running solution to your environment.....
I notice you have a Quark-Elec box there. You could potentially sell that one and purchase their AIS/GPS/SEATALK box. It's excellent. Another way if you still have a Raymarine repeater in your Seatalk bus like an ST-60, is to look for the NMEA output on them. Many of them that used the old original SEATALK had NMEA outputs. I found on my ST-60+ display output I had to write a Node-Red script to add checksum.

If all that fails, I agree with the brain-trust here: take the output from the sensor directly into an Arduino or ESP, count the pulses and determine speed and log from that. Arduinos can be made to read 9-bit data with a modified Serial module, but it also requires changing levels and ideally optical isolation.
(2018-12-25, 10:52 PM)gypsylyon Wrote: [ -> ]More complicated, you can read the pulses from the speed sensor directly with a GPIO from the Raspberry Pi. As the hall sensor produces, as you said, 12 Volt pulses. This voltage must first be reduced to the 3V input of the Raspberry GPIO, for example by using a voltage divider mounted as a pull down system,

That if, it will be necessary to write a program in Python to read the pulses and to turn them into speed

I connected the paddlewheel sensor (an old VDO sensor) directly to GPIO. But it's a little bit more of quick'n dirty hack: Instead of feeding 12V, it works well even with 5V which I forked off the Pi power supply.
No opto-isolation, but just a voltage division with 1kO-resistance to get 3.3V on pin 24

and then a simple phython script to transform the pulses into NMEA-sentences, which are fed to kplex with a FIFO:


Code:
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)

path = "/var/run/nmea.fifo"
os.mkfifo(path)

fifo = open(path, "w")
fifo.write('$VWVHW,,,,,0,00,N,,K\r\n')
fifo.close()

impulse_count = 0
NUM_CYCLES = 100
Counter = 100
while 1:
   start = time.time()
   for impulse_count in range(NUM_CYCLES):
       GPIO.wait_for_edge(24, GPIO.FALLING)
   duration = time.time() - start

   Counter = Counter + 100
   distance = Counter / 27368
   distancer = round(distance,2)
   speed = 7.6 / duration
   speedr = round(speed,2)
   nmea = '$VWVHW,,,,,' + str(speedr) + ',N,,K\r\n$VWVLW,,N,' + str(distancer) + ',N\r\n'

   fifo = open(path, "w")
   fifo.write(str(nmea))
   fifo.close()

   time.sleep(0.5)

GPIO.cleanup()


The values are experimental, I found it very hard to get documentation on how many pulses the sensor should give for 1 nautical mile.

This worked nicely during our summer cruise last summer, even though it can surely be made better.

Fair winds
Christian
Very nice! My old Raymarine paddlewheel is calibrated by doing measured distance calibration runs in opposite directions.

This might be something that could be added to your script to get more accuracy.
(2019-01-20, 11:08 AM)CVL Wrote: [ -> ]
(2018-12-25, 10:52 PM)gypsylyon Wrote: [ -> ]More complicated, you can read the pulses from the speed sensor directly with a GPIO from the Raspberry Pi. As the hall sensor produces, as you said, 12 Volt pulses. This voltage must first be reduced to the 3V input of the Raspberry GPIO, for example by using a voltage divider mounted as a pull down system,

That if, it will be necessary to write a program in Python to read the pulses and to turn them into speed

I connected the paddlewheel sensor (an old VDO sensor) directly to GPIO. But it's a little bit more of quick'n dirty hack: Instead of feeding 12V, it works well even with 5V which I forked off the Pi power supply.
No opto-isolation, but just a voltage division with 1kO-resistance to get 3.3V on pin 24

and then a simple phython script to transform the pulses into NMEA-sentences, which are fed to kplex with a FIFO:


Code:
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)

path = "/var/run/nmea.fifo"
os.mkfifo(path)

fifo = open(path, "w")
fifo.write('$VWVHW,,,,,0,00,N,,K\r\n')
fifo.close()

impulse_count = 0
NUM_CYCLES = 100
Counter = 100
while 1:
   start = time.time()
   for impulse_count in range(NUM_CYCLES):
       GPIO.wait_for_edge(24, GPIO.FALLING)
   duration = time.time() - start

   Counter = Counter + 100
   distance = Counter / 27368
   distancer = round(distance,2)
   speed = 7.6 / duration
   speedr = round(speed,2)
   nmea = '$VWVHW,,,,,' + str(speedr) + ',N,,K\r\n$VWVLW,,N,' + str(distancer) + ',N\r\n'

   fifo = open(path, "w")
   fifo.write(str(nmea))
   fifo.close()

   time.sleep(0.5)

GPIO.cleanup()


The values are experimental, I found it very hard to get documentation on how many pulses the sensor should give for 1 nautical mile.

This worked nicely during our summer cruise last summer, even though it can surely be made better.

Fair winds
Christian
The fifo function creates a temporary file where it writes data for another program to read.  I don't know, does kplex work with fifo.
OP works with the "socket" and "pynmea2" libraries, with which you can send data to localhost, which will then be available for all devices connected to Raspi.

Here I put you the script that reads the pulses every 10 seconds and transforms them into nautical miles and kilometers per hour.
With "pinimea2" it transforms to NMEA VHW sentence, and with "sock.sendto(vhw2, ('localhost', 10110))" it is sent to localhost.

"Frequency" are the pulses in 1 seconds from the speed sensor for a nautical knot.  To calculate it you need to know the number of pulses per NM and divides by 3600.
Although normally it also gives you the frequency.

For example, Airmar's s300/st300 transducer, which uses raymarine for the ST50 and St60, has 4 different encapsulations. The P371 with fins gives 17,000 pulses per nautical mile and has a frequency of 4.8 Hz. The P371 without fins 19,000 pulses/NM or 5.3Hz (for cruising sailboats and planing powerboats).
The P398 with fins gives 14.400 pulses/MN or 4.0 Hz. The P398 without fins 17,000 pulses/NM or 4.8Hz(for racing sailboats and high-speed powerboats).

If you don't know which one is yours it's a test-drive with different frequencies

#!/usr/bin/env python2.7

 
import RPi.GPIO as GPIO
import sys
import time
import os
import socket, pynmea2

try:
    from configparser import ConfigParser
except ImportError:
    from ConfigParser import ConfigParser  # ver. < 3.0


sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

start = time.time()
GPIO.setmode(GPIO.BCM)
 
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
 
contador = 0
frequency = 4.5
delay = 10
nm = 0
km = 0
def my_callback(channel):
    global contador
    contador = contador +1
    import time
    import sys
    sys.stdout.write('%d' % contador)
    sys.stdout.flush()
    i=1
    while i<=len(str(contador)):
        sys.stdout.write('\b')
        i = i+1;
 
GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback)
while  1:
    start = time.time()
    time.sleep(delay)  # Pausa de segundo segundos
    nm = contador / (frequency * delay)

    km = nm * 1.852

    contador = 0
    end = time.time()
    time_elapsed = end - start
    time_in_min =  time_elapsed / 60
    vhw = pynmea2.VHW('VW', 'VHW', ('', 'T','' , 'M', str(round(nm,1)),'N',str(round(km,1)),'K'))
    vhw1=str(vhw)
    vhw2=vhw1+"\r\n"
    sock.sendto(vhw2, ('localhost', 10110))

    print vhw2
    print '                 tiempo transcurrido:\t{} s'.format(time_elapsed)
    print '                 tiempo transcurrido:\t{} min'.format(time_in_min)
    print nm
GPIO.cleanup()



The "prints" are for checking the operation of the program. You can remove them and let the program run in background

If you also want to read the water temperature, you have to do it by the converter AD MCP3008. Openplotter recognizes this converter. In the OP SPI window you can adjust the parameters and assign the corresponding signalK sentence.

You'll notice, the course data is empty. If you want to set the course data to complete the VHW statement, you can read it from the VTG statement with the following script.
This I wrote it, to do the opposite, to send pulses to the display Tridata of the ST50, taking the speed of GPS of the sentence VTG.

# Name: lectura_NMEA_B.py

#!/usr/bin/env python


import socket, pynmea2
import RPi.GPIO as IO
import time

IO.setmode(IO.BCM)
IO.setwarnings(False)


pin = 17
frequency = 4.8
IO.setup(pin, IO.OUT)
p = IO.PWM(pin, frequency)



def ReadVTG():
    frase_nmea = ''
    velo = ''
    nm = 0
    try:
        frase_nmea = sock_in.recv(1024)
    except socket.error, error_msg:
        try:
            print 'Failed to connect with localhost:10110.'
            print 'Error: '+ str(error_msg[0])
            sys.stdout.flush()
        except: pass
    
    else:
        if frase_nmea:
            try:
                nmea_list=frase_nmea.split()
                for i in nmea_list:
                    msg = pynmea2.parse(i)
                    nmea_type=msg.sentence_type
                    if nmea_type == 'RMC':  
                        velo = str(msg)
                        nm = float(velo[46:-15])
                        
            except: pass
            
    return nm

try:
    sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock_in.settimeout(10)
    sock_in.connect(('127.0.0.1', 10110))
except socket.error, error_msg:
    print 'Failed to connect with localhost:10110.'
    print 'Error: '+ str(error_msg[0])
else:
    nm = 0
        while True:
        nm = ReadVTG()
        
        print nm
        f = frequency * nm
        print f
        if f < 0.5:
            f = 0.5
        print f
        p.ChangeFrequency(f)
        p.start (10)
        time.sleep (2)       


To adapt the 3.3 V pulse output of the Raspi to the 12V, a circuit with two resistors and a transistor, such as this one, must be mounted.
   
[Image: IMG-20190127-232136-BURST001-COVER.jpg]