Hi,I have been fighting with Remora on a Raspberry Pi for about 3 months now and I am running out of ideas, so I’m asking for some help.
Hardware / versions
- Raspberry Pi: (model + RAM ).
- BTT Octopus: (exact version, e.g. v1.1, STM32F446).
- LinuxCNC: version from the official RPi image.
- Remora: 1.1.0 – STM32 firmware for the Octopus from the 1.1.0 release, LinuxCNC component compiled from
remora-1.1.0/LinuxCNC/Components/Remora/remora.c
.
Why I switched from SKROn SKR 1.4 with Remora 0.1.0 I constantly get “bad SPI payload” and E‑STOP, even after improving the wiring (short cable, ground every second wire, shielded cable, common GND). In that old Remora version there are no
/
parameters, so I cannot slow down the SPI clock from the LinuxCNC side.Because of that I moved to a BTT Octopus with Remora 1.1.0, which gives me
and
so I can reduce SPI speed.
What happens on the Octopus
- SPI now looks stable: when I run the heater/wire only (no axis motion) I don’t get any “bad SPI payload” at all.
- I load the component like this:
loadrt remora SPI_clk_div=128 PRU_base_freq=40000
(Values can be changed, this is just what I’m testing now.)
- The motors move, in the correct direction, but I have two problems:
- Jog incremental overshoot
In incremental jog (for example 1 mm or 10 mm) when I press the jog “+” button and release it, the axis moves noticeably more than the requested increment.
It looks like Remora/stepgen continues to output steps for a short time after LinuxCNC has stopped the move.
- Joint following error after a few cm of travel
With conservative parameters (see JOINT_0 below) the axis can travel a few centimetres and then I get a joint following error.
With SKR + Remora 0.1.0, using the same HAL/INI values for SCALE, acceleration, max velocity and FERROR, I never had following errors – only the “bad SPI payload” issue.
Current section in my INI
[JOINT_0] TYPE = LINEAR HOME = 0 HOME_OFFSET = -10 MIN_LIMIT = -0.001 MAX_LIMIT = 450 MAX_VELOCITY = 10 MAX_ACCELERATION = 200 STEPGEN_MAXACCEL = 300 SCALE = (current value – was 50 originally) FERROR = 50 MIN_FERROR = 20 HOME_SEARCH_VEL = -1.5 HOME_LATCH_VEL = -0.5 HOME_IGNORE_LIMITS = YES HOME_SEQUENCE = 0
Relevant HAL fragment (Octopus / Remora connection)loadrt remora SPI_clk_div=128 PRU_base_freq=40000 # add remora and motion functions to threads addf remora.read servo-thread addf motion-command-handler servo-thread addf motion-controller servo-thread addf remora.update-freq servo-thread addf remora.write servo-thread # --- Joint 0 (X) --- setp remora.joint.0.scale [JOINT_0]SCALE setp remora.joint.0.maxaccel [JOINT_0]STEPGEN_MAXACCEL net xpos-cmd <= joint.0.motor-pos-cmd => remora.joint.0.pos-cmd net xpos-fb <= remora.joint.0.pos-fb => joint.0.motor-pos-fb net j0enable <= joint.0.amp-enable-out => remora.joint.0.enable
(If anything in this mapping looks obviously wrong, please point it out.)
What I have already tried
- Reduced , and a lot and increased /. This delays the following error but does not remove it.
- Tried to tune using G‑code (G91 / G0 X100 and measuring real travel). Even with reasonable SCALE values I still see overshoot in incremental jog: the axis moves clearly more than the selected increment.
- On SKR 1.4 with old Remora 0.1.0, with the same mechanical setup and same SCALE / accel / maxvel / FERROR, jogging and running G‑code worked fine (no following errors, no overshoot). The only issue there is the fixed, too‑fast SPI that causes “bad SPI payload”.
Questions
- Is this kind of jog overshoot in incremental mode a known configuration issue with Remora 1.1.0 + Octopus (for example related to PRU_base_freq, servo thread period, or some Remora parameter), or is it more likely that I have a clear mistake in my HAL/INI?
- What SPI / PRU settings do people successfully use on a BTT Octopus with Remora 1.x? Is and reasonable, or should I change these?
- Does anyone have a working LinuxCNC config (INI/HAL) for Remora 1.1.0 + Octopus in plain step/dir mode and would be willing to share the relevant line and joint settings?
- Are there any STM32/Octopus‑specific considerations in Remora (different expectations for SCALE, FERROR, etc.) when migrating from an LPC/SKR setup?
My main goals are:
- to get rid of the jog overshoot in incremental mode,
- to choose sane parameters so joint following error does not appear every few centimetres at reasonable speeds.
Any hints, working examples, or “known good” values for an Octopus setup would be very much appreciated.
my octopus config.txt:
{
"Board": "BIGTREETECH OCTOPUS",
"Modules": [
{ "Thread": "Servo", "Type": "Reset Pin", "Comment": "Reset pin", "Pin": "PC_15" },
{ "Thread": "Base", "Type": "SPI", "Comment": "SPI interface to Raspberry Pi", "CS Pin": "PA_4" },
{ "Thread": "Base", "Type": "Stepgen", "Comment": "X - Joint 0 stepgen", "Joint Number": 0, "Step Pin": "PF_13", "Direction Pin": "PF_12", "Enable Pin": "PF_14" },
{ "Thread": "Base", "Type": "Stepgen", "Comment": "Y - Joint 1 stepgen", "Joint Number": 1, "Step Pin": "PG_0", "Direction Pin": "PG_1", "Enable Pin": "PF_15" },
{ "Thread": "Base", "Type": "Stepgen", "Comment": "U - Joint 2 stepgen", "Joint Number": 2, "Step Pin": "PF_11", "Direction Pin": "PG_3", "Enable Pin": "PG_5" },
{ "Thread": "Base", "Type": "Stepgen", "Comment": "V - Joint 3 stepgen", "Joint Number": 3, "Step Pin": "PG_4", "Direction Pin": "PC_1", "Enable Pin": "PA_0" },
{ "Thread": "Base", "Type": "Stepgen", "Comment": "B - Joint 4 stepgen", "Joint Number": 4, "Step Pin": "PF_9", "Direction Pin": "PF_10", "Enable Pin": "PG_2" },
{
"Thread": "Servo",
"Type": "Digital Pin",
"Comment": "X limit",
"Pin": "PG_6",
"Mode": "Input",
"Data Bit": 0
},
{
"Thread": "Servo",
"Type": "Digital Pin",
"Comment": "Y limit",
"Pin": "PG_9",
"Mode": "Input",
"Data Bit": 1
},
{
"Thread": "Servo",
"Type": "Digital Pin",
"Comment": "U limit",
"Pin": "PG_10",
"Mode": "Input",
"Data Bit": 2
},
{
"Thread": "Servo",
"Type": "Digital Pin",
"Comment": "V limit",
"Pin": "PG_11",
"Mode": "Input",
"Data Bit": 3
},
{
"Thread": "Servo",
"Type": "Digital Pin",
"Comment": "B limit",
"Pin": "PG_12",
"Mode": "Input",
"Data Bit": 4
},
{
"Thread": "Servo",
"Type": "PWM",
"Comment": "PWM for heating",
"SP[i]": 5,
"PWM Pin": "PA_1",
"PWM Max": 256,
"Hardware PWM": "True",
"Variable Freq": "True",
"Period SP[i]": 1,
"Period us": 500
}
]
}
my .ini file:
[EMC]
MACHINE = Remora-XYUV
DEBUG = 0
VERSION = 1.1
[DISPLAY]
DISPLAY = axis
EDITOR = gedit
FOAM = 1
GEOMETRY = XY;UV
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
ARCDIVISION = 64
GRIDS = 10mm 20mm 50mm 100mm
MAX_FEED_OVERRIDE = 1.2
MIN_SPINDLE_OVERRIDE = 0.5
MAX_SPINDLE_OVERRIDE = 1.2
DEFAULT_LINEAR_VELOCITY = 2.50
MIN_LINEAR_VELOCITY = 0
MAX_LINEAR_VELOCITY = 25.00
DEFAULT_ANGULAR_VELOCITY = 36.00
MIN_ANGULAR_VELOCITY = 0
MAX_ANGULAR_VELOCITY = 45.00
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
PROGRAM_PREFIX = ~/linuxcnc/nc_files
OPEN_FILE = ./foam.ngc
INCREMENTS = 5mm 1mm .5mm .1mm .05mm .01mm .005mm
[KINS]
JOINTS = 5
KINEMATICS = trivkins coordinates=XYUVB
[FILTER]
PROGRAM_EXTENSION = .py Python Script
py = python
[TASK]
TASK = milltask
CYCLE_TIME = 0.010
[RS274NGC]
PARAMETER_FILE = linuxcnc.var
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 1.0
COMM_WAIT = 0.010
BASE_PERIOD = 100000
SERVO_PERIOD = 1000000
[HAL]
HALFILE = remora-xyuvb.hal
POSTGUI_HALFILE = postgui_call_list.hal
[TRAJ]
AXES = 5
COORDINATES = X Y U V B
LINEAR_UNITS = mm
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 2.50
MAX_LINEAR_VELOCITY = 25.00
NO_FORCE_HOMING = 1
[EMCIO]
EMCIO = io
CYCLE_TIME = 0.100
TOOL_TABLE = tool.tbl
EXTERNAL_OUTPUT_0 = motion.analog-out-00
[AXIS_X]
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
MIN_LIMIT = 10
MAX_LIMIT = 450
[JOINT_0]
TYPE = LINEAR
HOME = 0
HOME_OFFSET = -10
MIN_LIMIT = -0.001
MAX_LIMIT = 450
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
STEPGEN_MAXACCEL = 937.5
SCALE = 50
FERROR = 1
MIN_FERROR = .25
HOME_OFFSET = 0.000
HOME_SEARCH_VEL = -1.5
HOME_LATCH_VEL = -0.5
HOME_IGNORE_LIMITS = YES
HOME_SEQUENCE = 0
[AXIS_Y]
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
MIN_LIMIT = -0.001
MAX_LIMIT = 200.0
[JOINT_1]
TYPE = LINEAR
HOME = 0
HOME_OFFSET = -10
MIN_LIMIT = -0.001
MAX_LIMIT = 200.0
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
STEPGEN_MAXACCEL = 937.5
SCALE = -50
FERROR = 1
MIN_FERROR = .25
HOME_OFFSET = 0.000
HOME_SEARCH_VEL = -1.5
HOME_LATCH_VEL = -0.5
HOME_IGNORE_LIMITS = YES
HOME_SEQUENCE = 1
[AXIS_U]
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
MIN_LIMIT = 10
MAX_LIMIT = 450
[JOINT_2]
TYPE = LINEAR
HOME = 0
HOME_OFFSET = -10
MIN_LIMIT = -0.001
MAX_LIMIT = 450
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
STEPGEN_MAXACCEL = 937.5
SCALE = -50
FERROR = 1
MIN_FERROR = .25
HOME_OFFSET = 0.000
HOME_SEARCH_VEL = -1.5
HOME_LATCH_VEL = -0.5
HOME_IGNORE_LIMITS = YES
HOME_SEQUENCE = 0
[AXIS_V]
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
MIN_LIMIT = -0.001
MAX_LIMIT = 200.0
[JOINT_3]
TYPE = LINEAR
HOME = 0
HOME_OFFSET = -10
MIN_LIMIT = -0.001
MAX_LIMIT = 200.0
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
STEPGEN_MAXACCEL = 937.5
SCALE = -50
FERROR = 1
MIN_FERROR = .25
HOME_OFFSET = 0.000
HOME_SEARCH_VEL = -1.5
HOME_LATCH_VEL = -0.5
HOME_IGNORE_LIMITS = YES
HOME_SEQUENCE = 1
[AXIS_B]
MAX_VELOCITY = 23.75
MAX_ACCELERATION = 750.0
MIN_LIMIT = -0.001
MAX_LIMIT = 200.0
[JOINT_4]
TYPE = LINEAR
HOME = 0
HOME_OFFSET = 1
MIN_LIMIT = -0.001
MAX_LIMIT = 200.0
MAX_VELOCITY = 23.75
# MAX_ACCELERATION = 750.0
MAX_ACCELERATION = 500.0
# STEPGEN_MAXACCEL = 937.5
STEPGEN_MAXACCEL = 537.5
SCALE = 50
FERROR = 1
MIN_FERROR = .25
HOME_OFFSET = 0.000
HOME_SEARCH_VEL = 1
HOME_LATCH_VEL = 0.1
HOME_IGNORE_LIMITS = YES
HOME_SEQUENCE = 2
my .hal file:
# --- load the realtime components
loadrt [KINS]KINEMATICS
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=5
loadrt remora
# --- estop loopback, SPI comms enable and feedback
net user-enable-out <= iocontrol.0.user-enable-out => remora.SPI-enable
net user-request-enable <= iocontrol.0.user-request-enable => remora.SPI-reset
net remora-status <= remora.SPI-status => iocontrol.0.emc-enable-in
# --- add the remora and motion functions to threads
addf remora.read servo-thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
addf remora.update-freq servo-thread
addf remora.write servo-thread
# ------- Joint 0 (X / Tower 1) -------
setp remora.joint.0.scale [JOINT_0]SCALE
setp remora.joint.0.maxaccel [JOINT_0]STEPGEN_MAXACCEL
net xpos-cmd <= joint.0.motor-pos-cmd => remora.joint.0.pos-cmd
net j0pos-fb <= remora.joint.0.pos-fb => joint.0.motor-pos-fb
net j0enable <= joint.0.amp-enable-out => remora.joint.0.enable
net X-stop remora.input.0 => joint.0.home-sw-in joint.0.neg-lim-sw-in joint.0.pos-lim-sw-in
# ------- Joint 1 (Y / Tower 1) -------
setp remora.joint.1.scale [JOINT_1]SCALE
setp remora.joint.1.maxaccel [JOINT_1]STEPGEN_MAXACCEL
net ypos-cmd <= joint.1.motor-pos-cmd => remora.joint.1.pos-cmd
net j1pos-fb <= remora.joint.1.pos-fb => joint.1.motor-pos-fb
net j1enable <= joint.1.amp-enable-out => remora.joint.1.enable
net Y-min remora.input.1 => joint.1.home-sw-in joint.1.neg-lim-sw-in joint.1.pos-lim-sw-in
# ------- Joint 2 (U / Tower 2) -------
setp remora.joint.2.scale [JOINT_2]SCALE
setp remora.joint.2.maxaccel [JOINT_2]STEPGEN_MAXACCEL
net upos-cmd <= joint.2.motor-pos-cmd => remora.joint.2.pos-cmd
net j2pos-fb <= remora.joint.2.pos-fb => joint.2.motor-pos-fb
net j2enable <= joint.2.amp-enable-out => remora.joint.2.enable
net U-min remora.input.2 => joint.2.home-sw-in joint.2.neg-lim-sw-in joint.2.pos-lim-sw-in
# ------- Joint 3 (V / Tower 2) -------
setp remora.joint.3.scale [JOINT_3]SCALE
setp remora.joint.3.maxaccel [JOINT_3]STEPGEN_MAXACCEL
net vpos-cmd <= joint.3.motor-pos-cmd => remora.joint.3.pos-cmd
net j3pos-fb <= remora.joint.3.pos-fb => joint.3.motor-pos-fb
net j3enable <= joint.3.amp-enable-out => remora.joint.3.enable
net V-min remora.input.3 => joint.3.home-sw-in joint.3.neg-lim-sw-in joint.3.pos-lim-sw-in
# ------- Joint 4 (B / Rotary Table) -------
setp remora.joint.4.scale [JOINT_4]SCALE
setp remora.joint.4.maxaccel [JOINT_4]STEPGEN_MAXACCEL
net bpos-cmd <= joint.4.motor-pos-cmd => remora.joint.4.pos-cmd
net j4pos-fb <= remora.joint.4.pos-fb => joint.4.motor-pos-fb
net j4enable <= joint.4.amp-enable-out => remora.joint.4.enable
net B-min remora.input.4 => joint.4.home-sw-in joint.4.neg-lim-sw-in joint.4.pos-lim-sw-in
net heat_pwm motion.analog-out-00 => remora.SP.5