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
SeaTalk 1 to NMEA0183/2000 with Raspberry Pi
#22
Thank you very much Cari20!

I didn't know about the signalk-autopilot plugin, this saves a lot of time.
What I started doing was creating a NodeRed dashboard with buttons, which when pressed would trigger Marco Bergman's script.
This is what I had so far:
Code:
[{"id":"69638511.9f0fdc","type":"tab","label":"seatalk tiller pilot remote","disabled":false,"info":""},{"id":"cbb1ef69.90424","type":"ui_button","z":"69638511.9f0fdc","name":"","group":"966da9df.2c4648","order":0,"width":0,"height":0,"passthru":true,"label":"AUTO","tooltip":"Enable autopilot","color":"","bgcolor":"","icon":"","payload":"2","payloadType":"num","topic":"","x":470,"y":340,"wires":[["3f72a40.aac515c"]]},{"id":"3f72a40.aac515c","type":"python-function","z":"69638511.9f0fdc","name":"write seatalk","func":"#!/usr/bin/env python\n\nimport RPi.GPIO as GPIO\nimport time\nimport serial\nimport os\n\n# ST2000 remote control with Raspberry Pi 2\n# Marco Bergman 2019\n#\n#   +5V    (01) ---------------------+\n#                                    |\n#                                   +++\n#               2 x NPN             | |\n#               2 x 10k             | |\n#                                   +++       c------o SEATALK\n#                                    |     | /\n#                              c-----+----b|<\n#                   +---+   | /            | \\\n#   GPIO14 (08) ----+   +--b|<                e\n#                   +---+   | \\               |\n#                              e              |\n#                              |              |\n#   GND    (03) ---------------+--------------+\n\n# GPIO constants: connect switches to ground on these GPIO pins\n#AU = 24    # Auto       GPIO 24 (pin# 18) BROWN\n#M1 = 22    # Minus 1    GPIO 22 (pin# 15) ORANGE\n#M10 = 27   # Minus 10   GPIO 27 (pin# 13) GREEN\n#P10 = 17   # Plus 10    GPIO 17 (pin# 11) BLUE\n#P1 = 18    # Plus 1     GPIO 18 (pin# 12) YELLOW\n#SB = 23    # Standby    GPIO 23 (pin# 16) WHITE\nBUZZER = 25 # Buzzer    GPIO 25 (pin# 22) WHITE\n\nnode.log(\"test\")\n\nMODE_NORMAL = 1\nMODE_STEER_INTO_WIND = 2\n\ndef write_seatalk (xx, yy):\n# thanks to http://www.thomasknauf.de/seatalk.htm\n        with serial.Serial() as ser:\n                ser.baudrate = 4800\n                ser.port = '/dev/serial0'\n                ser.stopbits=serial.STOPBITS_ONE\n                ser.bytesize=serial.EIGHTBITS\n\n                ser.open()\n                ser.parity = serial.PARITY_MARK\n                ser.write(b'\\x86')\n                ser.parity = serial.PARITY_SPACE\n                ser.write(b'\\x11' + chr(int(xx, 16)) + chr(int(yy, 16)))\n                ser.close()\n                \n                \nangle = 0\nprevious_angle = 0\n\ndef send_command(command):\n        global angle\n        print \"command=\"+str(command)\n\n        if command == -10:\n                write_seatalk(\"06\", \"F9\")\n        if command == -1:\n                write_seatalk(\"05\", \"FA\")\n        if command == +1:\n                write_seatalk(\"07\", \"F8\")\n        if command == +10:\n                write_seatalk(\"08\", \"F7\")\n        angle = angle - command\n\n\ndef steer_to_angle(angle_to_steer_to):\n        global angle\n        angle = angle_to_steer_to\n\n        while angle != 0:\n                if angle <= -10:\n                        send_command(-10)\n                if angle > -10 and angle < 0:\n                        send_command(-1)\n                if angle > 0 and angle < 10:\n                        send_command(+1)\n                if angle >= 10:\n                        send_command(+10)\n\ndef steer_into_wind():\n        global previous_angle\n\n        try:\n                with open('/tmp/AWA', 'r') as myfile:\n                        line = myfile.read().replace(\"\\n\", \"\")\n                        awa = int(line)\n        except:\n                awa = 0\n\n        angle=(awa+180) % 360-180\n        previous_angle = angle\n        node.log(\"awa=\" + str(awa) + \"; angle=\" + str(angle))\n\n        steer_to_angle(angle)\n\n\ndef steer_previous_angle():\n        global previous_angle\n\n        steer_to_angle(-previous_angle)\n        \nGPIO.setmode(GPIO.BCM)\n#GPIO.setup(SB, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Stand By:   1\n#GPIO.setup(AU, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Auto:       2\n#GPIO.setup(P1, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # +1:         4\n#GPIO.setup(P10, GPIO.IN, pull_up_down=GPIO.PUD_UP) # +10:        8\n#GPIO.setup(M10, GPIO.IN, pull_up_down=GPIO.PUD_UP) # -10:       16\n#GPIO.setup(M1, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # -1:        32\nGPIO.setup(BUZZER, GPIO.OUT)        \n\n        \ndef beep(b):\n        if ( b == 1 ):\n                GPIO.output(BUZZER, 1)\n                time.sleep(0.1)\n                GPIO.output(BUZZER, 0)\n        if ( b == 2 ):\n                GPIO.output(BUZZER, 1)\n                time.sleep(0.2)\n                GPIO.output(BUZZER, 0)\n        if ( b == 3 ):\n                beep(1)\n                time.sleep(0.1)\n                beep(1)\n\n\nbeep(3)\n\nmode=MODE_NORMAL\n\nwhile 1:\n\n\tkey=msg['payload']\n\n\t# Stand by\n\tif (key == 1):\n\t\t\tnode.log(\"Stand by (\" + str(key) + \")\")\n\t\t\tbeep(2)\n\t\t\twrite_seatalk(\"02\", \"FD\")\n\t\t\tmode = MODE_NORMAL\n\t# Auto\n\tif (key == 2 and mode == MODE_NORMAL):\n\t\t\tnode.log(\"Auto (\" + str(key) + \")\")\n\t\t\tbeep(1)\n\t\t\twrite_seatalk(\"01\", \"FE\")\n\t# Auto steer back\n\tif (key == 2 and mode == MODE_STEER_INTO_WIND):\n\t\t\tnode.log(\"Steer previous wind angle\")\n\t\t\tbeep(3)\n\t\t\tsteer_previous_angle()\n\t\t\tmode = MODE_NORMAL\n\n\t# +1\n\tif (key == 4):\n\t\t\tnode.log(\"+1 (\" + str(key) + \")\")\n\t\t\tbeep(1)\n\t\t\twrite_seatalk(\"07\", \"F8\")\n\t# +10\n\tif (key == 8):\n\t\t\tnode.log(\"+10 (\" + str(key) + \")\")\n\t\t\tbeep(2)\n\t\t\twrite_seatalk(\"08\", \"F7\")\n\t# -10\n\tif (key == 16):\n\t\t\tnode.log(\"-10 (\" + str(key) + \")\")\n\t\t\tbeep(2)\n\t\t\twrite_seatalk(\"06\", \"F9\")\n\t# -1\n\tif (key == 32):\n\t\t\tnode.log(\"-1 (\" + str(key) + \")\")\n\t\t\tbeep(1)\n\t\t\twrite_seatalk(\"05\", \"FA\")\n\n\t# Track -10 & +10\n\tif (key == 24):\n\t\t\tnode.log(\"Track (\" + str(key) + \")\")\n\t\t\tbeep(3)\n\t\t\twrite_seatalk(\"28\", \"D7\")\n\t# Tack Port -1 & -10\n\tif (key == 48):\n\t\t\tnode.log(\"Tack Port (\" + str(key) + \")\")\n\t\t\tbeep(3)\n\t\t\twrite_seatalk(\"21\", \"DE\")\n\t# Tack Starboard +1 & +10\n\tif (key == 12):\n\t\t\tnode.log(\"Tack Starboard (\" + str(key) + \")\")\n\t\t\tbeep(3)\n\t\t\twrite_seatalk(\"22\", \"DD\")\n\t# Toggle auto seastate +1 & -1\n\tif (key == 36):\n\t\t\tnode.log(\"Toggle auto seastate (\" + str(key) + \")\")\n\t\t\tbeep(3)\n\t\t\twrite_seatalk(\"20\", \"DF\")\n\n\tif (key == 3 and mode == MODE_NORMAL):\n\t\t\tnode.log(\"Steer into wind\")\n\t\t\tbeep(3)\n\t\t\tsteer_into_wind()\n\t\t\tmode = MODE_STEER_INTO_WIND","outputs":1,"x":640,"y":300,"wires":[[]]},{"id":"55bb2f92.c05b3","type":"ui_button","z":"69638511.9f0fdc","name":"","group":"966da9df.2c4648","order":1,"width":0,"height":0,"passthru":true,"label":"STANDBY","tooltip":"","color":"","bgcolor":"","icon":"","payload":"1","payloadType":"num","topic":"","x":450,"y":260,"wires":[["3f72a40.aac515c"]]},{"id":"63cd06d1.cc5018","type":"inject","z":"69638511.9f0fdc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":300,"y":260,"wires":[["55bb2f92.c05b3"]]},{"id":"71191e8a.4a8df","type":"inject","z":"69638511.9f0fdc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":300,"y":340,"wires":[["cbb1ef69.90424"]]},{"id":"966da9df.2c4648","type":"ui_group","z":"","name":"Müdür","tab":"2cac5f75.ceba6","order":1,"disp":true,"width":"6","collapse":true},{"id":"2cac5f75.ceba6","type":"ui_tab","z":"","name":"Monitor","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
Mind you, this is still rough and probably full of bugs while I'm learning to use Python and NodeRed.
I got stuck last night on the fact I had to enable UART first, but openplotter warned me this was going to disable bluetooth (which I'd maybe need later).
I'm using an RPi 4, which should have 6 UARTs, so I need to investigate if I can use one of them without disabling bluetooth, as it's only disable when using UART0 I think.

Another problem is I don't have my ST2000 here, so testing is difficult Smile
But as Seatalk is a single-wire system, probably STALK_read.py will pick up the transmitted datagrams again?

By the way, do you know if the signalk-plugin does any collision detection?
Quote:To detect data collision, every single bit sent out to the SeaTalk bus is read back again and checked for successful transmission. If the transmission was corrupted, this transmission is stopped immediately. This single datagram will be discarded. When the bus becomes free again, the transmission will be started again. The lost datagram will be repeated on the next update from NMEA data.
Source: http://www.fwma.de/stalk/ManualUsb.pdf

Quote:There is no master on the bus. Every device has equal rights and is allowed to talk as soon as it recognizes the bus to be idle (+12V for at least 10/4800 seconds). Low priority messages use a longer or randomly selected idle-bus-waiting-time. This allows messages from other devices with a higher priority to be transmitted first. The different waiting times of all devices make data collisions (two or more devices start talking at exactly the same moment) very rare. Since each device also listens to its own transmission it will recognize when its message is garbled by a second talker. In this case it abandons the remaining characters of the datagram. It waits for the bus to become free again and then retransmits the whole message. For listeners this means that messages which are shorter than expected are invalid and have to be cancelled totally.
Source: http://www.thomasknauf.de/rap/seatalk1.htm

With all the bits of info I have now, there must be a way for me to translate NMEA XTE messages, coming from OpenCPN, to Seatalk.
But let's take baby steps and get this remote plugin working first Smile
Reply


Messages In This Thread
RE: SeaTalk 1 to NMEA0183/2000 with Raspberry Pi - by Nikotine - 2020-09-08, 11:58 AM

Forum Jump:


Users browsing this thread: 1 Guest(s)