(2019-01-20, 11:08 AM)CVL Wrote: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.(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
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.