The online maps come from the internet through this phone, not from Luff: on the boat's Wi-Fi with internet, or the phone's data. Without it, Luff's own map. Not for navigation.
No position: the map comes with one (Link → Position).
- SPEED
- --
- HEADING
- ---°
- BEARING
- --
- TO GO
- --
No heading. Make this phone the boat's compass so Luff can steer?
- Rate
- 0.0°/s
- Heel
- 0°
- Speed
- --
- Next point
- --
- Distance · bearing
- --
- Route length
- --
- Left to the end
- --
- Position
- --
- Speed · heading
- --
- Magnetic variation
- --
Selecting heading source...
Control diagnostics unavailable.
Gains
pypilot's sliders, its names, ranges and defaults: its pilot's gains (the motor's speed from the course error P and PR, the turn D, its acceleration DD and the course's change FF), its servo (period, speed min and max, max slew speed and slow) and its tack. No deadband, as pypilot: the turn is checked right to the course. Min and Max Motor PWM are Luff's motor calibration. The striped strip on the right only scrolls the page.
Profile default: pypilot's own settings, locked. To tune, tap Add under Profile (bottom of Tune): a copy you can change. The slews and the motor's PWM are the same for every profile and stay free.
Profile
pypilot's profiles: named sets of the gains, the period, speed min and max, and the tack (the slews and the motor's PWM are the same for all, as in pypilot). Choosing one puts its settings on the sliders. A change steers at once, to try it, but is kept only with Save profile, a "save as": with the name it suggests (the profile in use) it updates that profile; with a new name it makes a new profile of the settings now, the one edited left as it was saved. Choosing another profile, or a restart of Luff, brings back what was saved. default is pypilot's own settings and stays so: locked, never removed. Add: a new profile, a copy of the settings now (5 at most besides default). Remove: the profile in use goes, default is taken.
Help
Firmware --
Created by: Marc Robitaille
How to use the helm
- The Helm is the map, with the speed, heading, bearing and distance to the next point over its top, and the next point's line (⚑, right under those numbers: its name; while Luff follows the route, how far off its line and the side to steer to; when, at this speed; a tap shows the route). The bar under the map keeps the pilot in view: the mode, Standby (in AUTO) or Auto (in standby: AUTO on the current heading); in AUTO the course buttons about the course Luff steers to, labelled STEERING (the course held; in Track, the bearing turned back toward the route's line; the GPS course in GPS, the wind angle in the wind modes, P port or S starboard), with the error under it, or the GPS course or the wind now; in standby ◀ Port and Starboard ▶ about the heading; the tack buttons when the mode tacks. Slide the bar up (drag its grip, or tap it) for the modes, Hold bow / Reset course, the turn rate, heel and speed, and the rudder; up again for the route with its Use switch, the heading source and the pilot's diagnostics; tap the grip there to bring it down. Alarms show over the top of the map. Without a position, the heading in big figures stands where the map is, with the course held and the error under it in AUTO.
- Check the heading source and its sample age (the bar slid up twice) before enabling AUTO. When AUTO is enabled, the current heading becomes the target. Use Hold bow / Reset course to set the target to the current heading; Reset course shows in heading hold only (3.25.3) — in Track, wind or GPS it used to drop Luff back to Heading, and the route was no longer followed. The course buttons adjust the target by 1° or 10°.
- The helm shows heading, target, heading error, heel, yaw rate (the turn about the vertical, as pypilot's: from the compass's gyro and gravity, so a heeled boat's turn reads true), motor PWM command, GPS speed, active source, and the pilot's diagnostics (turn acceleration, its motor speed, the steering state). The heading refreshes frequently; a PWM value is a motor command, not measured rudder position.
- Use the A− / A+ controls in the upper-right corner to resize the interface from 70% to 130%. Tap the percentage to return to 100%; your choice is saved in this browser.
- Link holds Luff's settings in five groups, each opened with a tap on its title (3.14.2): Connections & sources (open first: the connections' state and where each input comes from), Navigation (the route kept on Luff, the track), Alarms & safety (alarms, end stops, the deck buttons), Sensors (the GPS module, compass calibration, rudder sensor) and Network (every network connection, 3.20.0: Wi-Fi, Signal K and NMEA 0183 in, send to the plotter and the shares, who may command Luff, status). Its Save buttons are in colour (3.14.4): a setting changed there is kept only once saved.
- A physical deck button (on/off, GPIO 32) also toggles AUTO/STBY. Five more can be fitted and ticked in Link → Deck buttons (3.15.0): mode, pause/resume, cancel the alarm, Port and Starboard; with their beeps Luff can be run with no phone at all. The fixed bottom navigation switches between Helm, Tune, Help and Link.
- Track follows the plotter's route (NMEA APB to Luff's UDP port) as pypilot: the heading to steer (else the bearing to the waypoint) and back toward the line by 30° for each 0.1 nm off it, 45° at most. A true course is steered as a course over ground once Luff has learned the GPS course's offset from the compass for 30 seconds (see GPS); until then it is turned magnetic with the GPS's variation (RMC, HDG or Signal K), else the World Magnetic Model's at Luff's position. If the route stops for 3 seconds, Luff holds the last course (or follows the route kept on Luff, when set as a backup) and the route-lost alarm sounds 5 seconds later; after 8 seconds without a route, as pypilot's fallbacks, GPS takes over on the same course (else Heading), and Track comes back with the route; the alarm stops then. Heading or a course button returns to heading hold.
- One route sender at a time (two phones, or a phone and a plotter): while one's route comes, the others' are set aside, and the helm says so. Another takes over once the first has been quiet for 3 seconds, or at once when its app asks.
- Without a plotter's route, Track follows the route kept on Luff (Link → Route kept on Luff), when its Use switch is on, by Luff's own position, from the nearest point (its nearer leg; the start itself, straight to it, while the boat is still before it, 3.26.1): toward the next point and back toward the line as a plotter's route, on to the next point within 0.05 nm or once past it. Tap, or long-press, a point of the route on the map — in any mode, standby too — and a small card offers the choice (3.26.2): Steer to it (Track), Luff turning straight to that point, a passed one too, the route going on from it (Track engages on the kept route, AUTO coming on from standby, as OpenCPN activates a route point), or Edit the route, the editor opening on that point. In the editor, Join track here keeps the route (as Save does) and steers to the point picked, in one go. If the position stops, Luff holds the last course and the route-lost alarm sounds; at the last point it holds the last course and the route-end alarm sounds.
- GPS holds the course over ground of the course steered (true; from standby, of the bow), as pypilot's GPS mode: the compass steers, and Luff learns slowly how far the GPS course is from it (leeway, current, the compass's error and its drift) while the boat makes more than 1 kn, from 0 at start-up (settled in about half a minute), so the boat goes where the GPS says, steered as quickly as on the compass. The course comes from any GPS source (Link → Sources, in the speed's order): the GPS module, NMEA RMC or VTG, Signal K or the phone. The course buttons move it. With GPS course chosen as the heading (Link → Sources → Heading), the GPS course itself is the heading, over its minimum speed only (2 kn unless changed there). Under 1 kn the offset is held as it was. If the GPS course stops, Luff steers on with the last offset; after 8 seconds Heading takes over on the same course, and GPS comes back with the GPS course (its course, if within 30 seconds).
- Wind holds the apparent wind angle of the course steered (from standby, of the bow), from the wind instrument (NMEA MWV or VWR to Luff's UDP port, or Signal K), smoothed as pypilot does: each sample by 0.1 × ln(wind speed / 5 + 1.1), so more wind, more weight; the compass steers between samples. The course buttons move that angle, on the same side (15° to 170°). If the wind stops for 3 seconds, Luff holds the last course and the wind-lost alarm sounds 5 seconds later; after 8 seconds Heading takes over on the same course, and Wind comes back with the wind (its angle, if within 30 seconds).
- True wind holds the true wind angle the same way: an instrument's (NMEA MWV with T), else worked out from the apparent wind and the boat's speed through the water (NMEA VHW, Signal K), or else the GPS speed (smoothed over 25 seconds). Lost for 8 seconds, Wind takes over, then Heading.
- Tack, as pypilot's: tap ◀ Tack port or Tack stbd ▶ twice, in Heading, GPS, Wind or True wind. After the tack delay (Tune; counted down, Cancel stops it), the boat turns at the tack turn rate until the share of the turn set in Tune (50%) is done, then the pilot steers the new course: in Heading and GPS the tack angle (Tune, 100°) to that side; in the wind modes, whichever button, the same wind angle on the other side: through the wind under 90° off it (half the turn the bow head to wind), else a gybe (half the turn the stern dead downwind). A gybe asks first, "About to gybe. Is this OK?" Yes / No (3.15.0, as pypilot): in the wind modes over 90° off the wind; in Heading and GPS a turn away from the side the wind has been on for 5 seconds, or, without a wind instrument and when chosen in Link → Sources, away from the high side when heeled over 7° for 5 seconds. No side known: to the side tapped, no question. A turn not done in 30 seconds ends, the old course kept; a course button or another mode also stops a tack.
- MOB (man overboard, 3.15.0), the red button over the map: at once, no question, Luff goes to standby (hand steering) and marks the point from its GPS in use (this phone's location when Luff has none); its alarm sounds on Luff and on every phone with this page or Boat Budget open, until silenced, and each phone opens its map, the point drawn (a red ring and cross, a dashed line from the boat). The card gives its distance and bearing. Steer to MOB asks "Sails ready? Luff will turn to the MOB point." and on Yes steers in Heading on the bearing to it, again each second; within 0.02 nm (37 m) the last course is held, steer by hand. A course or mode chosen, or standby, stops it. End MOB asks first and removes the point; a route followed before stays stopped. The point is kept through a restart of Luff.
- The map on the Helm shows the route kept on Luff on a world map (the coastline from OpenStreetMap, about 2 km of detail, small islands from 150 m across as a dot ringed at their size, and country borders) and the boat at Luff's position (its icon, a gold hull with a navy rim and a ring on the position — the same on Boat Budget's Map and the family page (3.27.0) — its bow along its heading, or its GPS course when chosen in ◧; a gold dot without either), with its track in purple (amber where Luff's map puts the boat on land, to show the map's resolution): a point every 10 m while the boat moves (stopped, the next once 100 m away), the last 200 nm, kept by Luff through restarts (Link → Luff's track); the route card (the bar slid up twice) gives the next point's name, distance and bearing (true, and magnetic when the variation is known), the route's length and what is left to its end with the time to get there at this speed ("8d 1:05h"; the ⚑ line carries it too until the last point), the position, and the speed and heading. It moves with the boat, 5 nm across at first, its scale bottom left with the GPS's accuracy beside it, small, in the unit chosen in Link → Alarms (Units, metres or feet, 3.24.0 — the depth, a man overboard's metres and the AIS sizes follow it too), when the GPS in use tells it (3.20.2); drag or pinch to look around, ⌖ follows the boat again, ⤢ shows the whole route; the eye (first of the buttons) hides the other buttons, the credit, the ⚑ line and the bottom bar, leaving the numbers on top and any alarm, and brings them back. Tap the HEADING over the map to swap the heading source between the compass and the GPS course, when a GPS course is coming. The next point is the one Luff steers to, or, before Track, the nearest point, where Track would join; a tap or a long press on any of its points offers Steer to it (Track, from any mode) or Edit the route (3.26.2). A long press anywhere on the map is the quick go-to (3.26.1): asked first, Luff steers straight to that point in AUTO Heading — the bearing to it again each second — from standby too (AUTO comes on); within 0.05 nm the course of the moment is held and the go-to ends; a long press on the go-to point ends it early, a course or mode chosen, Track or standby too. Its Use switch is the same as in Link; an unused route is not drawn at all (3.25.3) and the ⚑ line, the BEARING and TO GO rest until Use is on again. On the route card each kept route has its Forget (tapped twice, 3.25.3), as in Link. Day draws it on white, Night on dark. The map is coarse near the coast: for the big picture, never for pilotage. Luff sends the map in small parts the first time (the browser keeps them), so it never holds up the steering. ◧ picks an online map under it, as the app's: detailed satellite (Esri), satellite (Sentinel-2, 2016), sea depths (EMODnet) or streets (OpenStreetMap), and sea marks (OpenSeaMap) over any of them. The phone fetches them from the internet, not Luff (on the boat's Wi-Fi with internet, or the phone's data); without it, Luff's own map, as before. ◧ also turns the boat's bow to the GPS course whenever there is one, at any speed, else the heading (3.15.1); Luff still steers by its heading. The choices stay on this phone; Night darkens the pictures.
- AIS on the map: the other vessels Luff hears of, from NMEA 0183 (
!AIVDM) or Signal K. Each is a green triangle along its heading (else its course; a dot without either) where it was last heard, with a line to where its course and speed take it in 5 minutes (from 0.5 kn); the boat has the same line in orange, from its GPS course and speed. Under 20 nm across, each shows its name (else its MMSI) and speed, and one closing on the boat its closest approach under that (3.21.1; owner: "even if not in range yet"), in red when nearer than the collision alarm's distance, up to an hour ahead. Tap a vessel for its details (name, MMSI, its type and size when its AIS sends them (3.22.0; owner: "vessel dimensions and type (sailboat, cargo, etc)"), distance and bearing, speed, course, heading, closest approach, when heard), kept fresh while open. A vessel sends its name, type and size in its static message only every few minutes (its positions every few seconds), so a fresh one shows its MMSI alone and n/a for the type and size until that message comes; tap elsewhere or ✕ to close. Not heard for 3 minutes it is drawn faint, after 10 it is gone; Luff keeps the 40 heard last. The alarms are the circle and the collision course under Alarms. - In standby, ◀ Port and Starboard ▶ power-steer: hold one to move the ram at full power, the maximum PWM (Tune; 255 unless lowered). As pypilot's, the motor starts from zero at max slew speed (full in 0.7 s at 28) and, when you let go, slows to a stop at max slew slow (0.6 s from full at 34); 250 ms after the phone stops sending, it stops at once. After a motor fault (an end stop, the current limit), a new press clears it so the ram can be steered away from the end.
Sources, GPS & connections
Link → Connections lists Luff's links: the router, Luff's own Wi-Fi (the phones on it), Signal K, each NMEA 0183 port, the GPS module, the compass and the rudder sensor; ● working, ✕ set up but not working, – off or not set up. Every network connection is set up in Link → Network (3.20.0): the Wi-Fi networks, Signal K and NMEA 0183 in, Send to the plotter (with Share the GPS module and Share the compass), and who may command Luff.
In Link → Sources, choose where each input comes from: heading, position, speed and wind. The heading (3.15.0): Automatic takes the first that comes of the onboard IMU, the phone fixed to the boat, Signal K, NMEA 0183 and the GPS course (over its minimum speed), at once when the one in use stops, and goes back to an earlier one once it has come for 5 seconds. A source chosen by name is the only one used (owner: "if a specific source is selected... Stay with that source"), but for the onboard IMU ("The IMU is always a fallback"): if the one chosen stops (2 seconds; the IMU half a second), the IMU carries its last heading on, so the steering goes on, and takes over after 10 seconds; the one chosen comes back once it has come for 5 seconds. Without the IMU the rudder is held still, and after 10 seconds AUTO goes to standby and the heading alarm sounds. A source that stops sounds a short alarm, 15 seconds. The helm names the source in use. Each change of source keeps the course error; the same source back after a gap keeps its course. Position, speed and wind: Automatic takes the first fresh source in the order shown; a source chosen comes first, and the others take over in that order when it stops. Position and speed: the GPS module on the board, NMEA, Signal K, then the phone. Wind: NMEA, then Signal K.
Phone (position and speed): Boat Budget sends its phone's GPS to Luff every second while it is connected to Luff (its Luff page open or a route followed, screen off too), named by its $PLUF,SRC sentence; or this page sends this phone's location (Link → Lend this phone's location). 3.15.0: this page only while Luff wants it (Boat Budget too, with its next update): the phone chosen as the position or the speed, or no other GPS coming (owner: "the phones gps is deactivated as to not use the battery"); it turns on by itself, and off again once another GPS has come for 10 seconds. Luff's track comes from the GPS in use.
Who may command Luff (Link): ticked ones may engage AUTO, steer, power-steer and choose the route: this helm page, phone apps (Boat Budget), the deck buttons, the plotter's route (NMEA APB). Standby, a stop and silencing the alarms work from all of them, always. Luff takes commands only from its own page and from apps: a page from another website open on a phone on the boat's Wi-Fi is turned away.
- Onboard IMU: BNO055 or ICM20948, selected at compile time in firmware. The BNO055's calibration (0 to 3 for system, gyro, accel and mag; 3 is calibrated) shows on the helm. Luff loads the saved calibration at start-up and saves it by itself the first time it is complete (in standby); Link → Compass calibration saves or forgets it.
- Phone compass: Browser device orientation, from this page open on the phone ticked in Link → Sources as fixed to the boat (3.15.0), only one phone at a time; another phone that ticks it takes over after a warning naming the phone in use by its address. Used when Phone compass or Automatic is chosen (a touch on the page starts it; sensor permission may be required). That phone is then the boat's compass: keep it fixed to the boat, pointing ahead, and calibrated; a phone in a hand steers the boat where it points.
- GPS course (owner, 2026-10-28): the course over ground from the GPS (any source, in the speed's order) as the heading, true, while the boat makes more than its minimum speed (Link → Sources, under Heading: 0.1 to 2 kn, 2 by default); once in use, down to three quarters of it (1.5 kn of 2), so it does not hop. The slower the boat, the more the GPS course wanders, so a low minimum can make the steering wander. Slower, the board's compass takes its place if there is one; else there is no heading, and AUTO goes to standby with the heading alarm. No magnetic interference or drift, but it comes once a second on most GPSs and lags a turn, so the steering is slower and softer than on a compass.
- NMEA 0183: UDP, default port
10110, and up to three more ports (Link → Network → Signal K and NMEA 0183 in; 3.20.0), for a sender on a port of its own such as an AIS receiver; every port feeds the same. Heading accepts checksum-valid HDM, HDG (deviation applied when given), and HDT; magnetic headings are used, HDT only when no magnetic heading has come for 2 seconds. ROT can supply turn rate; otherwise it is estimated from heading changes. VTG/RMC can supply GPS speed. MWV (apparent wind, R) or VWR supply the wind for wind mode; MWV with T an instrument's true wind, and VHW the speed through the water, for True wind. DPT, else DBT, supplies the depth (3.22.0), shown small by the map's scale and watched by the minimum depth alarm. AIS (!AIVDM, here or on the GPS module's line) puts other vessels on the map. - Signal K: WebSocket, default port
3000. Configure the server host and optional token in Link. Luff subscribes to magnetic/true heading, rate of turn, speed over ground, the apparent wind, the speed through the water (for True wind), the position and the magnetic variation; it uses the magnetic heading, the true one only when no magnetic heading has come for 2 seconds. Once the server says which vessel it is on, Luff also takes the other vessels' positions, courses, speeds, names, types and sizes (its AIS; the types and sizes from 3.22.2), every 5 seconds at most, for the map only; they never count as this boat's. The connection runs apart from the steering, so an unreachable server cannot pause it. - Position (to follow the route kept on Luff, and for the map on the Helm): a GPS module on the board (NMEA 0183 on GPIO 16; Link → Position), NMEA over UDP (RMC, GGA, GLL), Signal K or the phone, as chosen in Link → Sources. A position older than 5 seconds is lost.
- Course over ground (GPS mode and Track): from the same sources as the speed, in its order: RMC or VTG (the GPS module or NMEA over UDP), Signal K
navigation.courseOverGroundTrue, or the phone (Boat Budget's RMC, or this page's location while moving). Older than 3 seconds it is lost.
Send to the plotter (Link → Network, each switch off by default), as NMEA 0183 broadcast over UDP on its port: Send pilot status, the heading (HDM or HDT) four times a second and the rudder angle (RSA, with the rudder sensor) once a second, and with Signal K connected the pilot's state, target heading and rudder angle too; Share the GPS module, its position, course and speed; Share the compass, the onboard IMU's heading (HDM), heel and pitch (XDR) and turn rate (ROT).
A setting not saved (3.20.0): when Luff's settings store refuses a save (almost always because it is full), the Helm says what was not saved, until OK, and so does the top of Link until Luff has saved it. It still works until Luff restarts, then it is lost: forget what Luff no longer needs (a tuning profile, a Wi-Fi network, the route kept on Luff), then save it again. Link → Network → Status shows the places free.
Network sources require Luff to reach the data server over Wi-Fi. Signal K uses an unencrypted local WebSocket; use it only on a trusted network and do not enter a token on an untrusted network.
GPS speed comes from the source chosen in Link → Sources (the GPS module, NMEA, Signal K or the phone). This page lends its phone's location (Link → Lend this phone's location, ticked at first) only while Luff has no other GPS or the phone is the position or speed chosen, so no battery is used otherwise (3.15.0); untick it never to lend it. The other sources work independently. Adjust steering strength to boat speed (optional, off by default) multiplies the motor's steering output by the reference speed over the GPS speed, between 0.5 and 1.5.
Steering & tune settings
Luff steers as pypilot does. Its pilot gives the motor a speed, from stop to full either way, worked out from the course error (up to 30°), the turn, the turn's acceleration and how fast the course itself moves: P × error + PR × √error − D × turn − DD × turn acceleration + FF × course change. Coming back to the course, the turn slows by itself as the course nears (D against P and PR), right to the course: there is no deadband, as in pypilot (3.12.0; owner: "remove deadband and make 100% pypilot clone"), and no reverse brake pulses. The heading and the turn are smoothed over 0.2 s and the turn acceleration over 0.45 s, as pypilot does.
Pulses (pypilot's servo): a speed under speed min adds up until it is worth a pulse at speed min, so the motor runs for as long as the speed asks for in all; the speed is never over speed max. A start, a stop or a change of direction comes at most once a period; a change of direction goes by way of a stop.
Max slew speed and max slew slow (pypilot's motor controller): how fast the motor speeds up and slows down, in pypilot's numbers: the PWM changes by that many thousandths of full power every 1/50 s; 28 goes from stop to full in 0.7 s, 34 from full to a stop in 0.6 s. As pypilot's: the motor starts from zero; a change of direction slows down through zero and speeds up the other way, with no pause of its own; the motor is off (braked) while within a tenth of full power of a stop (PWM 25). Power steer likewise. Standby, the kill switch, a fault, an end stop or a lost phone stop it at once.
Tack (Heading, GPS and the wind modes): the turn is held at the tack turn rate until the share of it set in Tune is done; then the pilot steers the new course.
Bench-test motor direction and stop behavior before trying AUTO on the water.
Tune slider guide
Drag a slider's round thumb to change it. The numeric value is shown beside each slider. Touching the track away from the thumb does not move it. The striped strip on the right of the sliders only scrolls the page. Each slider below: what it is for, then how to use it. The advice is pypilot's (its author, Sean D'Epagnier, on the OpenMarine forum, and pypilot's workbook wiki), as Luff steers as pypilot does.
Where to start (pypilot's author: "Starting out, you mostly need just D gain, and a bit of P to avoid drifting off course. It's possible to hold a course using just these two gains"): begin from pypilot's defaults, or with only D and a little P. Change one slider at a time, a small step, and watch the boat for a minute in steady conditions before the next. Tune D first, then P; then PR, DD and FF if needed. "If the gains are too high, the autopilot will track all over"; lower gains also use less power. Many pairs of P and D steer about as well: once one works, raise or lower both together to keep their ratio. Keep what works for each kind of day in a profile (bottom of Tune): default is pypilot's and locked, so Add one first, and tap Save profile to keep a change in it.
- P (course error) 0–0.03, default 0.003. For: how hard the pilot steers back for each degree off course; it also holds the rudder against weather helm. Use: raise it in small steps if the boat wanders off or comes back too slowly; lower it if the boat overshoots and snakes about the course. Some P is always needed.
- D (turn) 0–0.24, default 0.09. For: the main gain: it steers against the boat's turn, stopping a swing before it grows and slowing the boat as it comes back to the course (the turn's brake, right to the course). Use: raise it if the boat overshoots the course or yaws from side to side; lower it if the pilot steers back too early, the boat stops short of the course, or the motor works all the time in a seaway.
- DD (turn acceleration) 0–0.24, default 0.075. For: answers the turn as it starts, a wave's push, before it becomes a swing. Use: if the boat still oscillates with D set, "try slowly increasing it, but not to a value higher than 1.5x of the D gain" (pypilot's author); lower it if the motor jerks at every wave.
- PR (root of the course error) 0–0.02, default 0.005. For: more push than P for small errors, less for big ones: "This makes less movements when the heading is very wrong to avoid overshoot." Use: "Using a high value for PR, and cutting the P gain way back can reduce overshoot and oscillation", but keep some P. Raise PR until it shows, then lower P.
- FF (course change) 0–2.4, default 0.6. For: steers the moment the course itself moves: a course button, a route's turn, a tack ("The FF gain helps in maneuvering, tacking, and following routes"). It does nothing while the course stays put. Use: raise it if the boat is slow to start turning after a course change; lower it if it overshoots each new course.
- Period 0.1–1 s, default 0.4 s. For: "the minimum time the motor is moving in a certain direction or stopped"; small corrections add up until they are worth a move this long. Use: lower it for shorter, finer moves (more starts of the motor); raise it if the motor chatters on and off.
- Speed min 0–100%, default 100%. For: the speed of each move (pulse), as a share of the way from Min Motor PWM to Max Motor PWM; never over speed max. At 0 the motor runs at the speed asked for, never in pulses. Use: pypilot: "This can also generally be set to 100 to get the best performance." Lower it for gentler, finer moves if the ram is fast for the boat.
- Speed max 0–100%, default 100%. For: the fastest the motor runs in AUTO; never under speed min. Use: "usually always 100"; lower it only if the ram moves the rudder too fast for the boat.
- Max slew speed 0–100, default 28 (stop to full in 0.7 s). For: how quickly the motor speeds up, from a stop or after a change of direction, in AUTO and power steer (pypilot's motor controller: thousandths of full power each 1/50 s). Use: "setting lower will reduce current spikes but also responsiveness": lower it if the motor or the driver gets hot or the starts are harsh; raise it for a quicker answer.
- Max slew slow 0–100, default 34 (full to a stop in 0.6 s). For: how quickly the motor slows down, to a stop or before a change of direction; in power steer, how long the ram runs on after you let go. Use: as max slew speed; lower it if stops are harsh, raise it if the ram runs on after it should stop.
- Min Motor PWM 0–150. For: Luff's calibration of its motor (pypilot's servo calibration): the PWM where the ram starts to move, the least a move asks for; a speed is a share of the way from it to Max Motor PWM. The motor still starts from zero at max slew speed, as pypilot's. Use: set it once on the bench, in standby: max slew speed at 2 for the test (stop to full in 10 s), hold ◀ Port or Starboard ▶ and read the PWM on the rudder bar (slide the helm's bar up) when the ram starts to move; that is Min Motor PWM. Then max slew speed back (28).
- Max Motor PWM 50–255. For: full speed, in AUTO and power steer. Use: 255 for most rams; lower it if the ram is too fast or the motor or driver too hot.
- Tack turn rate 1–100°/s, default 15°/s (pypilot's). For: how fast the boat is turned through a tack, so it carries through the wind ("How quickly to tack"). Use: raise it if tacks stall head to wind; lower it if they are violent or the boat spins past the new course.
- Tack angle 10–180°, default 100°. For: how far a tack turns in Heading and GPS; the wind modes take the same wind angle on the other side by themselves. Use: set it to your boat's tacking angle (wider for a boat that points less high).
- Tack delay 0–60 s, default 0. For: "How many seconds to wait to tack after hitting tack button", counted down on the helm. Use: a few seconds to get to the sheets single-handed; Cancel stops it.
- Tack done at 10–100% of the turn, default 50%. For: when the turn at the tack rate stops and the pilot's gains steer the rest onto the new course. Use: lower it if the boat overshoots the new course; raise it if the boat slows and stalls before it is round.
Profiles (pypilot's)
At the bottom of Tune, as pypilot's Gain page (3.13.0, in place of the sea-state buttons; owner: "yes replace with pypilot profiles"): a profile is a named set of the settings pypilot keeps per profile: P, D, DD, PR, FF, the period, speed min and speed max, and the tack's delay, angle, rate and threshold. The max slew speed and slow and the motor's PWM range are the same for all profiles, as in pypilot.
- default (3.13.3; owner: "Use the same slider defaults as pypilot and name it default profile which can't be edited, deleted, altered"): always first, always pypilot's own settings (below). With it in use, its sliders are locked (greyed) and Save profile is off; to tune, Add a profile: a copy you can change. It is never removed. (pypilot's own "default" can be changed and removed; the lock is Luff's.)
- The sliders show the settings in use. A change steers at once but is kept in the profile only with Save profile (3.14.1; owner: "When a profile is edited... It does not autosave... A save profile button / New Values are used but not autosaved"); until then the Tune page says it is not saved. Save profile is a "save as" (3.14.3; owner: "If the same profile name (suggested) is selected then it updates the profile... If a new name is entered then it creates a new profile with those settings...the edited profile is simply not modified in this case"): it asks for a name, the profile in use's filled in; kept, that profile is updated; a new one makes a new profile of the settings now, then in use, and the one edited keeps what it had saved. The name of another profile, or default, is refused. The max slew speed and slow and the motor's PWM range belong to no profile: they stay free on every profile, default too, and are saved by themselves as before.
- Choosing another profile puts its settings, as saved, on the sliders; changes not saved to the one left are dropped (the page asks first). A restart of Luff likewise brings back the profile's saved settings.
- Add asks for a name (1 to 16 characters): a new profile, saved with the settings now (changes not saved yet included), then in use; the profile left keeps what it had saved. 5 at most besides default (owner: "Up to 5 profile can be created or deleted").
- Remove deletes the profile in use and takes default; default itself cannot be removed.
pypilot's defaults: P 0.003, D 0.09, DD 0.075, PR 0.005, FF 0.6, period 0.4 s, speed min and max 100%, max slew speed 28 and slow 34, and its tack: 15°/s, 100°, no delay, done at 50%. The firmware 3.12.0 set the gains and the servo to them once, at its first start; they are the profile "default".
Safety, wiring & hardware
Alarms: A buzzer on GPIO 23 sounds when heading lost, off course (not turning back), motor fault, low battery, rudder sensor, route lost, wind lost, route end, land ahead, an AIS vessel near, a collision course or the water too shallow has lasted 5 seconds. Silence it on the helm or with the deck button; with an alarm sounding, the first press only silences. Turn alarms off, set the off-course angle, and set up the battery voltage (GPIO 33 through a divider, calibrated against a meter) in Link → Alarms.
Land ahead (off until turned on in Link → Alarms): land on the GPS course within 2 to 10 nm (2 by default), by Luff's own world map, while the boat makes 1.5 kn or more, in AUTO or not; the map shows the spot in red. A rough warning: the map has about 2 km of detail for the coast; smaller islands, from 150 m up to about 4 km across, are kept as dots (a bounding circle round each), so they raise the alarm but can warn a little wide; only the course line is looked along, and a boat the coarse map puts ashore (a marina) is not warned when heading out. Luff reads the coast within the distance and 6 nm more around the boat from its map (a few seconds, beside the steering), again each 5 nm. Never for pilotage.
Collision course (3.21.0; on by default, Link → Alarms, the choice kept): sounds when a vessel's closest point of approach to the boat will come nearer than the distance chosen (0.05 to 5 nm, 0.5 by default) within the next minutes chosen (1 to 60, 20 by default), worked out from each vessel's AIS course and speed against the boat's GPS course and speed. The motion is relative, so a vessel at anchor that the boat bears down on counts, and a vessel bearing down on the boat at anchor; two that do not close at 0.2 kn or more never sound. The alarm names the vessel, its closest approach and when. It needs the boat's position; a vessel with no course or speed in its AIS counts as lying still. On the map, a vessel closing on the boat shows its closest approach under its name before the alarm's range is reached (3.21.1), and a tap on a vessel opens its details.
AIS vessel (3.14.0; off until turned on in Link → Alarms; owner: "Just a simple radius type alarm"): any AIS vessel within the radius chosen around the boat (0.1 to 10 nm, 1 by default), moving or not, in AUTO or not; it needs the boat's position (Link → Position). The vessels are the map's: a position heard in the last 10 minutes, where it was last heard. The alarm names the nearest, its distance and its speed (3.14.2); the map shows the radius as a dashed ring, red while a vessel is inside. A vessel staying inside (at anchor nearby) keeps it on: silenced, it sounds again only once that vessel has gone out and another comes in. Only vessels whose AIS reaches Luff (Link → Sources); never instead of a watch.
Minimum depth (3.22.0; off until turned on in Link → Alarms): sounds when the depth reads shallower than the depth chosen (0.5 to 30 m, 3 by default). The depth comes over NMEA 0183 — DPT (its offset applied: + gives the depth from the waterline, − from the keel), else DBT — on any NMEA port or the GPS module's line, and shows small by the map's scale while it comes. A sudden jump must stay shallow, sounding after sounding, for 5 seconds before the alarm sounds (owner: "Depth jump must be reverified over 5 sec"): one stray reading, or a sounder gone quiet, never sounds it. The alarm names the depth read and the minimum. Never instead of the chart or a lookout.
Kill switch: The active-low kill input stops the motor and forces STBY. If the heading source chosen stops during AUTO and neither the board's compass nor the GPS course can take its place, the motor stops and STBY is latched; restore it and deliberately re-enable AUTO. End stops are optional and off by default (Link → End stops): motor current sensing with its calibration, a full-power time limit, and end-of-travel switches. A current trip or the full-power limit stops the motor and holds STBY until AUTO is chosen again; an open end switch stops travel that way.
GPIO 25: Motor driver RPWM (right/starboard);GPIO 26: LPWM (left/port).GPIO 27: REN;GPIO 14: LEN.GPIO 13: Kill switch, active low to ground;GPIO 32: deck button (on/off), active low to ground; deck buttons when ticked in Link (3.15.0):GPIO 4mode,GPIO 5pause/resume,GPIO 15cancel the alarm,GPIO 36Port andGPIO 39Starboard, each to ground (36 and 39 with a 10 kΩ resistor to 3.3 V).GPIO 21 / 22: I²C SDA/SCL for IMU;GPIO 35: optional analog current sensor (Link → End stops).GPIO 18 / 19: optional end-of-travel switches, port / starboard, normally closed to ground.GPIO 23: alarm buzzer (active buzzer through a transistor);GPIO 33: optional battery voltage through a divider (e.g. 100k over 22k for 12 V).GPIO 16 / 17: optional GPS module (NMEA 0183, 3.3 V): its TX to GPIO 16, its RX to GPIO 17 (Link → Position).
Rudder position feedback is optional: a rudder angle sensor on GPIO 34 (Link → Rudder sensor). Without it, the helm's bar shows the motor command (PWM), not the rudder's angle. Keep the kill switch accessible.
Wi-Fi, browser permissions & first test
The ESP32 provides its own Luff access point (default password luff-helm) while attempting to join saved Wi-Fi networks. Open http://192.168.4.1 or http://luff.local. AP credentials are in firmware; change them before sharing a build. The status page at /status shows diagnostics. Day/night theme and Wi-Fi network management are available in the interface. On the boat's router Luff can keep one address that never changes (Link → Wi-Fi networks → Fixed address); off, the router gives it one.
Phone compass and geolocation APIs may require browser permission. Chrome may block sensors/local-network features on plain HTTP unless the ESP32 address is trusted as a secure origin:
- In Chrome, open
chrome://flags. - Find Insecure origins treated as secure and set it to Enabled.
- Enter the ESP32 address, for example
http://192.168.4.1orhttp://luff.local. Separate multiple addresses with commas, then relaunch Chrome.
For a new build, open luff-code-v12.ino in Arduino IDE, select the matching ESP32 board/core and IMU configuration, choose the partition scheme Huge APP (3MB No OTA/1MB SPIFFS) (the firmware no longer fits the default app space; updates are by USB), install the required IMU, Adafruit Unified Sensor, and ESP32 WebSockets libraries, then compile and upload. Confirm wiring, kill-switch operation, motor direction, and stop behavior with the actuator safely unloaded before enabling AUTO. Compile and bench-test before relying on the pilot underway; this guide is not a substitute for supervised hardware testing.
Link
This page is served by the ESP32 over HTTP.
Connections & sources
Connections
● working · ✕ set up but not working · – off or not set up.
Their settings: Network (Wi-Fi, Signal K, NMEA 0183 in and out) and Sensors (GPS module, compass, rudder sensor), below.
Sources
Where each input comes from. Position, speed and wind: Automatic takes the first fresh one in the order shown; a source chosen comes first, and the others take over when it stops. The heading: the source chosen below; if it stops, the board's compass, else the GPS course, never another.
No heel: it comes from Luff's compass board, or from the phone when it is the heading source.
As pypilot's, off by default: with no wind coming, the boat heeled over 7° to one side for 5 seconds puts the wind on the high side, and a tack in Heading or GPS away from it is a gybe, asked first (3.15.0). Very basic: not reliable under engine, with weight to one side or in a seaway. Check the side once: heeled to port must read "to port" (if not, tick the second box).
No position, speed or wind yet.
Only one phone gives the phone compass (Phone compass chosen, or Automatic): the one ticked here, on its own page. Another phone that ticks it takes over, after a warning.
Faster than the reference, the motor steers less; slower, more (from half to one and a half times). Needs GPS speed.
This phone's location is off. It turns on by itself only when Luff has no other GPS (or the phone is the position or speed chosen), so no battery is used otherwise.
Navigation
Routes kept on Luff
Up to five routes kept on Luff (120 points each), one of them in Use: the route Luff follows by its own position — on its own (Track without a plotter's route) or as a backup when the plotter's route stops — and the one the Helm's map shows. A new route replaces the one in Use, wherever it comes from: Boat Budget's send, a plotter (below), or the pencil on the Helm's map. GPX loads a file's route (its first route, else its track, else its waypoints) into that slot; the circle picks the slot in Use; Forget (tapped twice) empties a slot.
From OpenCPN: right-click the route → Send to GPS and choose Luff's connection (or set an output connection to Luff that carries the WPL and RTE sentences). Luff keeps the waypoints it sends (NMEA 0183 over UDP, on any of its NMEA ports under Network, 10110 by default), replacing any route kept and turning Use on. Then put Luff in Track to follow it. The sender must be ticked under Who may command Luff.
No route kept.
In Track, when the plotter's route has stopped for 3 seconds, Luff follows the route kept on Luff from the waypoint the plotter was steering to (by its name, else the nearest leg), and the route-lost alarm still sounds. When the plotter's route is back, Luff follows it again.
Luff's track
A point every 10 m while the boat moves; stopped (at anchor, at the dock), the next once it is 100 m away. GPS jumps are left out, whichever GPS is in use (3.20.2): a position its GPS says is worse than 50 m (an HDOP over 10, or under 4 satellites; a phone's own metres), one that would mean over 40 kn, and a point out and back (far from the one before while the next is back near it). Luff keeps the last 200 nm in its file space, through restarts, and the Helm's map draws them. Clear the track (tapped twice) forgets it all; it begins again at the next position.
No track yet.
Alarms & safety
Alarms
The buzzer (GPIO 23) sounds when one of these lasts 5 seconds: heading lost, off course, motor fault, low battery, rudder sensor, route lost, wind lost, route end, land ahead, AIS vessel, collision course and minimum depth (each when on, below). Silence it on the helm or with the deck button (with an alarm sounding, the first press only silences).
End stops (optional)
Each one stops the motor before it fights the end of the ram. All are off until turned on here.
Deck buttons
Each a push button to ground. On/off (GPIO 32): from standby AUTO on the heading of that moment (or in the mode the mode button chose); in AUTO standby. The others act only when ticked here, so a pin with nothing wired never acts (3.15.0). GPIO 36 and 39 need a 10 kΩ resistor to 3.3 V each.
Their beeps (only the deck buttons beep): Heading 1, Route 2, GPS course 3, Wind 4, True wind 5 beeps of a second; standby one of 3 seconds; a short tick for each degree.
No deck button ticked down now.
Sensors
GPS module (onboard)
A GPS module wired to the board: its TX to GPIO 16, its RX to GPIO 17 (3.3 V levels), GND to GND. Most modules send NMEA 0183 at 9600 baud. A plotter's NMEA 0183 output can come this way too, through an RS-422 to 3.3 V converter (usually 4800 baud). The other position sources (NMEA 0183 over UDP, Signal K, this phone) are chosen under Connections & sources; without the GPS's magnetic variation, Luff works it out at its position (World Magnetic Model 2025).
No position.
Monitor (the module's raw NMEA)
The lines the module sends, newest at the bottom: readable sentences ($GPRMC, $GPGGA) mean it is talking at the right baud; gibberish means the wrong baud; nothing means no data (check the wiring and 3.3 V). The same lines are printed on the USB serial.
Open this group with the module on to watch it.
Compass calibration (BNO055)
Each part reads 0 to 3; 3 is calibrated. Luff loads the saved calibration at start-up and saves it by itself the first time it is complete (in standby). Move the boat in slow circles to help the compass. The accel part calibrates only from stillness in different tilts (the BNO055's way): hold the pilot still a few seconds in each of several positions — flat, on each side, nose up, nose down — with slow moves between them; sitting level it stays at 0.
No BNO055 calibration data.
No IMU.
Alignment
Trim the onboard compass and zero its mounting tilt; the live compass shows the result.
Turns the onboard compass's heading, ±20°, to match a good compass; watch the heading above. Kept through updates.
Sit the boat level, then tap Calibrate level to zero the heel and pitch (the mounting tilt); watch them settle to 0. Clear undoes it. Kept through updates.
To share the compass on the network: Network → Send to the plotter → Share the compass.
Rudder sensor (optional)
A rudder angle sensor (potentiometer, 0 to 3.3 V) on GPIO 34. Luff shows the rudder's angle and never drives it past the calibrated ends. To calibrate, move the rudder (power steer in standby, or by hand) to each end and to the centre, and press the matching button.
Network
Wi-Fi networks
The board tries each one. If none are in range, Luff stays up.
Signal K and NMEA 0183 in
What comes to Luff over the network; which one it uses for each input is chosen under Connections & sources. Signal K: a server on the boat's network, over its WebSocket. NMEA 0183: sentences broadcast over UDP, on both Wi-Fi networks, to the ports below: a plotter's route (APB, and the WPL and RTE of OpenCPN's Send to GPS), heading, turn rate, speed, wind and AIS.
Who may command Luff
Ticked ones may engage AUTO, steer, power-steer and choose the route. Standby, a stop and silencing the alarms work from all of them, always; this page can always change these settings.
A page from another website, open on a phone on the boat's Wi-Fi, can never command Luff.
Send to the plotter
NMEA 0183 broadcast over UDP on both Wi-Fi networks, to the port below (10110 by default), for Signal K, OpenCPN and plotters. Each its own switch, off by default; each applies as soon as it is ticked.
Luff's heading (HDM, or HDT when steering on true) four times a second, and the rudder angle (RSA, with the rudder sensor) once a second. With Signal K connected, also the pilot's state, target heading (in wind mode also the wind angle) and rudder angle (steering.autopilot, steering.rudderAngle); the Signal K token must allow writing.
The GPS module's position, course and speed (Sensors → GPS module), so Signal K, OpenCPN and plotters can use Luff as their GPS.
The onboard IMU's heading (HDM), heel and pitch (XDR) and turn rate (ROT).
Status
Heading, rudder command, phone compass, free memory, and the settings store's places free.
Open status