commit 3da51315b6b52ec576c88b6997c74b77c5728e88 Author: Gabiginer Date: Sun Oct 4 01:48:55 2026 +0200 Primer commit: equipo de viento diff --git a/README.md b/README.md new file mode 100644 index 0000000..98359cf --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# Equipo de viento +Este proyecto enseña cómo utilizar un sensor de viento de bajo coste como equipo de viento para un velero, igualando (o superando) las prestaciones de equipos comerciales mucho más caros. + +La idea es utilizarlo en combinación con sistemas de visualización tipo Dashboard, cómo Kip, SignalK/Instrumenpanel, el Dashboard de Node-Red, o el incluido en aplicaciones como OpenCPN, Freeboard-sk, Avnav y similares. + +Además se pueden graficar los datos con software cómo InfluxDB o Grafana. + +Equipo utilizado: + +Sensor de velocidad y dirección del viento de bajo coste cuyos datos salen por un puerto RS-485: + +[Kit de sensor de dirección y velocidad del viento integrado, anemómetro, RY-FSX](https://es.aliexpress.com/item/1005005287660742.html?spm=a2g0o.productlist.main.1.63b078bdqfN1rq&algo_pvid=3e6598ce-523a-4587-b719-0bb3406c3743&algo_exp_id=3e6598ce-523a-4587-b719-0bb3406c3743-0&pdp_ext_f=%7B%22order%22%3A%2210%22%2C%22eval%22%3A%221%22%7D&pdp_npi=4%40dis%21EUR%2153.39%2153.39%21%21%21423.06%21423.06%21%402103956a17477515592515133e534a%2112000032500182038%21sea%21ES%21160365273%21X&curPageLogUid=hxFhplcr5wzF&utparam-url=scene%3Asearch%7Cquery_from%3A) + +![Sensor](https://git.gabiginer.es/Gabiginer/EquipoDeViento/raw/branch/main/README/Sensor.jpg) + +Convertidor de USB a RS-485: + +[Waveshare USB a RS485 convertidor serie RS485 ](https://es.aliexpress.com/item/1005007460513916.html?spm=a2g0o.productlist.main.3.5d35Kmo6Kmo6L1&algo_pvid=cfec339a-2243-43bd-a441-eceb0f6178e5&algo_exp_id=cfec339a-2243-43bd-a441-eceb0f6178e5-2&pdp_ext_f=%7B%22order%22%3A%2213%22%2C%22eval%22%3A%221%22%7D&pdp_npi=4%40dis%21EUR%2110.31%216.39%21%21%2111.32%217.02%21%402103956a17477514417543782e531a%2112000040848779764%21sea%21ES%21160365273%21X&curPageLogUid=fguNH0mktlkN&utparam-url=scene%3Asearch%7Cquery_from%3A) + + +![Convertidor.jpg](https://git.gabiginer.es/Gabiginer/EquipoDeViento/raw/branch/main/README/Convertidor.jpg) + + +Una Raspberry Pi con SignalK instalado (Recomendado Raspberry Pi 4 o superior) + +[Ficha técnica del sensor](https://git.gabiginer.es/Gabiginer/EquipoDeViento/src/branch/main/RY-FSX%20wind%20speed%20and%20direction%20sensor.pdf) + +Pre requisitos: + + - SignalK + - Node-Red + +# Instalación + + + - En Node-Red instalar la paleta "node-red-contrib-modbus" + + - Importar el archivo SensorDeViento.json (o copiar y pegar su contenido en la ventana de importación) + + - En el nodo Wind-Read hacer click en editar server ModBus_Wind y seleccionar el puerto USB adecuado para cada equipo. + + - Hacer click en Instanciar... ¡¡y disfrutar!! + +Una vez en funcionamiento, inyectará los siguientes valores en SignalK: + + - self.environment.wind.speedApparent: Velocidad aparente del viento en m/s. + - self.environment.wind.angleApparent: Angulo aparente del viento en relacción a la proa (de 0º a 180º a babor, de 0º a -180º a estribor) + + + # Galería + + Flujo Node-Red + ![Flujo Node-Red](https://git.gabiginer.es/Gabiginer/EquipoDeViento/raw/branch/main/README/Flujo%20Node-Red.jpg) + + Instrumentpanel + ![Instrumentpanel](https://git.gabiginer.es/Gabiginer/EquipoDeViento/raw/branch/main/README/Instrumentpanel.jpg) + + Kip + ![KIP](https://git.gabiginer.es/Gabiginer/EquipoDeViento/raw/branch/main/README/Kip.jpg) + + OpenCPN +![OpenCPN](https://git.gabiginer.es/Gabiginer/EquipoDeViento/raw/branch/main/README/OpenCPN.jpg) \ No newline at end of file diff --git a/README/Convertidor.jpg b/README/Convertidor.jpg new file mode 100644 index 0000000..aefac67 Binary files /dev/null and b/README/Convertidor.jpg differ diff --git a/README/Flujo Node-Red.jpg b/README/Flujo Node-Red.jpg new file mode 100644 index 0000000..7daa28a Binary files /dev/null and b/README/Flujo Node-Red.jpg differ diff --git a/README/Instrumentpanel.jpg b/README/Instrumentpanel.jpg new file mode 100644 index 0000000..adb9969 Binary files /dev/null and b/README/Instrumentpanel.jpg differ diff --git a/README/Kip.jpg b/README/Kip.jpg new file mode 100644 index 0000000..0c4cc8b Binary files /dev/null and b/README/Kip.jpg differ diff --git a/README/OpenCPN.jpg b/README/OpenCPN.jpg new file mode 100644 index 0000000..af593db Binary files /dev/null and b/README/OpenCPN.jpg differ diff --git a/README/Sensor.jpg b/README/Sensor.jpg new file mode 100644 index 0000000..c17a736 Binary files /dev/null and b/README/Sensor.jpg differ diff --git a/RY-FSX wind speed and direction sensor.pdf b/RY-FSX wind speed and direction sensor.pdf new file mode 100644 index 0000000..672ce26 Binary files /dev/null and b/RY-FSX wind speed and direction sensor.pdf differ diff --git a/SensorDeViento.json b/SensorDeViento.json new file mode 100644 index 0000000..00f1477 --- /dev/null +++ b/SensorDeViento.json @@ -0,0 +1,455 @@ +[ + { + "id": "44d283ea6b7c10e4", + "type": "tab", + "label": "Flujo 2", + "disabled": false, + "info": "", + "env": [] + }, + { + "id": "3a43f618afbfa2f7", + "type": "modbus-read", + "z": "44d283ea6b7c10e4", + "name": "Wind-Read", + "topic": "", + "showStatusActivities": true, + "logIOActivities": false, + "showErrors": true, + "showWarnings": true, + "unitid": "255", + "dataType": "HoldingRegister", + "adr": "0", + "quantity": "2", + "rate": "1", + "rateUnit": "s", + "delayOnStart": false, + "startDelayTime": "", + "server": "708f53f6157d2ec2", + "useIOFile": false, + "ioFile": "", + "useIOForPayload": false, + "emptyMsgOnFail": false, + "x": 100, + "y": 360, + "wires": [ + [ + "3cc6dfe7007d4f73", + "f0196ac713c38671", + "b5d068337b7b3f1f" + ], + [] + ] + }, + { + "id": "9956a0ce0ffa1692", + "type": "debug", + "z": "44d283ea6b7c10e4", + "name": "debug RAW", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": true, + "complete": "true", + "targetType": "full", + "statusVal": "payload", + "statusType": "auto", + "x": 730, + "y": 60, + "wires": [] + }, + { + "id": "3cc6dfe7007d4f73", + "type": "function", + "z": "44d283ea6b7c10e4", + "name": "RAW", + "func": "\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 470, + "y": 60, + "wires": [ + [ + "9956a0ce0ffa1692" + ] + ] + }, + { + "id": "d6c4f0aeee28dff6", + "type": "function", + "z": "44d283ea6b7c10e4", + "name": "RAW 2 m/s", + "func": "msg.payload /= 100\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 730, + "y": 200, + "wires": [ + [ + "9eeec0837153c824", + "ac8c43cb79976b82", + "fe880495d58287f5" + ] + ] + }, + { + "id": "9eeec0837153c824", + "type": "debug", + "z": "44d283ea6b7c10e4", + "name": "m/s", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": true, + "complete": "payload", + "targetType": "msg", + "statusVal": "payload", + "statusType": "auto", + "x": 950, + "y": 260, + "wires": [] + }, + { + "id": "ac8c43cb79976b82", + "type": "ui_gauge", + "z": "44d283ea6b7c10e4", + "name": "", + "group": "786fd9e70bfb3a7b", + "order": 1, + "width": 0, + "height": 0, + "gtype": "gage", + "title": "Velocidad Aparente", + "label": "m/s", + "format": "{{payload}}", + "min": 0, + "max": "20", + "colors": [ + "#21a7f8", + "#21a7f8", + "#21a7f8" + ], + "seg1": "5", + "seg2": "10", + "diff": false, + "className": "", + "x": 990, + "y": 200, + "wires": [] + }, + { + "id": "fe880495d58287f5", + "type": "signalk-send-pathvalue", + "z": "44d283ea6b7c10e4", + "name": "wind.speedApparent", + "path": "environment.wind.speedApparent", + "source": "node-red-wind", + "meta": "{}", + "x": 1000, + "y": 140, + "wires": [] + }, + { + "id": "f0196ac713c38671", + "type": "change", + "z": "44d283ea6b7c10e4", + "name": "", + "rules": [ + { + "t": "delete", + "p": "payload[1]", + "pt": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 520, + "y": 200, + "wires": [ + [ + "d6c4f0aeee28dff6" + ] + ] + }, + { + "id": "524293978f86d016", + "type": "switch", + "z": "44d283ea6b7c10e4", + "name": "Ajustes grados", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "1", + "vt": "num", + "v2": "270", + "v2t": "num" + }, + { + "t": "btwn", + "v": "271", + "vt": "num", + "v2": "360", + "v2t": "num" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 740, + "y": 440, + "wires": [ + [ + "129be4eb1a46fa37" + ], + [ + "617ba108d4ea2e34" + ] + ] + }, + { + "id": "129be4eb1a46fa37", + "type": "function", + "z": "44d283ea6b7c10e4", + "name": "+90 grados", + "func": "msg.payload -= -90\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 420, + "wires": [ + [ + "2182ef5de4dec356" + ] + ] + }, + { + "id": "617ba108d4ea2e34", + "type": "function", + "z": "44d283ea6b7c10e4", + "name": "- 270 grados", + "func": "msg.payload -= 270\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 460, + "wires": [ + [ + "2182ef5de4dec356" + ] + ] + }, + { + "id": "433a508466e9cba6", + "type": "function", + "z": "44d283ea6b7c10e4", + "name": "RAW 2 grados", + "func": "msg.payload/=10\nmsg.payload = parseFloat(msg.payload).toFixed(0);\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 540, + "y": 440, + "wires": [ + [ + "524293978f86d016" + ] + ] + }, + { + "id": "b5d068337b7b3f1f", + "type": "change", + "z": "44d283ea6b7c10e4", + "name": "", + "rules": [ + { + "t": "delete", + "p": "payload[0]", + "pt": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 320, + "y": 440, + "wires": [ + [ + "433a508466e9cba6" + ] + ] + }, + { + "id": "2182ef5de4dec356", + "type": "function", + "z": "44d283ea6b7c10e4", + "name": "a 2 de 180", + "func": "let angle = msg.payload % 360;\n\nif (angle === 0) {\n msg.payload = 0; // o 360 si prefieres mostrar 360 en el tope\n} else if (angle > 0 && angle <= 180) {\n msg.payload = angle; // positiva\n} else {\n msg.payload = -(360 - angle); // negativa\n}\n//msg.payload *= -1 // invierte el signo\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1090, + "y": 440, + "wires": [ + [ + "db43738fe70d0528", + "0662b9ac82b626c2", + "bf89d6dd2cb68747" + ] + ] + }, + { + "id": "db43738fe70d0528", + "type": "ui_gauge", + "z": "44d283ea6b7c10e4", + "name": "", + "group": "786fd9e70bfb3a7b", + "order": 4, + "width": 0, + "height": 0, + "gtype": "compass", + "title": "Dirección Aparente", + "label": "units", + "format": "{{value}}", + "min": "-180", + "max": "180", + "colors": [ + "#00b500", + "#e6e600", + "#ca3838" + ], + "seg1": "", + "seg2": "", + "diff": false, + "className": "", + "x": 1310, + "y": 500, + "wires": [] + }, + { + "id": "51f2c03e3dd98307", + "type": "signalk-send-pathvalue", + "z": "44d283ea6b7c10e4", + "name": "wind.angleApparent", + "path": "environment.wind.angleApparent", + "source": "node-red-wind", + "meta": "{}", + "x": 1300, + "y": 340, + "wires": [] + }, + { + "id": "0662b9ac82b626c2", + "type": "debug", + "z": "44d283ea6b7c10e4", + "name": "debug 2", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": true, + "complete": "payload", + "targetType": "msg", + "statusVal": "payload", + "statusType": "auto", + "x": 1280, + "y": 440, + "wires": [] + }, + { + "id": "bf89d6dd2cb68747", + "type": "function", + "z": "44d283ea6b7c10e4", + "name": "Pasa a radianes", + "func": "let grados = msg.payload;\n\n// Convertir a radianes\nlet radianes = grados * (Math.PI / 180);\n\n// Asignar el resultado a msg.payload\nmsg.payload = radianes;\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 340, + "wires": [ + [ + "51f2c03e3dd98307" + ] + ] + }, + { + "id": "708f53f6157d2ec2", + "type": "modbus-client", + "name": "ModBus_Wind", + "clienttype": "serial", + "bufferCommands": true, + "stateLogEnabled": true, + "queueLogEnabled": false, + "failureLogEnabled": true, + "tcpHost": "127.0.0.1", + "tcpPort": "502", + "tcpType": "DEFAULT", + "serialPort": "/dev/ttyACM0", + "serialType": "RTU-BUFFERD", + "serialBaudrate": "9600", + "serialDatabits": "8", + "serialStopbits": "1", + "serialParity": "none", + "serialConnectionDelay": "100", + "serialAsciiResponseStartDelimiter": "0x3A", + "unit_id": 255, + "commandDelay": 20, + "clientTimeout": 1000, + "reconnectOnTimeout": true, + "reconnectTimeout": 1000, + "parallelUnitIdsAllowed": false, + "showErrors": true, + "showWarnings": true, + "showLogs": true + }, + { + "id": "786fd9e70bfb3a7b", + "type": "ui_group", + "name": "Wind", + "tab": "36a5a0d798f9c3c6", + "order": 1, + "disp": true, + "width": "6", + "collapse": false, + "className": "" + }, + { + "id": "36a5a0d798f9c3c6", + "type": "ui_tab", + "name": "Dirección", + "icon": "dashboard", + "disabled": false, + "hidden": false + } +] \ No newline at end of file