; =========================================================================== ; hardware.ini - what this machine IS. ; ; Written once when the tower is assembled. Changing anything here means the ; hardware itself changed: a different board, a sensor fitted or removed, a ; cable moved to another port. Operational settings you tune to get better ; images - capture interval, camera profiles, scan grid, output paths - live in ; config.ini instead, and so does calibration, which is redone from time to time. ; ; WHERE THIS FILE GOES ; /etc/fire_gimbal_control/hardware.ini ; ; That is beside credentials.env, and it is deliberately OUTSIDE the directory ; deploy.sh rsyncs: a deploy cannot overwrite or delete what it never touches. ; The program looks, in order, at: ; --hardware | $FGC_HARDWARE | /etc/... | beside config.ini ; ; Keys here override the same keys in config.ini, and any that are still set in ; both are named in a warning at startup so the stale copy can be deleted. ; =========================================================================== ; --- Which computer ------------------------------------------------------- [Board] ; Free-form, but keep it matching a directory under hardware/ so the setup kit ; for this board is easy to find. model = lattepanda-3-delta ; PlatformIO env used to build the motor firmware for this board's MCU. ; lattepanda-3-delta / sigma -> leonardo (ATmega32U4, 5V logic) ; lattepanda-iota -> iota_rp2040 (RP2040, 3.3V logic) firmware_env = leonardo ; --- What is fitted ------------------------------------------------------- ; This is a DECLARATION, and its whole purpose is that startup can compare it ; with what it actually finds. The program already copes gracefully when a part ; is missing - the pitch axis, the IMU, the ambient sensor - which is correct for ; a rig built without them, and indistinguishable from a fault on a rig that has ; them. Saying what was assembled is what tells those two apart. [Hardware] ; Axes this gimbal has. A yaw-only rig says: axes = yaw axes = yaw, pitch ; Orientation sensor: a model name, or 'none'. Most of the fleet has none. ; ; Naming a model here is what ENABLES it - there is no second key to remember. ; [Features] enable_imu still exists for towers with no hardware.ini, but where ; this file declares a sensor the declaration wins, and a flag contradicting it ; is warned about and ignored. imu = none ; Ambient temperature/humidity sensor: a model name, or 'none'. Same rule. env = sht41 ; The [Camera.] blocks expected to be present and found. cameras = rgb ; ; What happens when this does not match the rig: ; declared but absent -> warned about by name, and with [Features] ; strict_presence = 1 in config.ini the program refuses ; to start (exit 3). --degraded starts it anyway. ; found but undeclared -> warned about as a stale file. Never fatal. ; A tower with no hardware.ini at all is never reconciled, whatever ; strict_presence says: gaining this file must not change how a tower behaves. ; --- Where to find it ----------------------------------------------------- ; Device bindings. These follow the hardware, not the tower, so they belong here ; rather than in config.ini. [Serial] ; The motor controller MCU. Prefer the stable by-id symlink over /dev/ttyACM0, ; which is assigned in enumeration order and moves when USB devices change. ; Leonardo : /dev/serial/by-id/usb-Arduino_LLC_Arduino_Leonardo-if00 device = /dev/serial/by-id/usb-Arduino_LLC_Arduino_Leonardo-if00 baud = 115200 [IMU] ; Only read when [Hardware] imu is not 'none'. On the LattePanda 3 Delta the MTi ; is on the RS-232 header, which is a hardware UART: a stable /dev/ttyS* node, ; NOT a USB device and NOT /dev/ttyUSB0-3 (those are the modem). device = /dev/ttyS0 [Env] ; Only read when [Hardware] env is not 'none'. This is the board's OWN native ; I2C bus, not the motor controller's serial link. The bus number varies by ; board - it is /dev/i2c-2 on the 3 Delta, not the /dev/i2c-1 default. ; ; Two traps when finding it: i2cdetect false-negatives on the SHT4x (probe with ; a real measurement instead), and an SMBus-only adapter can never work at all ; (i2cdetect -F N reports 'I2C = no'). i2c_device = /dev/i2c-2 i2c_addr = 0x44 ; --- What it is made of --------------------------------------------------- ; The drivetrain, one block per axis. A different motor, gearbox or driver board ; changes these; nothing an operator tunes belongs here. [Motor.yaw] ; Sense resistor fitted to THIS axis's TMC5160 board. It is what makes the ; milliamp figures below mean anything, which is why the host - not the firmware - ; converts them into GLOBALSCALER/IRUN register values and sends those. r_sense_ohm = 0.075 ; Milliamps RMS per phase. run_current_ma is normal motion; homing_current_ma ; applies ONLY while hunting for an endstop. ; ; The two differ when the stop cannot survive full torque. On the IOTA tower the ; endstop is a screw head meeting another screw head, and the high gear ratio let ; the motor shear one past the other - it ran 1.8 turns past the stop without the ; encoder ever falling behind. At 189 mA it homes against the same screw cleanly. ; ; The startup log prints what the registers ACTUALLY deliver, which is not ; always what you asked for; believe the log, not this file. run_current_ma = 756 homing_current_ma = 200 ; Mechanical angle between the hard endstops. A NAMEPLATE FACT: homing measures ; the travel in counts, and dividing by this yields [Motor] yaw_counts_per_deg in ; config.ini, offered for saving at the y/n prompt. ; ; Deliberately a different key, in a different file, from counts_per_deg itself: ; hardware.ini is merged OVER config.ini and wins, so sharing a key would ; silently discard every calibration the save path writes back. ; ; ROUGH until somebody measures it. Every bearing inherits its error ; proportionally, until 'gimbal heading setup' supersedes it with a landmark fit. travel_deg = 340 ; Production move speed, IN DEGREES PER SECOND - not VMAX. ; ; A register value is not portable: VMAX 30000 is 21.8 deg/s on the Delta fleet ; and 6.0 deg/s on the IOTA, because their gear ratios differ by 3.6x. Both were ; carrying the same literal, which is how two towers ended up sweeping at ; completely different speeds while their configs looked identical. ; ; The host converts through yaw_counts_per_deg and sends SPEED after each home, ; so this follows the calibration automatically. An axis whose scale is not ; trustworthy is left on the firmware's default and the reason is logged. scan_speed_deg_s = 8.0 ; The other two motions, also in deg/s. Both happen BEFORE the first home, so ; they cannot use the counts_per_deg that homing derives - they convert through ; the scale this file implies (steps_per_rev / travel_deg), which on the IOTA ; agrees with the measured one to 0.25%. homing_speed_deg_s = 2.0 center_speed_deg_s = 6.0 ; --- Told to the firmware, which holds none of it itself -------------------- ; The config handshake (docs/configuration.md): the firmware asks with NEED and ; these answer it. A key missing here leaves that axis in NEEDCFG, refusing to ; move, with the missing name logged - deliberately, because a drivetrain value ; guessed by the firmware is the duplication this removes. ; ; Expected full mechanical travel, IN COUNTS. Measured, not derived: it is the ; only guard against a PHANTOM endstop - too little homing current and the motor ; stalls on ordinary friction, trips the same latch a real stop does, and the ; bogus limit is accepted. steps_per_rev = 1210778 ; |XACTUAL - XENC| that means "position untrustworthy". Re-measure whenever the ; homing current changes: the free-running gap is coupled to it. enc_deviation = 1500 ; TMC SW_MODE - physical endstop switches on REFL/REFR. Yaw on this rig homes by ; StallGuard with no switches (0); an axis with real switches sets the bits. sw_mode = 0 ; Is this axis's encoder aligned to XACTUAL and usable for hold and DIAG? has_encoder = true [Camera.rgb] ; The serial of the physical camera fitted to this tower. A USB DEV_ id, or a ; GigE IP address. id = DEV_1AB22C049CD1